
5 Automated CloudWatch Dashboards Every Operations Team Needs
Build five automated AWS CloudWatch dashboards for infrastructure, applications, Lambda, RDS, and incident response using IaC.
5 Automated CloudWatch Dashboards Every Operations Team Needs
Your monitoring problem is probably not a lack of metrics.
It is a lack of answers.
AWS can give an operations team thousands of data points. CPU utilization. Lambda errors. Target response time. Database connections. Disk queues. Throttles. Logs.
Then production breaks, and someone spends the next ten minutes opening tabs.
That is not observability.
That is archaeology.
A useful CloudWatch dashboard should shorten the distance between “something is wrong” and “here is where to look.”
And if that dashboard matters in production, it should not depend on somebody remembering how they built it six months ago.
It should be code.

A simplified CloudWatch observability flow showing how AWS service metrics move from EC2, ALB, Lambda, and RDS into dashboards and alarms that help operators make faster decisions.
This article covers five CloudWatch dashboards worth automating:
- Infrastructure Health
- Application Performance
- Serverless Operations
- Database Health
- Incident Command
Each one follows the same pattern: what to visualize, how to automate it, what to alarm on, and what the graphs are trying to tell you.
Before You Build: Three Things to Get Right
1. Treat dashboards as infrastructure
CloudWatch dashboards can be created with CloudFormation, Terraform, CDK, the AWS CLI, APIs, or SDKs.
For deployment roles,
cloudwatch:PutDashboard is the key permission for creating or updating dashboards. Creating alarms requires permissions such as cloudwatch:PutMetricAlarm; publishing your own custom metrics requires cloudwatch:PutMetricData.Keep the dashboard definition in the same repository as the service or infrastructure it monitors.
Your ideal workflow is:
1
2
3
4
5
6
7
Git commit
↓
CI/CD
↓
Infrastructure
+ Dashboard
+ AlarmsObservability should ship with the system.
2. Use a naming convention
There is an easy CloudWatch detail to miss: dashboards are global within an AWS account, not Region-specific. A dashboard name therefore needs enough context to avoid collisions.
A useful convention is:
1
<environment>-<region>-<service>-<purpose>For example:
1
2
3
prod-us-east-1-checkout-application
prod-us-east-1-checkout-database
staging-eu-west-1-orders-serverlessFor organizations with many AWS accounts, consider a central monitoring account. CloudWatch supports cross-account observability and dashboards that combine metrics and logs from multiple accounts and Regions.
3. Know which metrics exist by default
EC2 gives you useful infrastructure metrics out of the box, but guest operating-system memory and filesystem usage are not standard EC2 metrics.
To collect values such as memory utilization and filesystem disk usage, install and configure the CloudWatch agent. Those additional metrics are commonly published under the
CWAgent namespace. AWS's EC2 health guidance includes agent configuration for memory, disk, swap, disk I/O, and CPU data.That distinction matters. A dashboard that promises memory graphs without explaining the agent is not deployable documentation.
1. Infrastructure Health Dashboard
The infrastructure dashboard answers the first question during an incident:
Is the platform itself under pressure?
For EC2-heavy systems, start with:
CPUUtilization- EC2 status checks
- Network activity
- EBS read/write activity
- EBS queue pressure
- Auto Scaling capacity
- Healthy/unhealthy load-balancer targets
- Memory and filesystem usage through the CloudWatch agent

Infrastructure health dashboard mockup showing CPU utilization, memory, EBS queue, network throughput, healthy targets, and Auto Scaling capacity.
AWS recommends several EBS metrics for operational visibility, including read/write operations, queue length, throughput percentage, and burst balance.
The goal is not to create a wall of graphs.
It is to reveal saturation.
Automate it
Here is a small Terraform example that puts an EC2 metric and an agent-provided memory metric on the same dashboard:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
resource "aws_cloudwatch_dashboard" "infra" {
dashboard_name = "${var.environment}-${var.region}-infra-health"
dashboard_body = jsonencode({
widgets = [
{
type = "metric"
x = 0
y = 0
width = 12
height = 6
properties = {
title = "EC2 CPU Utilization"
region = var.region
period = 60
metrics = [
[
"AWS/EC2",
"CPUUtilization",
"InstanceId",
var.instance_id
]
]
stat = "Average"
}
},
{
type = "metric"
x = 12
y = 0
width = 12
height = 6
properties = {
title = "Host Memory"
region = var.region
period = 60
metrics = [
[
"CWAgent",
"mem_used_percent",
"InstanceId",
var.instance_id
]
]
stat = "Average"
}
}
]
})
}Terraform's
aws_cloudwatch_dashboard resource accepts the dashboard body as JSON, which makes the same underlying widget model usable whether you prefer Terraform or native AWS tooling.Alarm starting points
These are examples to baseline against your own workloads:
- EC2 status check failure: >= 1
- Sustained CPU: >80% for 10 minutes
- Host memory: >85% for 10 minutes
- Healthy target count: alert when it falls below the capacity needed to serve normal traffic
Do not cargo-cult the numbers. A batch worker running at 95% CPU may be healthy. A latency-sensitive API at the same utilization may be minutes away from pain.
What to look for
CPU up + network up + request volume up
Likely traffic-driven pressure. Check whether scaling is responding quickly enough.
Likely traffic-driven pressure. Check whether scaling is responding quickly enough.
Memory up while CPU stays normal
Look for memory leaks, cache growth, JVM or runtime pressure, or a workload whose bottleneck is not CPU.
Look for memory leaks, cache growth, JVM or runtime pressure, or a workload whose bottleneck is not CPU.
EBS queue pressure + application latency up
Storage may be the constraint even though EC2 CPU looks healthy.
Storage may be the constraint even though EC2 CPU looks healthy.
The lesson: resource pressure is useful only when correlated with customer-facing symptoms.
2. Application Performance Dashboard
Infrastructure can be green while users are having a terrible day.
Your application dashboard should answer:
What is the customer experiencing?
For an Application Load Balancer, useful CloudWatch metrics include:
RequestCountTargetResponseTimeHTTPCode_Target_5XX_CountHTTPCode_ELB_5XX_CountHealthyHostCountUnHealthyHostCount
AWS documents
Sum as the meaningful statistic for request and target HTTP response-code counts, while HealthyHostCount is typically examined with statistics such as Average, Minimum, or Maximum.One graph tells you what happened.
Several related graphs tell you why.
Show error rate, not just error count

A simplified application performance dashboard showing request volume, P95 latency, 5XX error rate, and target health so operators can quickly see how rising traffic can lead to slower responses and more application errors.
“500 errors” means almost nothing without traffic context.
500 errors from 1,000 requests is a crisis.
500 errors from 50 million requests is a different conversation.
CloudWatch metric math lets you derive a time series from multiple metrics. AWS even uses dividing errors by invocations as an example of creating an error-rate metric.
For an ALB, a widget can calculate target 5XX percentage like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
"type": "metric",
"width": 12,
"height": 6,
"properties": {
"title": "Target 5XX Error Rate",
"region": "us-east-1",
"metrics": [
[
"AWS/ApplicationELB",
"HTTPCode_Target_5XX_Count",
"LoadBalancer",
"app/prod-alb/abc123",
{"id": "errors", "stat": "Sum", "visible": false}
],
[
"AWS/ApplicationELB",
"RequestCount",
"LoadBalancer",
"app/prod-alb/abc123",
{"id": "requests", "stat": "Sum", "visible": false}
],
[
{
"expression": "IF(requests>0,100*errors/requests,0)",
"label": "5XX %",
"id": "errorRate"
}
]
],
"period": 60
}
}Now your dashboard is showing impact, not just activity.
Alarm starting points
Examples:
- Target 5XX rate: >1% for 5 minutes
- P95 latency: alarm relative to your service SLO
- Unhealthy targets: >0 for critical services, or below your minimum safe capacity
- Sudden request-rate change: compare with historical baseline or anomaly detection
The SLO is more important than a generic threshold.
“Latency is high” is vague.
“Checkout P95 breached the 750 ms objective for five minutes” is operational.
What to look for
Request volume up + latency up + healthy hosts stable
Your targets may simply be saturated.
Your targets may simply be saturated.
5XX rate up + traffic flat
Suspect a code change, dependency failure, configuration problem, or bad deployment.
Suspect a code change, dependency failure, configuration problem, or bad deployment.
Healthy hosts down + ALB 5XX up
Start with target health and application startup/readiness failures.
Start with target health and application startup/readiness failures.
A good application dashboard does not ask, “Which graph looks scary?”
It asks, “What changed at the same time?”
3. Serverless Operations Dashboard
Serverless removes servers from your to-do list.
It does not remove operations.
For Lambda, start with:
InvocationsErrorsDurationThrottlesConcurrentExecutions
AWS recommends viewing invocation metrics such as errors and throttles with
Sum, while concurrency metrics such as ConcurrentExecutions should be examined with Max. Lambda also supports percentile statistics such as p95 for duration analysis.
A simplified Lambda operations dashboard that helps operators track invocations, errors, response duration, throttling events, and concurrency trends in one view.
Automate it with CloudFormation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
ServerlessDashboard:
Type: AWS::CloudWatch::Dashboard
Properties:
DashboardName: !Sub '${Environment}-${AWS::Region}-serverless'
DashboardBody: !Sub |
{
"widgets": [
{
"type": "metric",
"width": 12,
"height": 6,
"properties": {
"title": "Invocations vs Errors",
"region": "${AWS::Region}",
"period": 60,
"metrics": [
["AWS/Lambda","Invocations","FunctionName","${FunctionName}",
{"stat":"Sum"}],
["AWS/Lambda","Errors","FunctionName","${FunctionName}",
{"stat":"Sum"}]
]
}
},
{
"type": "metric",
"width": 12,
"height": 6,
"properties": {
"title": "Duration",
"region": "${AWS::Region}",
"period": 60,
"metrics": [
["AWS/Lambda","Duration","FunctionName","${FunctionName}",
{"stat":"p95"}],
["AWS/Lambda","Duration","FunctionName","${FunctionName}",
{"stat":"Average"}]
]
}
}
]
}Ship an alarm beside it
If the dashboard lives in code but the alarms live in somebody's memory, the system is only half automated.
Here is a simple throttling alarm:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
LambdaThrottleAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: !Sub '${Environment}-${FunctionName}-throttles'
Namespace: AWS/Lambda
MetricName: Throttles
Dimensions:
- Name: FunctionName
Value: !Ref FunctionName
Statistic: Sum
Period: 60
EvaluationPeriods: 3
DatapointsToAlarm: 2
Threshold: 0
ComparisonOperator: GreaterThanThreshold
TreatMissingData: notBreachingCloudFormation's
AWS::CloudWatch::Alarm resource also supports alarms based on metric-math expressions, which is useful when you want to alarm on a Lambda error rate instead of a raw error count.Alarm starting points
- Throttles: >0 across 2 of 3 minutes for synchronous critical functions
- Error rate: >1% as an initial investigation threshold
- P95 duration: relative to timeout and latency SLO
- Concurrency: alert before consistently approaching reserved or regional capacity
What to look for
Invocations up + concurrency up + throttles up
Capacity is probably the first place to investigate.
Capacity is probably the first place to investigate.
Duration up + errors flat
The function is becoming slower without necessarily failing. Inspect dependencies, cold starts, downstream latency, and code paths.
The function is becoming slower without necessarily failing. Inspect dependencies, cold starts, downstream latency, and code paths.
Errors up while invocations stay flat
That often points toward a deployment, dependency, permissions, or configuration change rather than traffic growth.
That often points toward a deployment, dependency, permissions, or configuration change rather than traffic growth.
The important principle:
Serverless scales infrastructure automatically. It does not scale your understanding automatically.
4. Database Health Dashboard
Applications often complain before databases scream.
By the time users notice slowness, the database may already have been accumulating pressure for several minutes.
For standard RDS DB instances, useful CloudWatch metrics include:
CPUUtilizationDatabaseConnectionsFreeStorageSpaceFreeableMemoryReadIOPSWriteIOPSReadLatencyWriteLatencyDiskQueueDepth
AWS publishes these metrics under
AWS/RDS; DBInstanceIdentifier is the dimension used to isolate a specific DB instance.
A simplified RDS health dashboard that helps operators monitor CPU, connections, latency, IOPS, and storage so they can identify database constraints before they become application outages.
Automate it
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
"type": "metric",
"width": 24,
"height": 6,
"properties": {
"title": "RDS Pressure",
"region": "us-east-1",
"metrics": [
[
"AWS/RDS",
"CPUUtilization",
"DBInstanceIdentifier",
"prod-orders-db",
{"stat": "Average"}
],
[
"AWS/RDS",
"DatabaseConnections",
"DBInstanceIdentifier",
"prod-orders-db",
{"stat": "Average", "yAxis": "right"}
]
],
"period": 60
}
}Do not stop with one graph. Pair connections and CPU with latency, free storage, IOPS, and queue behavior.
RDS is not Aurora with a different logo
Aurora adds cluster-level behavior and metrics that differ from traditional RDS instances. AWS documents Aurora metrics at both cluster and instance level, including engine-specific and cluster-specific measurements.
For deeper diagnosis, use CloudWatch Database Insights and, where appropriate, Enhanced Monitoring. Enhanced Monitoring exposes operating-system detail through CloudWatch Logs, while Database Insights adds deeper database-load and query-oriented analysis.
Your dashboard should therefore have two layers:
1
2
3
4
5
Shared RDS baseline
+
Engine / Aurora-specific metrics
+
Deep-dive database toolingDo not force every database into one universal template.
Alarm starting points
Examples:
- CPU: sustained >80%
- Free storage: alert well before exhaustion, based on growth rate and recovery time
- Connection count: alert relative to your configured safe maximum
- Read/write latency: baseline against your workload
AWS notes that read latencies above roughly 20 ms can merit investigation, but also explicitly says the right threshold depends on your application.
That is exactly how thresholds should be treated: evidence, not commandments.
What to look for
Connections up + CPU flat + latency up
Investigate connection-pool exhaustion, lock contention, blocked transactions, or inefficient queries.
Investigate connection-pool exhaustion, lock contention, blocked transactions, or inefficient queries.
CPU up + latency up + connections stable
Look for expensive SQL, changed execution plans, or a workload shift.
Look for expensive SQL, changed execution plans, or a workload shift.
IOPS near provisioned capacity + read/write latency up
Storage performance may be the bottleneck. AWS recommends considering both IOPS and throughput rather than using IOPS alone.
Storage performance may be the bottleneck. AWS recommends considering both IOPS and throughput rather than using IOPS alone.
A database dashboard should show you the constraint forming before users call it “the website is slow.”
5. Incident Command Dashboard
The first four dashboards explain individual layers.
The fifth exists for the moment nobody wants.
Production is failing.

A simplified incident command dashboard that brings alarms, service health, recent errors, deployment timing, and next-step runbook access into one view so operators can investigate faster from a single screen.
Your incident dashboard should answer:
- What is alarming?
- What are users experiencing?
- Which layer changed?
- What happened recently?
- Where is the runbook?
CloudWatch gives you more than metric graphs. Dashboard bodies support
metric, alarm, log, and text widgets, among other types. Alarm status widgets can surface alarms by state, log widgets can run CloudWatch Logs Insights queries, and text widgets can hold Markdown such as runbook links.Use them.
Automate the command center
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
{
"widgets": [
{
"type": "alarm",
"width": 24,
"height": 4,
"properties": {
"title": "Active Production Alarms",
"alarms": [
"arn:aws:cloudwatch:us-east-1:123456789012:alarm:api-errors",
"arn:aws:cloudwatch:us-east-1:123456789012:alarm:db-latency"
],
"states": ["ALARM", "INSUFFICIENT_DATA"],
"sortBy": "stateUpdatedTimestamp"
}
},
{
"type": "log",
"width": 18,
"height": 6,
"properties": {
"region": "us-east-1",
"title": "Recent Application Errors",
"query": "SOURCE '/aws/lambda/orders-api' | fields @timestamp, @message\n| filter @message like /ERROR/\n| sort @timestamp desc\n| limit 50",
"view": "table"
}
},
{
"type": "text",
"width": 6,
"height": 6,
"properties": {
"markdown": "## Incident Links\n- [Runbook](https://example.com/runbook)\n- [Status Page](https://example.com/status)\n- Escalation: Platform On-Call"
}
}
]
}AWS documents both the
SOURCE syntax for programmatic Logs Insights queries and the dashboard log-widget format.The URLs above are placeholders. Replace them with your actual operational links.
What about deployment markers?
CloudWatch does not magically know which vertical line on your graph represents a deployment.
You need a mechanism.
Two clean options are:
Option 1: Emit a deployment metric
Have CI/CD call
PutMetricData after a successful deployment:1
2
3
4
5
aws cloudwatch put-metric-data \
--namespace "Operations/Deployments" \
--metric-name Deployment \
--value 1 \
--dimensions Service=orders,Environment=prodPlot that metric beside application health.
Option 2: Update dashboard annotations
CloudWatch metric widgets support vertical annotations. Your deployment pipeline can update the dashboard JSON after a release and add a timestamped deployment annotation.
The first approach creates queryable deployment telemetry. The second creates a cleaner visual timeline.
Either is better than writing “add deployment markers” and pretending they appear by themselves.
Alarm starting points
The Incident Command dashboard usually should not invent a second set of thresholds. It should aggregate the alarms already owned by infrastructure, application, Lambda, database, queue, and dependency components.
For high-noise environments, consider using composite or higher-level alarms so one underlying failure does not page the team fifteen times.
What to look for
Alarm + deployment signal at the same time
The last release becomes a strong hypothesis, not automatic proof.
The last release becomes a strong hypothesis, not automatic proof.
Application errors up + infrastructure stable + DB stable
Look toward application code or external dependencies.
Look toward application code or external dependencies.
Latency rises first, then errors, then unhealthy targets
The order matters. The first symptom often tells you more than the loudest symptom.
The order matters. The first symptom often tells you more than the loudest symptom.
Incident response is partly debugging.
It is also chronology.
Dashboards and Alarms Should Be One Product
A dashboard tells you what is happening.
An alarm tells you when looking becomes urgent.
Treating them as separate projects creates drift.
Instead:
1
2
3
4
5
6
Service observability module
├── Dashboard
├── Metric math
├── Alarms
├── Log queries
└── Runbook linksWhen the service changes, its observability changes with it.
That is what “automated dashboards” should mean.
Not automated creation of pretty graphs.
Automated operational context.
What Will This Cost?
Do not assume CloudWatch observability is free because many AWS service metrics are published automatically.
Costs can come from:
- Custom metrics
- CloudWatch-agent metrics
- Additional dashboards
- Alarms
- Log ingestion and storage
- Logs Insights queries
- Some API usage
- Database Insights or other advanced observability features
AWS currently provides free-tier allowances for a limited number of custom metrics, dashboards, alarm metrics, and log usage. Pricing then varies by feature and Region. AWS also notes that loading dashboard widgets backed by Logs Insights queries can generate query charges.
So optimize dashboards the same way you optimize infrastructure:
collect what creates decisions.
More telemetry is not automatically more observability.
A Practical Deployment Checklist
Before calling any dashboard production-ready, check these boxes:
Infrastructure
- CloudWatch agent installed where host memory/filesystem metrics are required
- Correct metric namespaces and dimensions
- Environment and Region parameterized
Access
- Deployment role can create/update dashboards
- Deployment role can create alarms
- Custom metric publishers have only the permissions they require
Naming
Use:
1
environment-region-service-purposeRemember that dashboard names are account-global.
Multi-account AWS
If you operate across several accounts, decide whether teams should open dashboards account by account or use a monitoring account with cross-account observability. CloudWatch supports central views of metrics, logs, and traces from source accounts.
Thresholds
Start with reasonable numbers.
Then replace assumptions with:
- SLOs
- historical baselines
- capacity limits
- customer impact
- recovery time
That is how an alarm becomes useful instead of noisy.
The Real Test of an Operations Dashboard
Imagine it is 2:13 AM.
An alarm wakes somebody up.
They know nothing about the incident yet.
Your dashboard has one job:
reduce uncertainty.
Can the operator answer these questions quickly?
- What changed?
- Are customers affected?
- Which layer is under pressure?
- Did anything deploy recently?
- What should I investigate next?
If the answer is no, another twelve graphs probably will not save the dashboard.
Delete what does not help.
Promote what does.
Automate what matters.
The best CloudWatch dashboard is not the one with the most widgets.
It is the one that gets the operator to the next correct decision faster.
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article