Nuberio
  • Pricing
  • Blog
  • Tools
  • Security
  • About
Run free audit →
Nuberio

Free AWS health audit.

Run free audit →

Product

  • Pricing

Resources

  • Blog
  • Free Tools
  • CloudWatch Alarms

Company

  • Security
  • About

Connect

  • X (Twitter)
  • LinkedIn

© 2026 Nuberio. All rights reserved.

Built at 2am, for a 2am.

← All posts

EC2 Has No Memory or Disk Alarms Until You Install the CloudWatch Agent

August 10, 2026·9 min read

An EC2 instance can run at 40% CPU, healthy network throughput, and a passing status check right up to the moment a process gets OOM-killed or the root volume fills up and every write starts failing. None of the standard AWS/EC2 alarms would have shown a single warning sign — because none of them measure memory or disk usage in the first place. That's not a configuration mistake; it's how EC2 works by default, and most teams don't find out until the first outage it causes.

  • What metrics does EC2 collect by default?
  • Why doesn't EC2 report memory or disk usage on its own?
  • What actually happens when nobody's watching memory and disk?
  • How do you install the CloudWatch Agent on EC2?
  • What should the CloudWatch Agent config.json look like?
  • What alarms should you set on the new metrics?
  • Does an audit tool catch this automatically?

What metrics does EC2 collect by default?

Out of the box, EC2 publishes CPU utilization, network in/out, EBS I/O, and instance/system status checks to the AWS/EC2 namespace — all hypervisor-visible, hardware-level signals. Nothing in that list touches memory usage or filesystem free space, because those live inside the guest operating system, which the hypervisor can't see into.

MetricWhat it measuresCovers memory or disk space?
CPUUtilization% of allocated vCPU in useNo
NetworkIn / NetworkOutBytes sent/received on all interfacesNo
DiskReadOps / DiskWriteOps / DiskReadBytes / DiskWriteBytesEBS volume I/O operations and throughputNo — device-level I/O speed, not how full the filesystem is
StatusCheckFailed (+ _Instance / _System)Whether the instance or underlying host is reachable at allNo — fires after a hard failure, not before one
CPUCreditBalance / CPUCreditUsage (T-series only)Burstable credit balanceNo
The DiskReadBytes/DiskWriteBytes metrics are the single most common false sense of security here — teams see "disk metrics" already flowing to CloudWatch and assume disk-space monitoring is covered. It isn't. Those measure how fast the EBS device is being read from and written to, not how much free space is left on the filesystem mounted on top of it. A volume can be at 100% throughput or 100% full — they're unrelated numbers.

Why doesn't EC2 report memory or disk usage on its own?

The hypervisor sits below the guest OS and can measure what crosses the virtual hardware boundary — CPU cycles, network packets, disk I/O requests. It has no visibility into what's happening inside the OS itself: how much of that memory is actually in use versus cached, or how full a specific filesystem is. Getting those numbers requires an agent running inside the instance, reading them the same way `free` or `df` would.

That's exactly what the CloudWatch Agent is: a small process installed on the instance that reads OS-level stats (`/proc/meminfo`, `df`, and equivalents) and pushes them to CloudWatch as custom metrics under the CWAgent namespace — separate from the free AWS/EC2 namespace metrics, and billed accordingly.

What actually happens when nobody's watching memory and disk?

By the time StatusCheckFailed fires from a memory or disk problem, the failure has already happened — the metric only tells you the instance is now unreachable, not that it was heading there. Memory and disk alarms exist to catch the problem in the 15-30 minutes before that point, while there's still time to act.

This isn't hypothetical for EC2 specifically — AWS's own status-check documentation lists memory exhaustion and disk I/O errors as two of the direct causes of a failed instance status check: the OOM killer terminates critical OS processes, or a corrupted root volume forces the filesystem read-only. Both are preceded by a period of rising memory or disk usage that a CWAgent-based alarm would have caught, and both currently show as a completely clean CPUUtilization/NetworkIn/StatusCheckFailed dashboard right up until the moment they don't.

How do you install the CloudWatch Agent on EC2?

Four steps: attach the right IAM permissions, install the agent package, write a config file describing which metrics to collect, then start the agent pointed at that config. All four are one-time setup per instance (or per AMI/launch template, for fleets).

  1. Attach the AWS-managed CloudWatchAgentServerPolicy to the instance's IAM role — this is what authorizes the agent to write metrics to CloudWatch.
  2. Install the package: sudo yum install amazon-cloudwatch-agent on Amazon Linux 2/2023, or the equivalent apt/dpkg install on Ubuntu/Debian after adding the AWS package repo.
  3. Save a config.json describing which metrics to collect (see the next section) — either as a local file or in SSM Parameter Store for fleet-wide rollout via Systems Manager.
  4. Start the agent against that config with the amazon-cloudwatch-agent-ctl command, shown below.

What should the CloudWatch Agent config.json look like?

The minimum config to close the memory/disk gap is small — three metric categories (mem, disk, swap), each with a measurement array. The published metric name is the category and measurement joined together, so mem + used_percent becomes mem_used_percent in CloudWatch, and disk + used_percent becomes disk_used_percent.

{
  "agent": {
    "metrics_collection_interval": 60
  },
  "metrics": {
    "append_dimensions": {
      "InstanceId": "${aws:InstanceId}"
    },
    "metrics_collected": {
      "mem": {
        "measurement": ["used_percent"]
      },
      "disk": {
        "measurement": ["used_percent"],
        "resources": ["/"]
      },
      "swap": {
        "measurement": ["used_percent"]
      }
    }
  }
}

"resources": ["/"] scopes the disk metric to the root volume — add more mount paths to that array (or use ["*"] for every mounted filesystem) if the instance has separate data or log volumes worth tracking independently. Save this as /opt/aws/amazon-cloudwatch-agent/etc/cloudwatch-agent.json, then start the agent:

sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
  -a fetch-config -m ec2 -s \
  -c file:/opt/aws/amazon-cloudwatch-agent/etc/cloudwatch-agent.json

The first datapoints typically appear under the CWAgent namespace in the CloudWatch console within one collection interval — 60 seconds with the config above.

What alarms should you set on the new metrics?

Once mem_used_percent, disk_used_percent, and swap_used_percent are flowing, the alarms themselves are ordinary CloudWatch alarms — same as any AWS/EC2 metric, just on the CWAgent namespace instead. A reasonable starting point for most general-purpose workloads:

MetricSuggested thresholdWhy
mem_used_percent> 90% for 15 consecutive minutesGives roughly 15+ minutes of warning on most workloads before memory pressure escalates to an OOM kill
disk_used_percent (root volume)> 85% for 15 consecutive minutesLog files, temp files, and database writes typically start failing well before the volume hits 100%
swap_used_percent> 0% sustained for 10+ minutesAny sustained swap usage means memory pressure has already started — an earlier warning than mem_used_percent alone
These thresholds are a starting point, not an AWS-published standard — memory-hungry workloads (caches, JVMs with large heaps) legitimately run hotter than this, so tune per instance role the same way you'd tune CPUUtilization for a T-series burstable instance.

Does an audit tool catch this automatically?

Not fully, and it's worth being direct about the limitation: Nuberio Audit checks whether your running EC2 instances have alarms on the standard AWS/EC2 namespace metrics — CPUUtilization, StatusCheckFailed, and the rest of the table above. It doesn't currently detect whether the CloudWatch Agent is installed or whether CWAgent-namespace memory/disk alarms exist, because that requires knowing the agent is running in the first place, not just reading CloudWatch's alarm list.

That's exactly the kind of gap worth checking by hand even after running an automated coverage tool — the standard-namespace alarms an audit finds tell you the instance is being watched at the hardware level; they don't tell you anything about what's happening inside the OS.

Frequently asked questions

Does EC2 collect memory usage metrics by default?

No. EC2's default AWS/EC2 namespace only includes hypervisor-visible metrics — CPU, network, EBS I/O, and status checks. Memory usage is invisible to the hypervisor because it's a property of the guest operating system, not the virtual hardware. Getting mem_used_percent into CloudWatch requires installing the CloudWatch Agent inside the instance.

What's the difference between DiskReadBytes/DiskWriteBytes and disk_used_percent?

DiskReadBytes and DiskWriteBytes are default AWS/EC2 metrics measuring EBS device I/O throughput — how much data is being read from or written to the volume per second. disk_used_percent is a CloudWatch Agent metric measuring how full the filesystem mounted on that volume is. A volume can be at 100% I/O throughput and 10% full, or 0% I/O and 100% full — they measure completely unrelated things.

Does the CloudWatch Agent cost extra?

Yes. Metrics published by the CloudWatch Agent (under the CWAgent namespace) are custom metrics, billed the same as any other custom metric published via PutMetricData — see our CloudWatch custom metrics pricing breakdown for the exact per-metric tiers. Three or four metrics per instance (mem, disk, swap) is a small addition compared to what an undetected OOM kill or disk-full outage costs.

Can Nuberio Audit detect whether the CloudWatch Agent is installed?

Not yet. The Audit checks alarm coverage on the standard AWS/EC2 namespace — it doesn't currently detect CWAgent-namespace custom metrics or infer whether the agent is running on a given instance. Run the Audit for standard-namespace coverage, and verify CloudWatch Agent memory/disk alarms separately using the steps in this post.

Related reading

  • → The 12 CloudWatch alarms every small AWS team should have
  • → What "no dedicated SRE" actually means for AWS monitoring
  • → The $0.30 metric: what CloudWatch custom metrics actually cost
  • → EC2 StatusCheckFailed — threshold & debugging guide
  • → EC2 CPUUtilization — threshold & debugging guide
  • → Run a free Nuberio Audit — check your standard EC2 alarm coverage

Not sure your alarm coverage is actually solid?

Run a free Nuberio Audit — hygiene score, missing alarms, and security findings in about 5 minutes.

Run free audit →
N

Nitesh Bhavsar

Founder, Nuberio

Published

August 2026

Updated

August 2026

Have feedback? nitesh@nuberio.com