article
AWS Infrastructure Monitoring with CloudWatch: A Practical Guide (2026)

Amazon CloudWatch is the monitoring service built into AWS. Every AWS service publishes metrics to it, most can send logs to it, and it provides alarms, dashboards, anomaly detection and a few newer products (Container Insights, Lambda Insights, Application Signals, Synthetics) on top. If you run anything on AWS, CloudWatch is already collecting data about it whether you look or not.
This guide explains how AWS cloud monitoring actually works with CloudWatch, how to set it up so it catches real problems, where it falls short, what it costs at realistic scale, and how we combine it with Zabbix or Prometheus for clients whose estates do not stop at the AWS boundary.
What CloudWatch collects out of the box
CloudWatch metrics are numeric time series published by AWS services into namespaces such as AWS/EC2, AWS/RDS, AWS/Lambda, AWS/ApplicationELB and AWS/ECS. Standard metrics arrive at five-minute resolution for free; detailed monitoring (one-minute resolution) costs extra on EC2 and is on by default for most managed services.
What you get without installing anything:
- EC2: CPU utilisation, network in and out, disk read and write for instance-store volumes, status checks (instance and system), CPU credit balance on burstable instances. Not memory, not disk usage on EBS volumes, not processes.
- EBS: read and write ops and bytes, queue length, burst balance on gp2 and st1 volumes, volume status.
- RDS and Aurora: CPU, freeable memory, free storage, read and write IOPS and latency, database connections, replica lag, and for Aurora, buffer cache hit ratio and Aurora-specific replication metrics. Enhanced Monitoring adds OS-level metrics at up to one-second resolution.
- Lambda: invocations, errors, duration, throttles, concurrent executions, iterator age for stream sources.
- ECS and EKS: cluster CPU and memory reservation and utilisation; Container Insights adds per-task, per-pod and per-container metrics.
- Load balancers: request count, target response time, healthy and unhealthy host counts, HTTP 4xx and 5xx from targets and from the load balancer itself, TLS negotiation errors.
- SQS, SNS, Kinesis, DynamoDB, ElastiCache, API Gateway, CloudFront, S3, NAT Gateway, Transit Gateway, VPN, Direct Connect: each has its own namespace with the metrics that matter for that service.
The gaps are consistent: anything inside the operating system (memory, disk space, processes, log files) needs the CloudWatch agent, and anything about your application (queue depth in your own code, job completion, business transactions) needs custom metrics or Application Signals.
The CloudWatch agent: closing the OS gap
The CloudWatch agent runs on EC2 instances and on-premises servers and publishes memory, disk, swap, per-process and custom StatsD or collectd metrics, plus log files, to CloudWatch. It is configured with a JSON file that is best stored in SSM Parameter Store and deployed with SSM State Manager or your configuration management, so every instance in an auto-scaling group gets the same config.
Minimum useful configuration for a Linux fleet: mem_used_percent, disk_used_percent for / and data mounts, swap_used_percent, and the system log plus your application log with a log group per environment. On Windows add the Application and System event logs and the relevant performance counters. Set metrics_collection_interval to 60 seconds; anything lower on a large fleet is money, not insight.
Metrics from the agent land in the CWAgent namespace as custom metrics, which is where cost starts to matter (see below).
Designing alarms that page for the right reasons
A CloudWatch alarm evaluates one metric or a metric math expression over a period and number of datapoints, and moves between OK, ALARM and INSUFFICIENT_DATA. Alarms notify through SNS, which fans out to email, SMS, Lambda, PagerDuty, Opsgenie, Slack via Chatbot, or an incident tool. The alarms that earn their keep in most estates:
- EC2 status check failed (system) for one datapoint: the host is broken; recover or replace it. Use the built-in EC2 recover action.
- CPU above 85% for 15 minutes on non-batch instances, and CPU credit balance below 50 on burstable instances, which is the real reason a
t3gets slow. - Memory above 90% and disk above 85% from the agent, with a second alarm using metric math to forecast disk exhaustion.
- RDS free storage below 15%, freeable memory trending to zero, replica lag above 30 seconds, connections above 80% of
max_connections. - ALB target 5xx rate above 1% of requests using metric math (
5xx / requests * 100), and unhealthy host count above zero for five minutes. - Lambda errors above 1% of invocations and throttles above zero, and iterator age climbing on stream consumers.
- SQS oldest message age above the SLA for the consumer.
- Auto Scaling desired capacity minus in-service instances above zero for ten minutes: launches are failing.
Three rules keep the alarm set healthy. Use datapoints to alarm of at least 2 of 3 or 3 of 5 for utilisation metrics so a single spike does not page. Treat INSUFFICIENT_DATA as an alarm for anything that should always report; a silent instance is a dead instance. Use composite alarms to page once for an outage that trips five underlying alarms.
Anomaly detection, dashboards and Logs Insights
Anomaly detection fits a band to a metric's history and alarms when it leaves the band. It is good for request counts, latency and error rates where the normal range varies by time of day; it is poor for metrics that should simply stay below a number.
Dashboards are cheap and worth building per environment: one row per tier (edge, compute, data, queues) with the alarm-backed metrics and a text widget linking to the runbook. Cross-account and cross-region dashboards are supported through CloudWatch cross-account observability, which is worth enabling in a multi-account landing zone.
Logs Insights queries log groups with a SQL-like syntax, and metric filters turn log patterns into metrics you can alarm on: count of ERROR lines per minute, count of Out of memory, count of a specific exception. This is the quickest route to application-aware alerting without touching application code.
Container Insights and Lambda Insights add deeper metrics for ECS, EKS and Lambda; Application Signals adds service-level latency, error and request metrics with traces through the OpenTelemetry-based agent. All three are paid features and are worth switching on selectively rather than everywhere.
What CloudWatch does not do well
- Anything outside AWS. On-premises servers, colocation, other clouds and network devices need the agent (servers only) or a different platform entirely. SNMP is not supported.
- Host-level detail at scale. Per-process and per-service monitoring across hundreds of instances is expensive as custom metrics and awkward to alarm on.
- Trend and forecast alerting. Metric math and anomaly detection cover some cases; a "disk full in 20 hours" trigger is one line in Zabbix and a project in CloudWatch.
- Alert management. No acknowledgement, escalation timers, dependencies or maintenance windows. Those live in whatever SNS sends to, which is why a NOC platform or PagerDuty sits in front of it.
- Retention control. Metrics are retained on a fixed schedule (one-minute data for 15 days, five-minute for 63 days, one-hour for 15 months). Long-term capacity trends need export or a second store.
- Cost predictability. See below.
What CloudWatch costs
CloudWatch pricing is per metric, per alarm, per dashboard, per GB of logs ingested and stored, per Logs Insights query scanned, per canary run and per Insights-enabled resource, with a free tier that covers small estates. Standard AWS service metrics are free; custom metrics (including every CloudWatch agent metric) are priced per metric per month with volume tiers, and each dimension combination is its own metric. Alarms are priced per alarm per month, with high-resolution and composite alarms costing more.
Logs are where bills grow: ingestion is priced per GB, storage per GB-month, and a chatty application on a busy fleet can ingest terabytes. The controls that keep it sane are log-group retention policies (set them; the default is never expire), sampling debug logs, metric filters instead of queries for alerting, and sending high-volume logs to S3 through Firehose instead of CloudWatch Logs.
Order-of-magnitude for a 200-instance estate with the agent, sensible alarms and moderate logging: low hundreds of dollars per month for metrics and alarms, and whatever the logs come to, which is usually the larger number. Run the AWS pricing calculator with your actual log volume before enabling anything fleet-wide.
CloudWatch plus Zabbix or Prometheus: the hybrid pattern
Most estates we manage use CloudWatch for what only AWS can see and a second platform for everything else:
- Zabbix pulls CloudWatch metrics through the official AWS templates (EC2, RDS, ELB, Lambda, S3, ECS, EKS discovery) using an IAM role with
cloudwatch:GetMetricDataand the relevantDescribepermissions, and adds agent-based host monitoring, SNMP for network devices, on-premises and other-cloud hosts, forecast triggers, dependencies, escalations and maintenance windows. One board, one alert path. Our Zabbix monitoring guide covers the AWS deployment step by step. - Prometheus and Grafana fit Kubernetes-heavy estates: the CloudWatch exporter or YACE scrapes AWS metrics into Prometheus, Grafana dashboards combine them with cluster metrics, and Alertmanager handles routing. Amazon Managed Service for Prometheus and Amazon Managed Grafana remove the operational overhead at a per-sample and per-user cost.
- Datadog or similar when the application teams need APM in the same pane and the budget allows; the AWS integration crawls CloudWatch for you.
The pattern is the same in each case: CloudWatch remains the source for AWS-native metrics and the place where EC2 recovery actions and Auto Scaling policies read from; the second platform owns alerting quality, hybrid coverage and long-term trends.
A setup checklist for a new AWS account
- Enable detailed monitoring on production EC2 instances and Enhanced Monitoring on production RDS.
- Deploy the CloudWatch agent through SSM with a config in Parameter Store; publish memory, disk and the system and application logs.
- Set retention on every log group. Thirty to ninety days is typical; longer goes to S3.
- Create the alarm set above per environment, routed to an SNS topic per severity, with the high-severity topic wired to your on-call tool.
- Use composite alarms for each customer-facing service so an outage pages once.
- Build one dashboard per environment with runbook links.
- Enable cross-account observability from the monitoring account if you run a multi-account landing zone.
- Turn on Container Insights, Lambda Insights or Application Signals only for the workloads whose teams will use them.
- Put budgets and anomaly alerts on the CloudWatch line item itself.
- Decide who acknowledges the alarm at 3am. If the answer is "nobody yet", that is the next problem to solve, not the next widget.
Frequently asked questions
Is AWS CloudWatch enough for infrastructure monitoring?
For a pure-AWS estate with small scale and a team that owns on-call, often yes, once the agent and a disciplined alarm set are in place. For hybrid estates, network devices, large fleets, or anyone who needs escalation and acknowledgement, it needs a platform such as Zabbix or Prometheus alongside it.
Does CloudWatch monitor memory and disk on EC2?
Not by default. Memory, disk space and process metrics come from the CloudWatch agent, which publishes them as custom metrics.
What is the difference between CloudWatch and CloudTrail?
CloudWatch is metrics, logs and alarms about how resources perform. CloudTrail is an audit log of API calls: who did what to which resource. Security monitoring uses CloudTrail (often through CloudWatch Logs); performance monitoring uses CloudWatch.
How do I keep CloudWatch costs under control?
Set log-group retention, avoid high-cardinality custom metric dimensions, use metric filters instead of repeated Logs Insights queries, send bulk logs to S3, and enable Insights products only where a team uses them.
Can Techtweek run CloudWatch monitoring for us?
Yes. Our NOC monitoring services manage CloudWatch alongside Zabbix or Prometheus with 24/7 acknowledgement and escalation, and the cloud infrastructure services team builds the alarm set into the Terraform for every landing zone we deliver.
Work with Techtweek
DevOps, cloud & compliance. CERT-In empanelled, AWS Advanced Partner.
Book a consultation