How CostLens Detects Waste
The criteria CostLens uses to identify wasted, underutilized, and overprovisioned resources across AWS, Azure, and GCP — the thresholds behind each recommendation, the confidence attached to it, and the safeguards that keep new or business-critical resources from being flagged.
Every CostLens recommendation starts from the same question: is this resource costing you money it doesn't need to? This page explains exactly how CostLens answers that — the signals it reads, the thresholds that qualify a resource as waste, how much to trust each finding, and the safeguards that stop it from flagging things you actually need. It applies across AWS, Azure, and Google Cloud, and it's the map that ties together the individual check guides.
The three shapes of waste
CostLens looks for resources that fall into one of three buckets:
| Shape | What it means | Typical example |
|---|---|---|
| Wasted | Provisioned and billing, but not used at all | An unattached disk, a load balancer with no traffic |
| Underutilized | Running continuously while doing very little work | A VM at 3% CPU, a database with no connections |
| Overprovisioned | Sized larger than the workload needs | A function with double the memory it uses, an oversized instance |
The golden rule
CostLens only recommends a change when the resource is actually incurring the cost the change would remove. A stopped instance, a paused database, or a brand-new resource with no usage history is not flagged — an optimization is only real if there's real spend to recover.
How every recommendation is scored
Two dimensions accompany each recommendation so you know what to tackle first and how much to trust it.
Severity — based on the money at stake
Severity is driven purely by the estimated monthly saving, so the biggest opportunities rise to the top:
| Severity | Estimated monthly savings |
|---|---|
| Critical | $500 or more |
| High | $100 – $499 |
| Medium | $20 – $99 |
| Low | under $20 |
Confidence — how strong the evidence is
| Confidence | What's behind it |
|---|---|
| High | Direct evidence — an unattached resource, zero traffic, or the cloud provider's own recommendation — over a complete data window. |
| Medium | A utilization measurement with good coverage, or a tag/name-based heuristic. |
| Low | A short observation window or a single weak signal. Shown, but de-prioritised. |
You can filter the Recommendations page by both, so you can focus on, say, only High-confidence Critical findings first.
Safeguards that prevent false positives
These rules apply to every check, and they're what let you trust the list without second-guessing each item:
Lifecycle-state awareness
Stopped, deallocated, or paused resources are skipped — they aren't billing for compute, so there's nothing to recover. CostLens won't tell you to "schedule" a machine that's already off.
Minimum observation window
A resource must be old enough to judge. A weekday schedule, for example, claims a resource is idle at nights and on weekends — so CostLens waits until it has observed at least a full weekly cycle (7 days) before recommending one. A one-day-old instance is never flagged for scheduling.
Seasonal-pattern suppression
Some resources are busy only at predictable times — a payroll job that spikes monthly, a service that peaks on weekends. When CostLens detects a strongly periodic pattern, it lowers the finding's urgency rather than treating a real recurring peak as waste.
Production protection
Resources tagged or named as production are excluded from schedule and stop recommendations, so a business-critical workload is never proposed for shutdown.
Size floors
Trivially small resources (tiny buckets, small snapshots, negligible databases) are ignored — the goal is meaningful savings, not noise.
The scenarios CostLens detects
Each row links to the detailed guide for that check, where you'll find the exact mechanism, permissions, and remediation.
Idle and underutilized compute
VMs, instances, and Kubernetes node pools running around the clock while doing little work.
| What we look for | Typical criteria | What we recommend |
|---|---|---|
| Non-production instance running 24/7 | Low CPU (under ~20%) over the observed window | A weekday off-hours schedule (~70% saving) |
| Over-provisioned instance | Sustained CPU/memory/network below the instance type's headroom (14 days) | Right-size one size down — Azure · GCP |
| Idle virtual machine | Average CPU below 5% over 14 days | Deallocate/stop or right-size — Azure · GCP |
| Stopped instance still billing for storage | Stopped for 7+ days with attached disks | Snapshot and clean up |
| Idle Kubernetes node pool | Average CPU below 5% over 14 days | Scale to zero or remove (EKS/AKS/GKE) |
| Over-provisioned or well-utilized node pool | CPU 5–25% → downsize · CPU above 25% → Spot | Right-size or move to Spot |
Overprovisioned CPU, memory, storage, and networking
Capacity allocated well above what the workload sustains.
| What we look for | Typical criteria | What we recommend |
|---|---|---|
| Function with excess memory | Peak memory usage below 40% of allocated (14 days) | Lower the memory |
| Over-allocated database storage | More than 60% free (AWS), or under 40% used (Azure/GCP) | Right-size storage — RDS · Azure · GCP |
| Over-provisioned Cosmos DB throughput | Consumed RU below ~30% of provisioned | Lower RU/s or autoscale |
| Premium disk with low I/O | Very low sustained IOPS on a premium tier | Downgrade the tier — Azure · GCP |
| EBS volume still on gp2 | Any gp2 volume (gp3 is cheaper at equal performance) | Migrate gp2 → gp3 |
Unattached and unused storage
Volumes, disks, and snapshots that bill monthly but aren't attached to anything.
| What we look for | Typical criteria | What we recommend |
|---|---|---|
| Unattached volume or managed disk | In the "available" (unattached) state | Snapshot if needed, then delete — Azure · GCP |
| Orphaned snapshot | Source volume no longer exists | Delete the orphan — Azure · GCP |
Unused load balancers, IP addresses, and networking
Networking resources that carry a standing charge while serving no traffic.
| What we look for | Typical criteria | What we recommend |
|---|---|---|
| Load balancer with no traffic | Zero requests over 7 days, or no healthy backends | Delete it — AWS · Azure · GCP |
| Unassociated IP address | Not attached to any resource | Release it — AWS · Azure · GCP |
| Idle NAT gateway | No subnet attached, or negligible throughput | Delete it — AWS · Azure · GCP |
| Idle VPC endpoint | Under ~1 GB/day of traffic | Remove the endpoint |
Low-utilization databases and managed services
Managed databases and caches running continuously with almost no activity.
| What we look for | Typical criteria | What we recommend |
|---|---|---|
| Idle database | Fewer than ~5 connections/day, or CPU under 15%, on 10+ of 14 days | Stop, schedule, or downsize — RDS · Azure SQL · Cloud SQL |
| Idle warehouse or cache | No queries / negligible throughput | Pause or downsize — Redshift · Memorystore |
Orphaned resources
Resources whose parent workload no longer exists.
| What we look for | Typical criteria | What we recommend |
|---|---|---|
| Stranded snapshot, disk, or address | Parent resource positively confirmed deleted | Delete the orphan (see the storage guides above) |
| Recommendation for a deleted resource | The resource was removed after the finding was raised | CostLens auto-resolves the stale recommendation on the next sync |
Expired test, development, and temporary environments
Non-production resources that only need to run during working hours.
| What we look for | Typical criteria | What we recommend |
|---|---|---|
| Dev / test / staging resource on 24/7 | Tagged or named non-production, running outside business hours | A weekday off-hours schedule — EC2 · Azure VM · GCP VM |
CostLens schedules — it doesn't delete environments
For dev/test resources, CostLens recommends turning them off outside business hours (a fully reversible ~70% saving), not deleting them. Automatically tearing down an "expired" environment would require an explicit expiry/TTL tag on the resource, so CostLens deliberately takes the safe, reversible action instead.
Duplicate, redundant, and oversized resources
Storage that accumulates cold data, old versions, and untagged images — plus oversized configurations.
| What we look for | Typical criteria | What we recommend |
|---|---|---|
| Bucket with no lifecycle/tiering policy | Holding cold data above a size floor | Add a lifecycle rule — S3 · Azure · GCP |
| Versioned bucket keeping every old version | No noncurrent-version cleanup rule | Add a cleanup rule — S3 · Azure · GCP |
| Image registry with no retention policy | Unbounded image history | Add a retention policy — ECR · ACR · Artifact Registry |
Inefficient autoscaling
Scaling groups pinned to a high fixed baseline instead of scaling with demand.
| What we look for | Typical criteria | What we recommend |
|---|---|---|
| Scaling group with a high static size | Low sustained CPU across the group | Lower the baseline and enable demand-based autoscaling — ASG · VMSS · MIG |
Unused commitments, reservations, and savings plans
Two opposite problems: on-demand spend that should be under a commitment, and commitments that are under-used or about to lapse.
| What we look for | Typical criteria | What we recommend |
|---|---|---|
| Steady usage not under commitment | Reserved Instance / Savings Plan coverage below 70% | Consider a commitment for the stable baseline — RI coverage · SP coverage |
| Commitment that's under-used | Utilization below 90% (AWS) or 75% (Azure/GCP) | Resize or reallocate — Azure · GCP |
| Reservation about to expire | Expiring within 90 days | Renew before it lapses to on-demand |
Commitments are always advisory
Reservations and Savings Plans commit real money for one to three years, so CostLens never buys them automatically. It shows the economics — break-even, term, expected savings — and you make the purchase decision.
What CostLens does — and doesn't — do
Being clear about the boundaries here so nothing is a surprise:
- Savings figures are estimates for prioritisation. Cloud bills are metered at the service and region level, not per individual resource, so a per-resource saving is a list-price estimate — accurate enough to rank opportunities, and corroborated by your actual spend trends, but not a line-item invoice.
- Utilization needs history. Several checks require a full observation window before a resource qualifies. A resource connected or created very recently may not appear as a finding until enough data exists — this is intentional, to avoid premature recommendations.
- "Duplicate" means redundant, not identical. CostLens flags redundant storage tiers, stale versions, and oversized configurations. It does not infer that two independently-running resources are functional duplicates of each other.
- Environments are scheduled, not reaped. As noted above, dev/test resources are recommended for off-hours scheduling, not deletion.
Acting on recommendations safely
Every recommendation is labelled by how reversible the fix is:
| Action type | Examples | How CostLens applies it |
|---|---|---|
| Reversible | Schedules, right-sizing, deallocate/stop, storage-tier changes | Can be applied automatically with one-click rollback (see Auto-Fix) |
| Irreversible | Deleting volumes, snapshots, IP addresses | Requires explicit typed confirmation before applying |
| Advisory | Commitment purchases, capacity decisions | Recommended only — you take the action in your own tooling |
You can review everything that's been applied, and roll back reversible changes within the rollback window, on the Fix History page.
Related
- Recommendations — how findings are surfaced, filtered, and prioritised
- Auto-Fix — approval workflow and automatic remediation
- Fix History — what's been applied, and rolling changes back
- Kubernetes Optimization — the node-pool detection model in depth