Amazon CloudWatch Dashboards: Build, Share, and Manage as Code
A CloudWatch dashboard is a configurable screen that combines metric graphs, alarm states, and log query results into a single view. Open it at the start of a shift or during an incident and immediately see the state of your system. This page explains what dashboards are, when to use them, how to build and share them, and how to manage them as version-controlled code.
CloudWatch dashboards, simply explained
Analogy
Think of a CloudWatch dashboard like the instrument panel in a car. You could check fuel level, tyre pressure, and engine temperature by visiting three separate sensors under the hood, or you could glance at the dashboard and see all of it at once. CloudWatch dashboards work the same way: instead of navigating between multiple CloudWatch pages, you arrange all the signals that matter for a service onto one screen.
Each dashboard is made up of widgets (graphs, number readouts, alarm status panels, and log tables) arranged on a 24-column grid. You decide what to show, where to place it, and what time range it covers. The underlying data comes from CloudWatch metrics, which your AWS services publish automatically.
A dashboard is not an alarm system. That is what CloudWatch Alarms are for. It is not a log search tool. That is CloudWatch Logs. It is not a request tracer. That is AWS X-Ray. A dashboard is the visualization layer that brings all those signals together in one place. For the full picture of what CloudWatch covers, see the Amazon CloudWatch overview.
What CloudWatch dashboards are best for
- Incident triage. When an alert fires, open one dashboard to see error rate, latency, alarm state, and queue depth together instead of clicking through five separate pages.
- Service health overview. A persistent screen showing whether a production service is healthy, shared with the whole team so everyone has the same situational awareness at all times.
- Shared operational visibility. Stakeholders and support teams can see system status without an AWS login, using public sharing or a cross-account configuration.
- SLA and SLO tracking. A dedicated dashboard showing availability, error rate, and latency against your targets, reviewed daily or at weekly team meetings.
- Multi-signal correlation. Combine metrics from Lambda, RDS, SQS, and API Gateway in one view so you can see when a database slowdown is causing Lambda timeouts upstream.
- On-call handoff. A consistent screen that every on-call engineer opens at the start of a shift to assess system state before anything goes wrong.
CloudWatch dashboards vs alarms vs logs vs X-Ray
Each CloudWatch tool solves a different problem. Choosing the right one depends on whether you are trying to see what is happening, detect when something went wrong, search for what caused it, or trace where it broke.
| Tool | What it does | When to use it |
|---|---|---|
| CloudWatch Dashboards | Visual display of metrics, alarm states, and log queries on one screen | Incident triage, service health overview, stakeholder visibility |
| CloudWatch Alarms | Monitors a metric threshold and fires a notification or action when breached | Detecting problems automatically, triggering auto-scaling, alerting on-call |
| CloudWatch Logs | Stores, searches, and queries raw log events from your services | Finding the specific error message, filtering events by pattern or time window |
| AWS X-Ray | Traces individual requests through distributed services end to end | Finding which service caused a latency spike, root-cause analysis for errors |
In practice, these tools work together. A dashboard shows you that Lambda errors are spiking. You open CloudWatch Logs to find the specific error message. You use distributed tracing to follow the failing request through downstream services and find the root cause. The dashboard is where you start; the other tools are where you dig.
Automatic dashboards vs custom dashboards
Automatic dashboards
AWS generates automatic dashboards for services you are actively using. In the CloudWatch console, navigate to Dashboards and look for the Automatic dashboards section. You will see pre-built dashboards for services like EC2, Lambda, RDS, and API Gateway with AWS-recommended metrics already configured. These are free, require zero setup, and are a useful starting point when you first set up monitoring.
The limitation: automatic dashboards cannot be customized. You cannot add your own metrics, change the layout, or mix signals from multiple services on the same screen.
Custom dashboards
Custom dashboards are what most teams build for production services. You choose every widget, metric, and layout position. You can combine signals from multiple AWS services, add annotations, use variables, and share them with specific people or the public. The first three are free per account; beyond that, a small monthly fee applies per dashboard.
The rest of this page covers custom dashboards.
How CloudWatch dashboards work
Widgets and the grid
A dashboard is a collection of widgets arranged on a 24-column grid. Each widget has an
x position, y position, width, and height in grid units. A full-width widget has
width: 24. Two side-by-side widgets each have width: 12.
The grid expands vertically as you add more rows. There is no fixed height limit.
Time ranges and refresh
Every dashboard has a time range selector in the top-right corner. Use relative time ranges (last 3 hours, last 7 days) rather than fixed dates so the dashboard always shows current data without manual adjustment. The default refresh rate is one minute. During an incident, you can drop it to 10 seconds for near-real-time updates.
Annotations
Annotations are horizontal reference lines drawn across a metric graph at a value you specify. Add one at your SLA threshold or normal operating range so team members can immediately see whether a metric is within bounds without having to remember the numbers.
Variables
Dashboard variables add a dropdown to the dashboard that filters all widget metrics by a chosen dimension value. Instead of building a separate dashboard per Lambda function or per ECS cluster, you build one dashboard and select the resource from the dropdown. See the variables section below for a JSON example.
Cross-region and cross-account visibility
If you run services across multiple AWS accounts, CloudWatch cross-account observability lets you aggregate metrics and alarms from source accounts into a single monitoring account. A dashboard in the monitoring account can then display data from all of your accounts in one view. This requires configuration in both the monitoring account and the source accounts before metrics from different accounts appear in the same dashboard.
Widget types
CloudWatch dashboards support eight widget types. The alarm status and Logs Insights table widgets are the two most frequently overlooked, and also two of the most useful for on-call dashboards.
| Widget type | What it shows | Best used for |
|---|---|---|
| Line graph | Time-series metric values as continuous lines | Trends over time: CPU, latency, request rate, error rate |
| Stacked area | Multiple metrics stacked to show composition | Traffic breakdown by endpoint, errors by Lambda function |
| Number | Single current value with optional sparkline | Error count, active connections, queue depth at a glance |
| Gauge | Current value within a min/max arc | Utilization percentages where 0–100% context matters |
| Bar chart | Metric values compared across dimension values | Errors by Lambda function name, invocations by region |
| Alarm status | Current state (OK / ALARM / INSUFFICIENT) for one or more alarms | Top of every on-call dashboard so you see what is broken first |
| Logs Insights table | Results of a saved Logs Insights query as a table | Recent errors, slow queries, or any log-derived data on the same screen |
| Text | Markdown text block | Section headings, runbook links, on-call escalation instructions |
The most effective on-call dashboard layout puts alarm status widgets at the top (what is broken right now), followed by line graphs for the metrics that explain why those alarms are firing, followed by a Logs Insights table showing the most recent errors.
How to create a CloudWatch dashboard in the console
Before you start adding widgets, decide three things:
- Scope. Is this dashboard for one service, one team, or one environment? Avoid mixing unrelated services on the same screen.
- Primary audience. On-call engineers need alarm status and error details. Stakeholders need availability and latency numbers. Build for one audience first; create a second dashboard if you need to serve both.
- Most important signal. That signal goes in the top-left. Everything else flows from it.
To create the dashboard in the console:
- Navigate to CloudWatch › Dashboards › Create dashboard.
- Give it a name tied to the service or team (e.g.,
prod-order-service). - Click “Add widget” and choose a widget type.
- For metric widgets: select the namespace (e.g.,
AWS/Lambda), then the dimensions (e.g.,FunctionName = process-orders), then check the metrics to graph. - Switch to “Graphed metrics” to add metric math expressions (e.g., error rate as a percentage of invocations).
- Click “Create widget” and drag it into position on the grid.
- Repeat for remaining widgets, then save the dashboard.
The console makes it easy to keep clicking “Add widget” without a clear plan. A dashboard built by browsing available metrics will accumulate graphs that each make sense in isolation but are confusing together during an incident. Decide scope and audience before you add your first widget.
The console is useful for initial exploration, but for dashboards that need to stay consistent across environments or survive account changes, use the JSON approach below.
Dashboards as code
Dashboard JSON structure
Every CloudWatch dashboard is defined as a JSON document. You can export this JSON from
the console (Actions › View/edit source) or write it from scratch. The top-level
structure is a widgets array where each entry specifies its type, grid
position, and display properties.
{
"widgets": [
{
"type": "metric",
"x": 0,
"y": 0,
"width": 12,
"height": 6,
"properties": {
"title": "Lambda Errors and Invocations",
"view": "timeSeries",
"stacked": false,
"period": 60,
"stat": "Sum",
"metrics": [
["AWS/Lambda", "Errors", "FunctionName", "process-orders"],
["AWS/Lambda", "Invocations", "FunctionName", "process-orders"]
],
"region": "us-east-1",
"annotations": {
"horizontal": [
{"label": "Error threshold", "value": 10, "color": "#d62728"}
]
}
}
},
{
"type": "alarm",
"x": 12,
"y": 0,
"width": 6,
"height": 6,
"properties": {
"title": "Alarm Status",
"alarms": [
"arn:aws:cloudwatch:us-east-1:123456789012:alarm:Lambda-HighErrors",
"arn:aws:cloudwatch:us-east-1:123456789012:alarm:Lambda-HighDuration"
]
}
},
{
"type": "log",
"x": 0,
"y": 6,
"width": 24,
"height": 6,
"properties": {
"title": "Recent Lambda Errors",
"query": "SOURCE '/aws/lambda/process-orders' | fields @timestamp, @message | filter @message like /ERROR/ | sort @timestamp desc | limit 20",
"region": "us-east-1",
"view": "table"
}
},
{
"type": "text",
"x": 0,
"y": 12,
"width": 24,
"height": 2,
"properties": {
"markdown": "## Order Service Dashboard\nMonitors the `process-orders` Lambda function. [Runbook](https://wiki.example.com/runbooks/order-service)"
}
}
]
}The grid uses 24 columns. x and y mark the top-left corner of
each widget; width and height are in grid units. Two half-width
widgets side by side each use width: 12. A full-width row uses
width: 24.
CLI commands
# Create or replace a dashboard from a JSON file
aws cloudwatch put-dashboard \
--dashboard-name prod-order-service \
--dashboard-body file://dashboard.json
# List all dashboards in the account
aws cloudwatch list-dashboards \
--query 'DashboardEntries[*].{Name:DashboardName,Modified:LastModified}' \
--output table
# Export the JSON for an existing dashboard
aws cloudwatch get-dashboard \
--dashboard-name prod-order-service \
--query 'DashboardBody' \
--output text
# Delete one or more dashboards
aws cloudwatch delete-dashboards \
--dashboard-names prod-order-service old-dashboard-v1put-dashboard is idempotent: calling it again with the same name replaces
the existing dashboard. This makes it safe to run repeatedly from a deployment pipeline.
Storing dashboard JSON in version control
Treat dashboard JSON the same way you treat infrastructure code. Store it in source control alongside the service it monitors, review changes in pull requests, and apply it during deployment using the CLI. The benefits are practical:
- Dashboards survive accidental deletion and can be restored in seconds.
- Changes are reviewable, attributable, and reversible.
- New environments (staging, production) get identical dashboards automatically.
- Onboarding engineers can see which signals the team considers most important, without asking.
A common pattern is a dashboards/ directory in the service repository with
one JSON file per dashboard, applied by the CI/CD pipeline on every deploy. Infrastructure
tools like Terraform can also manage CloudWatch dashboards using the
aws_cloudwatch_dashboard resource if you are already managing infrastructure
that way.
Dashboard variables: one dashboard for many resources
Dashboard variables add a dropdown selector to the top of a dashboard that filters all widget metrics by a chosen dimension value. Instead of one dashboard per Lambda function, you build one dashboard and pick the function from a dropdown. The variable populates automatically from CloudWatch metric dimensions, so new resources appear in the dropdown without any dashboard changes.
{
"variables": [
{
"type": "property",
"property": "FunctionName",
"inputType": "select",
"id": "FunctionName",
"label": "Function",
"visible": true,
"search": {
"expression": "SEARCH('{AWS/Lambda,FunctionName}', 'FunctionName')",
"populateFrom": "FunctionName"
}
}
],
"widgets": [
{
"type": "metric",
"properties": {
"metrics": [
["AWS/Lambda", "Errors", "FunctionName", "${FunctionName}"],
["AWS/Lambda", "Duration", "FunctionName", "${FunctionName}"]
],
"title": "Lambda: ${FunctionName}"
}
}
]
}This pattern reduces the number of dashboards you need to maintain. It is especially useful for teams running many similar services (microservices, Lambda functions, or ECS tasks) where each service has the same key metrics but different dimension values.
Example dashboard layouts by workload
The right layout depends on the workload. These are practical starting points. Each row suggests what to show first (top of the dashboard), the key metrics to include, and what to avoid loading the dashboard with.
| Workload | Show first | Key metrics | Avoid |
|---|---|---|---|
| Lambda / serverless API | Alarm status + error rate | Errors, Duration p99, Throttles, ConcurrentExecutions | Combining every function on one screen without a variable filter |
| ECS or EKS service | Running task or pod count | CPU utilization, memory utilization, task count, ALB 5xx errors | Mixing unrelated services or namespaces in the same view |
| RDS-backed application | Database connections + query latency | DatabaseConnections, ReadLatency, WriteLatency, FreeStorageSpace | Low-level OS metrics that belong in a separate infrastructure dashboard |
| SQS queue worker | Queue depth (messages visible) | ApproximateNumberOfMessagesVisible, AgeOfOldestMessage, NumberOfMessagesSent | Tracking every queue without filtering by team or service boundary |
For any of these workloads, consider adding a CloudWatch Synthetics canary SuccessPercent metric to the dashboard. It gives you external uptime visibility alongside your internal metrics. It confirms whether a customer-facing endpoint is actually reachable, not just internally healthy.
Sharing and access
CloudWatch offers three ways to share a dashboard, each with different access requirements and security implications.
Share within the account
Any IAM user or role with the cloudwatch:GetDashboard permission can view
dashboards in the same account. This is the default mode for internal teams. No additional
configuration is required beyond standard IAM permissions.
Share publicly via link
CloudWatch can generate a public URL for a dashboard. Anyone with that URL can view it without AWS credentials. The dashboard is read-only and cannot be modified by external viewers.
To enable public sharing: open the dashboard in the console, click Actions › Share dashboard, then select “Share your dashboard publicly.” AWS generates a shareable URL.
Public sharing exposes raw metric values to anyone with the URL. This can include customer counts, revenue proxies, request volumes, or infrastructure topology depending on what the dashboard shows. Only share dashboards publicly when the metrics are genuinely non-sensitive. Never publicly share dashboards that reveal business-sensitive signals or data subject to compliance requirements.
Cross-account and cross-region dashboards
If you run workloads in multiple AWS accounts, CloudWatch cross-account observability lets you pull metrics and alarms from source accounts into a central monitoring account. A dashboard in the monitoring account can then display data from all your accounts in one view. This requires a sharing policy configured on each source account.
# On the source account: grant the monitoring account read access
aws cloudwatch put-dashboard-sharing-policy \
--policy-type "ALLOW_SPECIFIC_ACCOUNTS" \
--policy-json '{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Principal": {"AWS": "arn:aws:iam::MONITORING_ACCOUNT_ID:root"},"Action": "cloudwatch:GetDashboard"}]}'When to use CloudWatch dashboards
Dashboards add the most value in these specific situations:
On-call and incident response. A well-built dashboard is the first screen an on-call engineer should open when an alert fires. It surfaces the most useful signals for triage without requiring any navigation. See incident response with monitoring for how dashboards fit into a broader response workflow.
Production service overview. Each team should have a persistent dashboard for each production service they own. It becomes the default answer to “is it healthy?” without requiring anyone to open the CloudWatch metrics explorer.
Executive and stakeholder visibility. A simplified dashboard showing availability and error rate, shared via public link, keeps leadership informed during incidents without pulling engineers into status update meetings.
Multi-account monitoring. With cross-account observability configured, one dashboard can show the health of services across dev, staging, and production accounts in a single view.
Recurring troubleshooting patterns. If your team regularly investigates the same type of issue (SQS lag causing downstream timeouts, for example), build a dashboard purpose-built for that investigation. Reusing it saves time and reduces the chance of missing a signal. See debugging production systems for more on building systematic investigative workflows.
CloudWatch dashboards refresh every minute by default. During an active incident, set the refresh rate to 10 seconds for near-real-time monitoring. More frequent refreshes generate more API calls, which adds cost if many team members are simultaneously viewing a dashboard with many widgets.
Common beginner mistakes
- Too many metrics on one dashboard. A dashboard with 40 graphs is overwhelming and hard to scan during an incident. Limit each dashboard to the 8 to 12 most important signals for its scope. Build separate investigation dashboards for detailed analysis.
- Organizing by AWS service instead of business service. A dashboard called “Lambda functions” listing 20 unrelated functions is not useful when something breaks. A dashboard called “Order Service” showing Lambda errors, API Gateway latency, SQS queue depth, and RDS connections for one service is highly useful. Organize by team or product ownership, not by AWS resource type.
- Not storing dashboards in version control. Building dashboards manually in the console and then losing them after an accidental deletion is a preventable problem. Export dashboard JSON and commit it to source control. Apply it as part of your deployment pipeline.
- Using absolute time ranges. A dashboard with a hardcoded range like “March 15 to March 18” becomes useless after that window passes. Use relative time ranges (last 3 hours, last 7 days) so the dashboard always shows current data.
- Public sharing of sensitive metrics. Public dashboard URLs expose metric values to anyone with the link. Never share dashboards publicly that contain customer counts, revenue signals, or any data regulated under privacy laws or that could reveal business-sensitive information.
- Building dashboards only after incidents. A dashboard built during an incident, while you are already under pressure, will be rushed and incomplete. Build dashboards proactively for every production service before you need them. Include dashboard creation as a requirement in your service launch checklist.
Summary
- CloudWatch dashboards combine metric graphs, alarm status, Logs Insights results, and text widgets on a 24-column grid.
- There are eight widget types. Alarm status and Logs Insights table are the two most commonly overlooked, and also two of the most valuable for on-call dashboards.
- Every dashboard is JSON. Store it in source control and deploy it programmatically so dashboards are reproducible and recoverable.
- Put alarm status widgets at the top so the first thing you see during an incident is what is broken, not a graph you have to interpret.
- Use dashboard variables to build one parameterized dashboard instead of a separate dashboard per resource.
- Public dashboard sharing exposes raw metric data to anyone with the URL. Only use it for genuinely non-sensitive operational metrics.
- Organize dashboards by service or team ownership, not by AWS service type.
Frequently asked questions
What can you put on a CloudWatch dashboard?
CloudWatch dashboards support eight widget types: line graphs, stacked area graphs, number displays, gauge dials, bar charts, alarm status widgets, Logs Insights query tables, and Markdown text blocks. You can mix and match these freely to build a screen that shows everything your on-call team needs at a glance.
Can you share a CloudWatch dashboard without AWS access?
Yes. CloudWatch supports public sharing via a generated URL. Anyone with the link can view the dashboard without AWS credentials. The dashboard is read-only. Only use this for dashboards with non-sensitive metrics, since it exposes metric data to anyone who has the URL.
What is the difference between a CloudWatch dashboard and a CloudWatch alarm?
A dashboard is a visual display showing metric graphs, alarm states, and log query results on one screen. An alarm is an automated monitor that evaluates a metric against a threshold and fires a notification when breached. Dashboards help you understand what is happening; alarms tell you when something went wrong.
Can you manage CloudWatch dashboards as code?
Yes. Every CloudWatch dashboard is defined as a JSON document. You can deploy dashboards with the AWS CLI using aws cloudwatch put-dashboard, store the JSON in source control, and apply it as part of your deployment pipeline, making dashboards reproducible and reviewable like any other infrastructure change.
How many CloudWatch dashboards are free?
The first three dashboards per account are included in the AWS Free Tier. Beyond that, each additional dashboard is billed at a small monthly rate. Check the current AWS CloudWatch pricing page for up-to-date costs, as pricing can change.