# Idle running EC2 instance

> Finds running EC2 instances that are near-totally idle for 30 days and recommends review, then stop or schedule.

Source: https://zop.dev/integrations/aws/recommendations/idle-running-ec2-instance

---

## A running instance bills for every second it is up, busy or not

The [instance lifecycle guide](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-lifecycle.html)
lists `running` as the billed state. CPU load does not enter into it: a machine sitting at 1% CPU
costs the same per hour as one at 90%. Stopping ends the compute charge, but
[AWS notes](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/how-ec2-instance-stop-start-works.html)
that attached EBS volumes and associated Elastic IP addresses persist through a stop, and those keep
their own charges.

Instances that nobody uses but nobody switched off are the target here. Instances already stopped
belong to <a href="https://zop.dev/integrations/aws/recommendations/idle-ec2-instance">Idle EC2 Instance</a>.

## Looking at the hourly peaks, not the average

An average can hide a daily job. The hourly maximum shows it:

```bash
aws cloudwatch get-metric-statistics --namespace AWS/EC2 --metric-name CPUUtilization \
  --dimensions Name=InstanceId,Value=i-0123456789abcdef0 \
  --start-time 2026-08-26T00:00:00Z --end-time 2026-09-25T00:00:00Z \
  --period 3600 --statistics Maximum
```

Check `NetworkIn` and `NetworkOut` the same way. With basic monitoring, each datapoint covers 5
minutes, so a byte count divided by 300 gives bytes per second.

## The idle verdict, step by step

1. The instance is `running`, has no known recurring schedule, and is not already off most of the
   time by measured uptime.
2. The CPU data is recent and continuous, not a stale slice from a broken sync.
3. Average `NetworkIn` and `NetworkOut` each stay under 5 MB per 5-minute sample.
4. Hourly peak CPU is under 8%, and hourly average CPU under 5%, in at least 95% of measured hours,
   with at least 168 hours measured.
5. No recurring daily peaks, sustained chatter or network bursts, and a confidence score of at
   least 50 once scattered spikes are weighed.
6. A positive compute cost taken from the bill rather than a rack-rate estimate.

## Instances it never tells you to stop

Names that mark access infrastructure (`bastion`, `jump`, `jumpbox`, `vpn` and similar), standby
roles (`dr`, `standby`, `failover`, `replica`, `backup`) or stateful data services are excluded,
because they are quiet by design. When the brief peaks recur at the same hours on most days, the
instance is running a daily task: ZopNight suggests a schedule that keeps that window on instead of
a stop. When the few peaks cluster near a month boundary, the finding warns you to check for a
month-end batch first.

## The saving is compute only

```text
saving = monthly compute cost of the instance
still billed after a stop = EBS volumes + any Elastic IP
```

## Stopping it safely

1. Confirm with the owner that nothing depends on the instance.
2. Take an AMI so the change is reversible:
   `aws ec2 create-image --instance-id i-0123456789abcdef0 --name pre-stop-backup --no-reboot`
3. Stop it: `aws ec2 stop-instances --instance-ids i-0123456789abcdef0`
4. After the retention period, terminate it and delete volumes you no longer need.
5. If it turns out to have a purpose, put it on an off-hours schedule instead of running 24x7.

**Note**
ZopNight does not stop the instance for you. This finding is advisory, because only the owner
can confirm a quiet machine is truly unused.
