CubeAPM
CubeAPM CubeAPM

How to Monitor AWS CloudWatch Metrics: Step-by-Step Guide 2026

How to Monitor AWS CloudWatch Metrics: Step-by-Step Guide 2026

Table of Contents

AWS CloudWatch is AWS’s native monitoring service for collecting and tracking metrics from EC2 instances, RDS databases, Lambda functions, and over 100 other AWS services. Without proper CloudWatch monitoring, a spike in API Gateway latency or an RDS connection pool exhaustion can quietly degrade application performance for hours before anyone notices.

This guide walks through how to monitor AWS CloudWatch metrics from initial setup to building dashboards and creating alarms. By the end, you will know how to surface performance bottlenecks, set up actionable alerts, and query metrics programmatically using the CloudWatch API and CLI.

Prerequisites

Before starting, ensure you have:

  • An active AWS account with IAM permissions for CloudWatch (cloudwatch:PutMetricData, cloudwatch:GetMetricStatistics, cloudwatch:DescribeAlarms at minimum)
  • AWS CLI installed and configured with aws configure (verify with aws sts get-caller-identity)
  • Basic familiarity with AWS services you want to monitor (EC2, RDS, Lambda, API Gateway, etc.)
  • A running AWS resource to monitor (an EC2 instance, RDS database, or Lambda function)
  • Access to the AWS Management Console

Step 1: Understand CloudWatch Metrics Structure

CloudWatch organizes metrics into namespaces, which group related metrics by AWS service. Each metric belongs to exactly one namespace. For example, all EC2 instance metrics live in the AWS/EC2 namespace, RDS metrics in AWS/RDS, and Lambda metrics in AWS/Lambda.

Every metric is identified by:

  • Namespace: The AWS service (AWS/EC2, AWS/RDS, AWS/Lambda)
  • Metric name: What is being measured (CPUUtilization, NetworkIn, Invocations)
  • Dimensions: Key-value pairs that filter metrics (InstanceId=i-1234567890abcdef0, FunctionName=my-lambda)
  • Statistics: How the metric is aggregated (Average, Sum, Maximum, Minimum, SampleCount)
  • Period: The time window for aggregation (1 minute, 5 minutes, 1 hour)

To see all available namespaces, run:

aws cloudwatch list-metrics --query 'Metrics[*].Namespace' --output text | tr '\t' '\n' | sort -u

This returns a list of every namespace currently publishing metrics in your account. For a new AWS account with a few EC2 instances and an RDS database, you will see AWS/EC2, AWS/RDS, and AWS/Billing at minimum.

Step 2: View Metrics in the CloudWatch Console

The CloudWatch console provides the fastest way to explore what metrics are available and understand what your resources are currently reporting.

Open the CloudWatch console. In the left navigation pane, click Metrics, then All metrics. You will see a list of namespaces. Click on a namespace to drill down. For example, click AWS/EC2 to see EC2 metrics.

CloudWatch groups metrics by dimension combinations. For EC2, common groupings include:

  • Per-Instance Metrics: Metrics broken down by individual EC2 instance
  • By Auto Scaling Group: Metrics aggregated by ASG
  • By Image (AMI) Id: Metrics grouped by the AMI used
  • Across All Instances: Metrics aggregated across all instances in the region

Click Per-Instance Metrics to see all metrics for each running EC2 instance. Each row shows:

  • Metric name (CPUUtilization, NetworkIn, NetworkOut, DiskReadBytes, etc.)
  • Dimension values (InstanceId, ImageId, InstanceType)
  • A checkbox to graph the metric

Select the checkbox next to CPUUtilization for one of your instances. The metric appears as a line graph in the upper panel. The graph shows the last hour by default. You can change the time range using the time selector in the top right.

To add multiple metrics to the same graph, select additional checkboxes. This is useful for comparing CPU utilization across multiple instances or viewing NetworkIn and NetworkOut on the same chart to understand bandwidth patterns.

Step 3: Query Metrics Using the AWS CLI

The AWS CLI provides a programmatic way to retrieve metric data, which is essential for scripting, automation, and integrating CloudWatch data into infrastructure monitoring tools.

To retrieve the last hour of CPUUtilization data for an EC2 instance:

aws cloudwatch get-metric-statistics \
  --namespace AWS/EC2 \
  --metric-name CPUUtilization \
  --dimensions Name=InstanceId,Value=i-1234567890abcdef0 \
  --start-time $(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%S) \
  --end-time $(date -u +%Y-%m-%dT%H:%M:%S) \
  --period 300 \
  --statistics Average

Replace i-1234567890abcdef0 with your actual instance ID. This command returns Average CPU utilization in 5 minute intervals (300 seconds) over the last hour.

To list all available metrics for a specific instance:

aws cloudwatch list-metrics \
  --namespace AWS/EC2 \
  --dimensions Name=InstanceId,Value=i-1234567890abcdef0

This returns every metric that instance is publishing, including CPUUtilization, NetworkIn, NetworkOut, DiskReadOps, DiskWriteOps, and StatusCheckFailed.

For RDS databases, replace the namespace and dimension:

aws cloudwatch list-metrics \
  --namespace AWS/RDS \
  --dimensions Name=DBInstanceIdentifier,Value=mydb

Common RDS metrics include DatabaseConnections, ReadLatency, WriteLatency, FreeStorageSpace, and CPUUtilization.

Step 4: Create a CloudWatch Dashboard

Dashboards let you visualize multiple metrics in one place. This is critical when monitoring distributed systems where understanding the relationship between frontend API latency, backend service load, and database connection counts determines whether an issue is in code, infrastructure, or upstream dependencies.

In the CloudWatch console, click Dashboards in the left navigation, then Create dashboard. Enter a name like Production Monitoring and click Create dashboard.

CloudWatch prompts you to add a widget. Choose Line for time series graphs, Number for single metric values, or Log table for log query results. Click Line to add a line graph.

In the metric selection screen, choose a namespace (AWS/EC2), then a dimension grouping (Per-Instance Metrics). Select the metrics you want to graph. For example, select CPUUtilization for three production instances, then click Create widget.

To add another widget, click Add widget at the top of the dashboard. Repeat the process to add RDS database metrics, Lambda invocation counts, or API Gateway request latencies.

You can resize widgets by dragging their corners and rearrange them by dragging the widget header. Save the dashboard by clicking Save dashboard at the top right.

Dashboards are region specific. If you run resources in multiple regions, create separate dashboards for each region or use CloudWatch cross-region functionality (available in select regions) to aggregate metrics.

Step 5: Set Up CloudWatch Alarms

Alarms trigger actions when a metric crosses a threshold you define. Without alarms, you rely on manual dashboard checks to discover issues. With alarms, CloudWatch notifies you via SNS (Simple Notification Service) the moment a problem occurs.

To create an alarm, open the CloudWatch console and click Alarms in the left navigation, then Create alarm. Click Select metric.

Choose a namespace and metric. For example, navigate to AWS/EC2, Per-Instance Metrics, and select CPUUtilization for a specific instance. Click Select metric.

Configure the alarm conditions:

  • Threshold type: Static (fixed threshold) or Anomaly detection (ML-based)
  • Whenever CPUUtilization is: Greater than, Less than, or Equal to
  • than: The threshold value (e.g., 80 for 80% CPU)
  • Datapoints to alarm: How many periods must breach the threshold before the alarm triggers (e.g., 2 out of 3)

For example, to alert when CPU exceeds 80% for 10 consecutive minutes, set:

  • Greater than 80
  • Period: 5 minutes
  • Datapoints to alarm: 2 of 2 (two consecutive 5 minute periods)

Click Next. Configure the notification. If you do not have an SNS topic, create one by clicking Create new topic, entering an email address, and clicking Create topic. AWS sends a confirmation email to that address. You must confirm the subscription before alarms can send notifications.

Click Next, name the alarm (e.g., High CPU – Production Instance), and click Create alarm.

The alarm enters the OK state if the metric is below the threshold, ALARM if it breaches, and INSUFFICIENT_DATA if CloudWatch cannot evaluate the metric (common for newly created resources that have not yet published data).

Step 6: Use CloudWatch Metrics Insights for Advanced Queries

CloudWatch Metrics Insights allows SQL-like queries across metrics, making it easier to aggregate, filter, and compare metrics without manually selecting them in the console. This is particularly useful when monitoring dozens of instances or microservices.

In the CloudWatch console, click Metrics, then Query. This opens the Metrics Insights editor.

To find the average CPU utilization across all EC2 instances in an Auto Scaling group:

SELECT AVG(CPUUtilization)
FROM "AWS/EC2"
WHERE AutoScalingGroupName = 'my-asg'
GROUP BY InstanceId

Replace my-asg with your Auto Scaling group name. This returns one line per instance showing average CPU over the selected time range.

To identify which Lambda function has the highest error rate:

SELECT SUM(Errors) / SUM(Invocations) * 100 AS ErrorRate
FROM "AWS/Lambda"
GROUP BY FunctionName
ORDER BY ErrorRate DESC

This calculates error rate as a percentage for every Lambda function and sorts by highest error rate first.

Metrics Insights supports filtering by dimension, aggregating with SUM, AVG, MAX, MIN, and combining metrics from different namespaces in a single query. For teams managing large fleets of resources, this is faster than manually building graphs for each resource.

Step 7: Monitor CloudWatch Metrics with Third-Party Tools

AWS CloudWatch is AWS native, but many teams integrate CloudWatch metrics into top AWS monitoring tools that provide deeper correlation with logs, traces, and application performance data. CubeAPM, for example, ingests CloudWatch metrics alongside OpenTelemetry traces and logs, giving you a unified view of AWS infrastructure health in the same dashboard where you debug application performance issues.

To send CloudWatch metrics to an external platform, use CloudWatch Metric Streams or the CloudWatch API.

CloudWatch Metric Streams continuously delivers CloudWatch metrics to destinations like Amazon Kinesis Data Firehose, which can forward them to S3, Datadog, Splunk, or any HTTP endpoint. To set up a metric stream:

  1. Open the CloudWatch console, click Metrics, then Streams
  2. Click Create metric stream
  3. Choose whether to stream all metrics or select specific namespaces
  4. Choose a Kinesis Data Firehose delivery stream as the destination
  5. Click Create metric stream

Metrics begin streaming within minutes. This is the recommended approach for real time integration with external observability platforms.

For batch ingestion, use the AWS CLI to periodically fetch metrics and push them to your monitoring platform:

aws cloudwatch get-metric-statistics \
  --namespace AWS/EC2 \
  --metric-name CPUUtilization \
  --dimensions Name=InstanceId,Value=i-1234567890abcdef0 \
  --start-time $(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%S) \
  --end-time $(date -u +%Y-%m-%dT%H:%M:%S) \
  --period 300 \
  --statistics Average \
  --output json

This outputs JSON that can be parsed and forwarded to any observability backend.

Troubleshooting Common Issues

Metric data is missing or delayed

CloudWatch metrics are published by AWS services at varying intervals. EC2 basic monitoring publishes metrics every 5 minutes. EC2 detailed monitoring (which must be enabled and costs extra) publishes every 1 minute. Lambda and API Gateway metrics appear within seconds of invocation. If a metric is missing, verify the resource is running and publishing metrics by checking aws cloudwatch list-metrics.

Alarm stuck in INSUFFICIENT_DATA state

This happens when CloudWatch cannot evaluate the metric, usually because the resource has not published data yet or the metric does not exist. Verify the metric name and dimensions are correct using list-metrics. For newly created resources, wait 5 to 10 minutes for the first data points to appear.

Costs scaling faster than expected

CloudWatch charges for custom metrics, detailed monitoring, API requests, and alarms beyond the free tier. The free tier includes 10 custom metrics, 10 alarms, and 1 million API requests per month. Beyond that, custom metrics cost $0.30 per metric per month, alarms cost $0.10 per alarm per month, and API requests cost $0.01 per 1,000 requests. For teams ingesting millions of custom metrics or running hundreds of alarms, costs can reach thousands of dollars monthly. The Amazon CloudWatch pricing calculator models these costs before you scale.

Cannot query metrics older than 15 months

CloudWatch retains metrics for 15 months. After that, data is deleted and cannot be retrieved. For long term metric storage, export metrics to S3 using CloudWatch Metric Streams or periodically pull data with get-metric-statistics and store it in your own data warehouse.

Dashboard shows no data for custom metrics

Custom metrics require explicit publishing via put-metric-data. If your application is not actively publishing data, the metric will not appear. Verify your application or Lambda function is calling PutMetricData with the correct namespace, metric name, and dimensions.

Conclusion

Monitoring AWS CloudWatch metrics is the baseline for understanding AWS infrastructure health. By following the steps in this guide, you can view metrics in the console, query them programmatically, build dashboards, set up alarms, and integrate CloudWatch data with external observability platforms. For teams running production workloads, the next step is correlating CloudWatch metrics with application traces and logs to answer not just what broke, but why it broke and which code path caused it.

Disclaimer: The information in this article reflects the latest details available at the time of publication and may change as technologies and products evolve. Features, pricing, and plan limits can change over time. Always verify the latest information directly with the vendor before making purchasing or deployment decisions.

Frequently Asked Questions

What is the difference between CloudWatch metrics and CloudWatch Logs?

CloudWatch metrics are numeric time series data like CPU utilization, request count, or disk IOPS. CloudWatch Logs are text based log streams from applications, Lambda functions, or VPC Flow Logs. Metrics answer “how much” and logs answer “what happened.”

How often does CloudWatch update metrics?

EC2 basic monitoring publishes metrics every 5 minutes. EC2 detailed monitoring publishes every 1 minute. Lambda, API Gateway, and DynamoDB publish metrics within seconds. RDS and EBS publish every 1 to 5 minutes depending on the metric.

Can I monitor on premises servers with CloudWatch?

Yes, install the CloudWatch agent on on premises Linux or Windows servers. The agent publishes system metrics (CPU, memory, disk) and custom application metrics to CloudWatch under a custom namespace. The agent requires IAM credentials with cloudwatch:PutMetricData permissions.

How much does CloudWatch cost?

CloudWatch offers a free tier: 10 custom metrics, 10 alarms, 1 million API requests, 5 GB log ingestion, and 5 GB log storage per month. Beyond that, custom metrics cost $0.30 per metric per month, alarms cost $0.10 per alarm per month, and logs cost $0.50 per GB ingested and $0.03 per GB stored.

What is the maximum resolution for CloudWatch metrics?

Standard resolution is 1 minute. High resolution metrics can be published at 1 second intervals using put-metric-data with a StorageResolution of 1. High resolution metrics cost the same as standard resolution but allow finer granularity for detecting short lived spikes.

Can I create alarms based on multiple metrics?

Yes, use composite alarms. These combine multiple alarms using AND, OR, and NOT logic. For example, trigger an alarm only if CPU is high AND disk IOPS are low, indicating a resource bottleneck rather than normal load.

How do I export CloudWatch metrics to S3?

Use CloudWatch Metric Streams to continuously deliver metrics to a Kinesis Data Firehose delivery stream configured to write to S3. Alternatively, use the AWS CLI to periodically fetch metrics with get-metric-statistics and upload the JSON output to S3.

×
×