cloudwatch-janitor 🧹
Find the CloudWatch waste hiding in your AWS bill — in one read-only command.
CloudWatch costs creep up silently: log groups that keep data forever, alarms watching resources that were deleted months ago, dashboards nobody has opened since 2024. cloudwatch-janitor scans your account, lists every finding, and estimates what it's costing you per month.
It never modifies anything. Four read-only API calls, that's it.
CHECK RESOURCE ISSUE EST. $/MO
---------------- ------------------------------ ------------------------------------------------- ---------
log-retention /aws/lambda/etl-processor No retention policy (312.40 GB stored, growing…) 9.37
log-retention /aws/eks/prod-cluster/apps No retention policy (88.10 GB stored, growing…) 2.64
idle-log-groups /aws/lambda/old-webhook-fn No incoming events in 90 days (12.33 GB stored) 0.37
stale-alarms db-conn-alarm-legacy INSUFFICIENT_DATA for 214 days (metric likely…) 0.10
stale-dashboards team-x-dashboard Not modified in 431 days 3.00
5 finding(s), estimated savings: $15.48/month (rough estimate, standard pricing)
Install
pip install cloudwatch-janitor
Or straight from GitHub:
pip install git+https://github.com/varunmj/cloudwatch-janitor.git
Or clone and run directly:
git clone https://github.com/varunmj/cloudwatch-janitor.git
cd cloudwatch-janitor && pip install -e .
Usage
# Scan the default profile/region
cloudwatch-janitor
# Specific profile and region
cloudwatch-janitor --profile prod --region us-west-2
# Only some checks
cloudwatch-janitor --checks log-retention,stale-alarms
# JSON output (pipe it, save it, alert on it)
cloudwatch-janitor --json > findings.json
What it checks
| Check | What it finds | Why it matters |
|---|---|---|
log-retention |
Log groups with no retention policy | Logs are stored forever at ~$0.03/GB-month, growing every day |
idle-log-groups |
Log groups with zero incoming events in 90 days but data still stored | Usually left behind by deleted Lambdas/services — safe to remove |
stale-alarms |
Alarms in INSUFFICIENT_DATA for 30+ days |
The metric is probably gone; you're paying for monitoring that monitors nothing |
stale-dashboards |
Dashboards not modified in 180+ days | Dashboards beyond the first 3 cost $3/month each |
Cost estimates are deliberately rough (us-east-1 standard pricing) — they're there to help you prioritize, not to reconcile your bill.
Permissions
Least privilege, read-only. Attach docs/iam-policy.json:
{
"Action": [
"logs:DescribeLogGroups",
"cloudwatch:DescribeAlarms",
"cloudwatch:GetMetricData",
"cloudwatch:ListDashboards"
]
}
Contributing
New checks are the easiest way to contribute — each check is a single file in cw_janitor/checks/ exposing CHECK_ID, TITLE, and run(session, region) -> list[Finding]. See CONTRIBUTING.md and the open issues for ideas (unused custom metrics, orphaned metric filters, Contributor Insights rules...).
License
MIT
Metadata
Release files for cloudwatch-janitor 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| cloudwatch_janitor-0.1.0.tar.gz | 9.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| cloudwatch_janitor-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 21.3 kB
Release files / cloudwatch_janitor-0.1.0.tar.gz
| Download URL | cloudwatch_janitor-0.1.0.tar.gz |
|---|---|
| Size | 9.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d156d48a3d70a3c1e9d92c32fe3ed9b311e9abbebb0007b7dfea5d35138adb78
|
|
BLAKE2b-256 checksum How to use checksums |
d74c98fc7a207f69adb28e7198c226c77177fc6342ad5038a6c5638459a98405
|
| 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 Jul 30, 2026.
Transparency logRelease files / cloudwatch_janitor-0.1.0-py3-none-any.whl
| Download URL | cloudwatch_janitor-0.1.0-py3-none-any.whl |
|---|---|
| Size | 11.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2b02dfbfc40a0ee2c8463d2fcd755d47028b84f86895708adc33ab052aa9f0fe
|
|
BLAKE2b-256 checksum How to use checksums |
c5861578eda30b25162e61c88aa82381d045a77fabe8f42c9c465587e82857d2
|
| 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 Jul 30, 2026.
Transparency log