zombiecost
Find the zombie resources in your AWS account: things that should be dead but still bill you every month.
Find idle and forgotten AWS resources and see what they cost you every month.
One read-only scan. One table. A number at the bottom you can act on today.
What it finds
| Check | What it flags | How cost is estimated |
|---|---|---|
ebs-unattached |
EBS volumes attached to nothing | GB-month price by volume type |
eip-unused |
Elastic IPs not associated with anything | Hourly unused-EIP charge |
snapshots-old |
Snapshots older than 90 days that no AMI you own uses | GB-month snapshot price |
ec2-idle |
Running instances averaging under 3% CPU over the lookback window | On-demand hourly price |
nat-idle |
NAT gateways that moved under 1 GiB in the lookback window | Hourly NAT charge |
rds-idle |
RDS instances with zero connections over the lookback window | Instance class + storage |
lb-unused |
Load balancers with no registered targets, or ALBs that served 0 requests | Hourly LB charge |
s3-stale |
Buckets nothing has written to in 180 days, with their size and storage class | GB-month by storage class |
Prices are rough us-east-1 on-demand numbers. The goal is order of magnitude, not an invoice.
Checks that depend on usage history (ec2-idle, rds-idle, nat-idle, lb-unused)
ignore resources younger than 3 days, so a freshly launched instance is never
reported as idle. s3-stale can see writes but not reads; it says so in every
finding, because reads are invisible without paid request metrics.
Install
pip install zombiecost
Or from a clone:
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
Run
zombiecost # every enabled region, default profile
zombiecost --profile prod --regions eu-west-1,us-east-1
zombiecost --days 30 --json report.json # longer lookback, machine-readable output
zombiecost --redact # placeholders instead of IDs, names and IPs: safe to paste publicly
Permissions
The scan is read-only. Attach ReadOnlyAccess, or this minimal policy:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"sts:GetCallerIdentity",
"ec2:DescribeRegions",
"ec2:DescribeVolumes",
"ec2:DescribeAddresses",
"ec2:DescribeSnapshots",
"ec2:DescribeImages",
"ec2:DescribeInstances",
"ec2:DescribeNatGateways",
"rds:DescribeDBInstances",
"elasticloadbalancing:DescribeLoadBalancers",
"elasticloadbalancing:DescribeTargetGroups",
"elasticloadbalancing:DescribeTargetHealth",
"s3:ListAllMyBuckets",
"s3:GetBucketLocation",
"s3:ListBucket",
"cloudwatch:GetMetricStatistics",
"cloudwatch:ListMetrics"
],
"Resource": "*"
}]
}
Tests
pytest
Tests run against moto, no AWS account needed.
Roadmap
- Unused KMS keys, Secrets Manager secrets and VPC endpoints (small, fixed monthly charges that add up)
- Stopped instances still paying for their volumes
- Old AMIs and the snapshots behind them
- Hosted version: cross-account role, weekly scans, Slack alerts
Metadata
Release files for zombiecost 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| zombiecost-0.1.1.tar.gz | 17.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| zombiecost-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 38.0 kB
Release files / zombiecost-0.1.1.tar.gz
| Download URL | zombiecost-0.1.1.tar.gz |
|---|---|
| Size | 17.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0b5f912bc38f9bd482b53091dd7a1f953fda343e58fe59bc85d3174edbed740c
|
|
BLAKE2b-256 checksum How to use checksums |
82401cc667849f16e542c2476306aa983aade5d34c001808f87de234b0aaa2ca
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.
Transparency logRelease files / zombiecost-0.1.1-py3-none-any.whl
| Download URL | zombiecost-0.1.1-py3-none-any.whl |
|---|---|
| Size | 20.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
40d410437521942e0eb79950ca47aaa18e6814a31cb04ab6918d5a4cb088c13d
|
|
BLAKE2b-256 checksum How to use checksums |
c78150b400d0c349ebc72ffcc6cf806d8a0984e580391d7f338fc630ba3dd6d5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.
Transparency log