AWS CloudWatch Metrics Explained: Namespaces, Dimensions, Custom Metrics
CloudWatch metrics are the foundation of monitoring in AWS. Before you can build alarms, create dashboards, or trigger auto-scaling, you need to understand what a metric is, how CloudWatch organizes them, and how to find the data you actually care about.
What is a CloudWatch metric in AWS?
A metric is a numeric measurement tracked over time. CloudWatch stores these measurements
as a sequence of data points, each with a timestamp, a value, and a unit. For example,
CPUUtilization for an EC2 instance might record 42% at 14:00, 67% at 14:05,
and 71% at 14:10.
Most AWS services publish metrics to CloudWatch automatically with no setup required. When you launch an EC2 instance, CloudWatch immediately starts receiving CPU, network, and disk I/O data. When a Lambda function runs, CloudWatch records invocation count, errors, duration, and throttles. This automatic collection is part of the Amazon CloudWatch platform and works across virtually every AWS service.
Think of metrics like your car’s instrument panel
The speedometer shows 65 mph. The fuel gauge reads quarter-tank. The temperature gauge sits at normal. Those are metrics: numbers that update over time, readable at a glance. The namespace is the make of car (a Tesla’s gauges differ from a Ford’s). The metric name is which gauge: Speed, Fuel, Temperature. The dimension is which specific car: yours versus the one parked next to it. The alarm is the low-fuel warning light. And logs are the mechanic’s diagnostic report when something breaks. CloudWatch works the same way, just for your servers, functions, and databases.
The short version
If you are new to AWS monitoring, here is the essential picture:
- A metric is a number over time: CPU at 72%, 5 errors in the last minute, 2.3ms average latency
- CloudWatch stores it automatically for most AWS services, or via the API for your own custom data
- Alarms use it: an alarm watches a metric and fires when it crosses a threshold you set
- Dashboards visualize it: you graph metrics alongside alarm states to see what is happening at a glance
- Logs and traces answer different questions: metrics say something is wrong; logs say what the error was; traces say which service caused it
A good first move is browsing the AWS console at CloudWatch › Metrics › All metrics › AWS/EC2 and clicking an instance to see its live CPU graph. That hands-on look at namespaces and dimensions makes the rest of this page much easier to follow.
Why metrics matter in AWS
Metrics are efficient. A single number (78% CPU, 42ms latency, 3 errors) carries actionable signal in far less storage than a log line. That efficiency makes metrics the right tool for several jobs that logs and traces cannot do as well:
- Alerting: set a threshold and get paged automatically without watching a dashboard. See Creating CloudWatch Alarms for how to build them.
- Dashboards: graph CPU, error rate, and latency side by side on a CloudWatch Dashboard so on-call engineers see the full picture at a glance
- Auto-scaling: Auto Scaling Groups use metrics (typically CPU or a custom signal) to decide when to add or remove EC2 instances
- Trend analysis: metrics retained up to 15 months let you compare this week’s error rate against last month’s baseline
- Troubleshooting scope: during an incident, metrics tell you when the problem started and how widespread it is before you dig into logs
How CloudWatch metrics work
Every metric in CloudWatch has four identifying properties. Together they uniquely identify a specific data stream.
Namespace
A namespace is a container that groups related metrics. AWS services use the pattern
AWS/ServiceName, for example AWS/EC2, AWS/Lambda,
or AWS/RDS. When you publish custom metrics from your application, you choose
your own namespace, such as MyApp/Payments or MyCompany/API.
Common AWS namespaces you will encounter:
| Namespace | Service | Key Metrics |
|---|---|---|
AWS/EC2 | EC2 instances | CPUUtilization, NetworkIn, NetworkOut, StatusCheckFailed |
AWS/Lambda | Lambda functions | Invocations, Errors, Duration, Throttles, ConcurrentExecutions |
AWS/RDS | RDS databases | CPUUtilization, DatabaseConnections, FreeStorageSpace, ReadLatency |
AWS/ApplicationELB | Application Load Balancer | RequestCount, TargetResponseTime, HTTPCode_ELB_5XX_Count |
AWS/SQS | SQS queues | NumberOfMessagesSent, ApproximateAgeOfOldestMessage, NumberOfMessagesDeleted |
AWS/ECS | ECS clusters/services | CPUUtilization, MemoryUtilization, RunningTaskCount |
CWAgent | CloudWatch agent (EC2) | mem_used_percent, disk_used_percent, processes_running |
The CWAgent namespace is worth calling out: it is where the CloudWatch agent
publishes OS-level metrics (memory, disk) that EC2 does not expose by default. AWS cannot
see inside your operating system without an agent, so these metrics require installing the
agent on the instance.
Metric name
The metric name identifies what is being measured within a namespace:
CPUUtilization, Errors, ReadLatency. Within a
namespace, the metric name and dimensions together identify a unique time series.
Dimensions
Dimensions are key-value pairs that identify which specific resource a metric belongs to. Without dimensions, you would have one aggregated CPU metric for all EC2 instances in your account. Dimensions let CloudWatch store per-instance, per-function, or per-queue data and let you query it at any granularity. A metric can have up to 30 dimensions. Examples:
InstanceId = i-0abc123def456789(EC2)FunctionName = process-orders(Lambda)QueueName = my-order-queue(SQS)DBInstanceIdentifier = prod-postgres(RDS)
Two metrics with the same name but different dimensions are different metrics.
CPUUtilization for InstanceId=i-0abc123 is a completely
separate time series from CPUUtilization for InstanceId=i-0def456.
When you publish custom metrics, you choose your own dimensions. A payment service might
publish error counts dimensioned by Environment=production and
PaymentMethod=card, making it possible to graph error rates broken down by
payment method.
High-cardinality dimensions are a cost trap. If you use user IDs, order IDs, or request IDs as dimension values, CloudWatch creates a new metric series for every unique value. With millions of requests, that becomes millions of metric series and your bill can spiral quickly. Stick to stable, low-cardinality labels like environment, region, or service name.
Data points and units
Each data point has three parts: a timestamp, a numeric value, and a unit. Units include
Count, Bytes, Milliseconds, Percent,
and others. Always publish metrics with the correct unit. Publishing latency in milliseconds
but setting an alarm threshold expecting seconds means your alarm logic is off by a factor
of 1000, and it will not obviously look wrong until it fires at the wrong time.
Statistics, periods, and resolution
When you query a metric, you aggregate data points into a period (a time bucket, in seconds) using a statistic: Average, Sum, Minimum, Maximum, SampleCount, or a percentile like p99. Resolution determines how frequently data points are stored in the first place:
| Resolution Type | Granularity | Retention | Notes |
|---|---|---|---|
| Basic (EC2) | 5 minutes | 15 months | Free; included with all EC2 instances |
| Detailed (EC2) | 1 minute | 15 months | Extra charge; required for fast Auto Scaling responses |
| Standard custom | 1 minute | 15 months | Published via PutMetricData; billed per metric |
| High-resolution custom | 1 second | 3 hours at 1s, then rolled up | Higher cost; use only where sub-minute alerting is required |
CloudWatch automatically rolls up high-resolution data over time. Data at 1-second resolution is retained for 3 hours, then aggregated to 1-minute for 15 days, then 5-minute for 63 days, and finally 1-hour for 15 months. You cannot retrieve finer granularity than what was originally stored.
Standard vs custom metrics
AWS publishes standard metrics automatically at no setup cost. Custom metrics are data points you publish yourself, typically business-level signals that AWS has no visibility into, like orders placed per minute or cache hit ratio.
| Standard metrics | Custom metrics | |
|---|---|---|
| Who publishes them | AWS services automatically | You, via PutMetricData or the CloudWatch agent |
| Setup required | None; available immediately | Application code or agent configuration |
| Cost | Included with the service (basic resolution free) | Billed per metric per month after the free tier |
| Default resolution | 5 minutes (EC2 basic), 1 minute (Lambda, RDS, others) | 1 minute (standard) or 1 second (high-resolution) |
| Examples | CPUUtilization, Lambda Errors, RDS DatabaseConnections | OrdersPlaced, CacheHitRatio, QueueProcessingLag, ActiveUsers |
Custom metrics are particularly valuable when you want business KPIs alongside
infrastructure health. When your dashboards show both CPUUtilization and
OrdersPlaced on the same timeline, you can correlate a traffic spike with
its business impact in real time.
When to use metrics
Not every observability question calls for a metric. Here is when metrics are the right tool and what to watch for each common scenario:
- Resource saturation: CPU, memory, disk, and network approaching limits. For EC2 instances, watch
CPUUtilizationand (with the CloudWatch agent)mem_used_percent. Enable detailed monitoring when auto-scaling needs to respond within minutes of a load change. - Lambda reliability:
ErrorsandThrottlesare the first metrics to alarm on for any Lambda function. The Lambda monitoring guide covers a practical alarm and dashboard setup. - SQS backlog growth:
ApproximateAgeOfOldestMessagetells you how far behind your consumers are. If messages are aging, your consumer is not keeping up. - RDS health:
DatabaseConnectionsapproaching the max causes connection refused errors.ReadLatencyandWriteLatencysurface query performance problems. For deeper query-level analysis, see AWS Performance Insights. - Business KPIs: publish custom metrics for orders placed, payments succeeded, active sessions, or conversion rate. Pairing these with infrastructure health on the same CloudWatch Dashboard makes on-call decisions faster.
Reach for CloudWatch Logs when you need the text of an error message, a stack trace, or a request payload. Reach for traces when you need to follow a request across multiple services. Metrics answer “how much” and “when.” Logs and traces answer “why” and “where exactly.”
Real examples of useful AWS metrics
These metrics are worth alarming on for most production systems. Each has a clear action associated with it.
| Service | Metric | What it tells you | When to act |
|---|---|---|---|
| EC2 | CPUUtilization | Percentage of CPU in use | Sustained above 80% — scale up or optimize |
| EC2 | StatusCheckFailed | Instance or system health check failure | Any value above 0 — investigate immediately |
| Lambda | Errors | Number of failed invocations | Any errors in a function that should be error-free |
| Lambda | Throttles | Invocations rejected due to concurrency limits | Any throttles — request a concurrency limit increase |
| Lambda | Duration (p99) | Worst-case execution time per invocation | Approaching timeout limit — optimize or increase timeout |
| RDS | DatabaseConnections | Current number of open connections | Above 80% of max_connections — check for connection leaks |
| RDS | ReadLatency | Average per-operation read time | Increasing trend — investigate slow queries |
| SQS | ApproximateAgeOfOldestMessage | How long the oldest unprocessed message has been waiting | Above 5 minutes — consumer may be failing or too slow |
| ECS | CPUUtilization | CPU across all running tasks in a service | Sustained above 70% — may need to scale task count |
For Kubernetes workloads on EKS, see the EKS monitoring guide for container-level metrics via CloudWatch Container Insights.
How to publish and query metrics
For exploratory work, the AWS console at CloudWatch › Metrics › All metrics gives you an interactive metric browser. Use the CLI or API when you need to automate queries, script alerting, or pull data into external tools.
Publishing a custom metric
# Publish a single custom metric data point
aws cloudwatch put-metric-data \
--namespace "MyApp/Orders" \
--metric-name "OrdersPlaced" \
--value 42 \
--unit Count \
--dimensions Name=Environment,Value=production
# Publish multiple metrics in one call (more efficient)
aws cloudwatch put-metric-data \
--namespace "MyApp/Payments" \
--metric-data '[
{
"MetricName": "PaymentSucceeded",
"Value": 98,
"Unit": "Count",
"Dimensions": [{"Name": "Environment", "Value": "production"}]
},
{
"MetricName": "PaymentFailed",
"Value": 2,
"Unit": "Count",
"Dimensions": [{"Name": "Environment", "Value": "production"}]
}
]'In application code, use the AWS SDK rather than calling the CLI. The Python boto3
equivalent uses cloudwatch.put_metric_data() with the same parameters.
Querying metrics with the CLI
Use get-metric-statistics for simple aggregated queries. Use
get-metric-data when you need metric math (for example, error rate
= errors / invocations × 100) or when pulling multiple metrics at once.
# Get average CPU for an EC2 instance over the last hour, in 5-minute buckets
aws cloudwatch get-metric-statistics \
--namespace AWS/EC2 \
--metric-name CPUUtilization \
--dimensions Name=InstanceId,Value=i-0abc123def456789 \
--start-time $(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ) \
--end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \
--period 300 \
--statistics Average \
--output table
# Use metric math to calculate Lambda error rate
aws cloudwatch get-metric-data \
--metric-data-queries '[
{
"Id": "errors",
"MetricStat": {
"Metric": {
"Namespace": "AWS/Lambda",
"MetricName": "Errors",
"Dimensions": [{"Name": "FunctionName", "Value": "process-orders"}]
},
"Period": 300,
"Stat": "Sum"
},
"ReturnData": false
},
{
"Id": "invocations",
"MetricStat": {
"Metric": {
"Namespace": "AWS/Lambda",
"MetricName": "Invocations",
"Dimensions": [{"Name": "FunctionName", "Value": "process-orders"}]
},
"Period": 300,
"Stat": "Sum"
},
"ReturnData": false
},
{
"Id": "error_rate",
"Expression": "errors / invocations * 100",
"Label": "Error Rate (%)",
"ReturnData": true
}
]' \
--start-time $(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ) \
--end-time $(date -u +%Y-%m-%dT%H:%M:%SZ)Metric math and anomaly detection: CloudWatch supports metric math expressions in alarms and dashboards, letting you derive new metrics from existing ones without publishing extra data points. It also supports anomaly detection, which trains a baseline model on historical data and alerts when behavior deviates from the expected band.
Metrics vs logs vs traces
Metrics, logs, and traces are complementary signals. The question is not which is better — it is which one to reach for first given what you are trying to answer.
| Signal | Question it answers | AWS service | Reach for it when… |
|---|---|---|---|
| Metrics | How much? How many? Is this above threshold? | Amazon CloudWatch | You need to alert, trend, or feed auto-scaling |
| Logs | What exactly happened? What was the error? | CloudWatch Logs | You need the error message, stack trace, or request detail |
| Traces | Which service caused the slowdown? Where did the request fail? | AWS X-Ray | You have a distributed system and need to follow a request across services |
In practice: an alarm (metric) wakes you up. You check the dashboard (metrics) to understand scope. You query CloudWatch Logs to find the error message. If the problem spans multiple services, you pull a trace from AWS X-Ray to see which downstream call is failing and how long it takes.
You can also bridge the gap: log-based metrics
let you turn log patterns (like the word ERROR appearing in a log line) into
CloudWatch metrics you can alarm on, without changing your application code. For a full
picture of combining all three signal types, see the guide to
distributed tracing in AWS.
Common beginner mistakes
- Using request IDs as dimensions. High-cardinality dimensions (user ID, order ID, session ID) create a new metric series for every unique value. With millions of requests, this creates millions of metric series and costs can spiral rapidly. Use low-cardinality labels like environment, region, or service name.
- Assuming EC2 memory is automatic. The
AWS/EC2namespace does not include memory or disk usage. AWS cannot see inside the OS without an agent. Install the CloudWatch agent to collect these metrics under theCWAgentnamespace. - Relying on 5-minute resolution for auto-scaling. Basic EC2 monitoring at 5-minute resolution is too slow for responsive Auto Scaling. Enable detailed monitoring (1-minute resolution) when you need scaling decisions within minutes of a load change.
- Querying with a period that does not match your resolution. If you request data with
—period 3600(1 hour) but only have 1-minute data, you get one data point per hour. Match your query period to the granularity you actually need. - Getting metric units wrong. Publishing a latency metric in milliseconds but setting an alarm threshold expecting seconds means your alarm is off by a factor of 1000, and it will not obviously look wrong until it fires (or fails to fire) at the wrong time.
Summary
- A CloudWatch metric is a time-series of numeric data points, identified by namespace, metric name, and dimensions.
- Most AWS services publish standard metrics automatically; custom metrics require publishing via
PutMetricDataand are billed per metric per month after the free tier. - Namespaces group related metrics. AWS services use
AWS/ServiceName; use your own convention for custom metrics. - Dimensions filter metrics down to a specific resource. Use low-cardinality values to avoid unexpected cost.
- EC2 ships at 5-minute basic resolution; enable detailed monitoring for 1-minute data when fast alerting or auto-scaling is required.
- Memory and disk metrics on EC2 require the CloudWatch agent and are not collected automatically.
- Use
get-metric-statisticsfor simple queries;get-metric-datafor metric math and multi-metric queries. - Metrics answer “how much / when.” Use logs for “what happened” and traces for “which service failed.”
Frequently asked questions
What is a CloudWatch metric?
A CloudWatch metric is a time-ordered sequence of numeric data points, each with a timestamp, a value, and a unit. For example, the CPUUtilization metric for an EC2 instance records the percentage of CPU used every 5 minutes (or every minute with detailed monitoring). Metrics are the numeric signals you use to build alarms, dashboards, and auto-scaling rules.
What is the difference between standard and custom metrics?
Standard metrics are published automatically by AWS services — you get them for free at basic resolution with no setup required. Custom metrics are data points you publish from your own application using the PutMetricData API or the CloudWatch agent. Custom metrics are billed per metric per month after the free tier, but they let you track business-level signals like orders placed or cache hit ratio that AWS does not measure for you.
Do EC2 instances send memory metrics automatically?
No. The AWS/EC2 namespace does not include memory or disk usage because AWS cannot see inside the operating system. You need to install the CloudWatch agent on your EC2 instance to collect memory and disk metrics, which are then published under the CWAgent namespace.
What is metric resolution in CloudWatch?
Resolution is how frequently data points are recorded. Standard resolution is 1-minute granularity (or 5-minute for basic EC2 monitoring). High-resolution custom metrics can be published at 1-second granularity. Higher resolution gives faster alerting but costs more to store and query. High-resolution data at 1-second granularity is retained for 3 hours before being rolled up to coarser resolutions.
When should I use metrics instead of logs?
Use metrics when you need to alert on a threshold, trend a number over time, or feed data into dashboards or auto-scaling rules. Use logs when you need to understand what exactly happened — error messages, stack traces, request details. In practice, an alarm (metric) wakes you up, and logs tell you why the problem occurred.