Almost every engineering team has had the same moment: the monthly AWS or GCP invoice arrives, it's higher than last month again, and nobody can point to a single reason why. Usage hasn't doubled. No major new features shipped. Yet the bill keeps climbing.
Cloud cost overrun is rarely caused by one big mistake. It's usually the accumulation of small decisions, each reasonable at the time, that nobody ever revisits. This post covers where that money actually goes, and the specific, practical steps to bring it back down without disrupting your infrastructure.
Why Cloud Costs Creep Up Without Anyone Noticing
Cloud billing has a structural quirk that makes overspend easy: it's usage-based, but "usage" includes resources that are provisioned and idle, not just resources that are actively doing work. A server that's running but receiving no traffic still costs the same as one handling real load.
Combine this with how teams typically operate, provisioning resources is fast and easy, while decommissioning them requires someone to notice, decide it's safe, and take action, and you get a system that's biased toward growth. Nothing actively removes unused resources; someone has to choose to.
Where the Money Actually Goes: 6 Common Sources of Overspend
1. Oversized Instances
The Problem
Instances are often sized based on anticipated peak load, sometimes peak load that was estimated early on and never revisited. If actual usage runs well below that estimate, you're paying for capacity that's rarely, if ever, used.
How to Find It
Both AWS (via Cost Explorer and Compute Optimizer) and GCP (via Recommender) provide built-in tools that compare provisioned resources against actual utilization and flag oversized instances directly. Look specifically at CPU and memory utilization over a 2-4 week window, instances consistently running below 20-30% utilization are strong candidates for downsizing.
The Fix
Downsize incrementally, one tier at a time, and monitor for impact. Most workloads can be right-sized without any noticeable performance change, since the original sizing included generous headroom that was never needed.
2. Idle Non-Production Environments
The Problem
Staging, QA, demo, and development environments often run 24/7, even though they're only used during business hours, and sometimes only a few days a week.
How to Find It
Check the usage patterns of non-production environments specifically. If a staging environment shows near-zero traffic outside 9am-6pm on weekdays, it's running unused roughly 75% of the time.
The Fix
Schedule non-production environments to shut down outside business hours using automation (most cloud providers support scheduled start/stop, or this can be handled with a simple scheduled script). For environments used infrequently, consider spinning them up on-demand rather than running continuously. This single change often produces some of the largest percentage savings of any optimization, because the waste is so consistently 100% during off-hours.
3. Unattached Storage and Orphaned Resources
The Problem
When instances are terminated, their attached storage volumes (EBS volumes on AWS, persistent disks on GCP) often aren't automatically deleted. Over time, these orphaned volumes accumulate, each one billed continuously despite being attached to nothing.
How to Find It
Both platforms allow filtering storage volumes by attachment status. Look for volumes with no attached instance, especially ones that have been unattached for more than a few weeks.
The Fix
Before deleting, snapshot any orphaned volumes that might contain useful data, then delete the volumes themselves. Going forward, configure instance termination settings to automatically delete attached volumes (where appropriate), or set up a recurring audit to catch orphaned resources before they accumulate.
4. Inefficient Data Transfer
The Problem
Data transfer costs, particularly between regions, between cloud providers, or out to the public internet, are often overlooked because they're billed separately from compute and storage, and the per-GB cost looks small until volume scales up.
How to Find It
Review the network/data transfer line items on your bill specifically. Cross-region transfer between services that don't need to be in different regions, or frequent large transfers to external services, are common culprits.
The Fix
Where possible, co-locate services that communicate frequently in the same region. For data that needs to be served externally (e.g., to users), use a CDN, which is typically far cheaper than serving directly from compute instances for high-volume content.
5. Build and CI/CD Infrastructure Costs
The Problem
CI/CD runners, build caches, and artifact storage are easy to overlook in cost reviews because they're "developer tooling" rather than "production infrastructure," but they can represent a significant portion of spend, especially for teams running frequent builds.
How to Find It
Check whether CI/CD runners are sized appropriately for the jobs they run, and whether build artifacts and caches are being cleaned up on a schedule or accumulating indefinitely in storage.
The Fix
Right-size CI/CD runners the same way you would production instances. Set retention policies on build artifacts and caches so old, unused data doesn't accumulate in storage indefinitely. If build volume varies significantly by time of day or week, consider runners that scale down to zero when not in use rather than running continuously.
6. Reserved Capacity Mismatches
The Problem
Reserved instances or committed use discounts (savings plans on AWS, committed use discounts on GCP) offer significant discounts in exchange for committing to usage levels. But if actual usage has changed since the commitment was made, either growing past it or shrinking below it, you can end up paying for commitments that no longer match reality.
How to Find It
Compare your current reserved/committed capacity against actual current usage. Both AWS and GCP provide utilization reports for reserved capacity specifically.
The Fix
If usage has grown past commitments, you're paying on-demand rates for the excess, adjusting commitments upward typically captures additional discount. If usage has shrunk, commitments often can't be canceled but can sometimes be modified or resold (on AWS, via the Reserved Instance Marketplace). Either way, this is worth reviewing whenever usage patterns shift significantly, not just when commitments are first made.
A Practical Approach: The 80/20 of Cloud Cost Review
You don't need to review every line item to make meaningful progress. In most cases, the largest savings come from a small number of areas:
Start with non-production environment scheduling (item 2), since it's typically the fastest to implement and produces immediate, measurable savings. Then move to oversized instances (item 1) using your cloud provider's built-in recommendations, these are designed specifically to surface this issue with minimal manual analysis. Finally, do a one-time sweep for orphaned resources (item 3), which tends to accumulate "free money" that's just sitting on the bill.
These three areas alone often account for the majority of recoverable spend, and none of them require architectural changes or carry meaningful risk to production systems.
Cost Optimization as an Ongoing Process, Not a One-Time Project
The reason cloud costs creep up gradually is the same reason a one-time cleanup doesn't permanently fix the problem: new resources get provisioned, new environments get created, and without ongoing attention, the same patterns re-emerge over months.
The most effective long-term approach is a lightweight recurring review, monthly or quarterly, that checks for the same patterns: new oversized instances, newly idle environments, newly orphaned storage. This doesn't need to be a large effort; often it's a 30-minute review of the same cost reports each month.
Where Cloud Costs Fit Into the Bigger Picture
Cloud cost overrun is often a symptom rather than an isolated issue. Teams with unmanaged cloud costs frequently also show some of the other signs covered in our post on signs your DevOps setup is costing you more than it should, since both tend to stem from the same root cause: nobody owning operational efficiency as an ongoing responsibility.
If you're seeing cost issues alongside other friction, slow pipelines, environment drift, frequent incidents, a broader DevOps audit will likely surface the connections between them, and often reveal that fixing one improves the others.
