Reduce Cloud Infrastructure Costs by 40% in One Sprint
Most cloud bills can be cut by 30 to 40 percent without touching a single feature or degrading reliability, because most cloud waste is not caused by expensive architecture — it is caused by resources that are oversized, idle, or forgotten. The work is unglamorous and largely mechanical: find what is running below capacity, find what is running that nobody uses, and pay differently for the workloads that are genuinely stable. Running a client through the moves below took roughly 40 percent off the next invoice within a single sprint. None of them required an architectural change, and none of them made the system slower. What follows is the order I work in, why each move produces savings, and the specific ways each one can backfire if applied without checking the workload first.
Why cloud costs drift upward on their own
Nobody decides to overspend. The drift is structural. Instances are provisioned for launch-day estimates and never revisited. Environments are created for a project and outlive it. Features get enabled during an incident and stay enabled. Every one of these is individually reasonable and permanent by default, because nothing in a cloud console ever asks whether you still need something.
The consequence is that cost optimization is mostly archaeology. You are not redesigning the system; you are finding the decisions that were correct eighteen months ago and are not correct now.
Before changing anything, get a cost breakdown by service and by tag. If your resources are not tagged by environment and owner, that is the first task, because untagged spend is unattributable spend and you cannot reason about it.
1. Rightsize instances against real utilization
Most teams run instances at 10 to 20 percent average CPU. That is not prudent headroom; that is paying for four times the machine you are using.
AWS Compute Optimizer and GCP's recommender will identify candidates directly from observed utilization. Both are free and both are more reliable than intuition, because intuition tends to remember the worst incident rather than the typical day.
The caveat that matters: size against peak and percentiles, not averages. An instance averaging 15 percent CPU that hits 90 percent during a nightly batch window will fail if you halve it. Look at p95 and p99 utilization over at least two weeks, and make sure the window covers whatever your monthly cycles are.
Memory is the more common trap. CPU utilization is reported by default; memory frequently is not, and a rightsizing decision made on CPU alone will occasionally produce an instance that runs out of memory under load. Install the agent that reports memory before you resize anything stateful.
2. Which workloads belong on spot instances?
Spot and preemptible instances cost 60 to 90 percent less than on-demand, in exchange for the provider being able to reclaim them with short notice.
That trade is excellent for anything interruptible and retryable: CI/CD runners, batch processing, data pipeline jobs, dev and staging environments, and stateless workers behind a queue. If the work can be restarted without a human noticing, it is a spot candidate.
It is a poor trade for anything holding state in memory, anything where a restart drops a user session, and single-instance databases. The interruption rate is lower than most teams fear, but the correct question is not how often interruption happens — it is what happens when it does. If the answer is "the job restarts," use spot. If the answer is "we find out from a customer," do not.
The practical approach is a mixed fleet: a baseline of on-demand or reserved capacity sized to handle your floor, with spot capacity absorbing everything above it.
3. Commit to capacity you have already proven you need
If you have run the same instance type continuously for three months or more, you are not making a prediction by committing to it for a year — you are describing what already happened. Reserved instances and savings plans return 30 to 40 percent for that commitment with no architectural change whatsoever.
Two rules keep this safe. Commit to your floor, not your ceiling: reserve the capacity you are certain you will still be running in twelve months, and leave growth on on-demand or spot. And prefer the more flexible commitment types where the discount difference is small, because a commitment locked to one instance family becomes a liability the moment you want to change instance families.
This is the highest return per unit of effort on this list. It is also the one teams postpone longest, because a one-year commitment feels like a bigger decision than it is when the alternative is paying the same money in monthly instalments at a worse rate.
4. Find and delete what nobody is using
Idle resources are pure waste, and they accumulate invisibly because nothing bills you loudly enough to notice a single one.
The usual inventory: unattached storage volumes left behind when instances were terminated, allocated static IPs pointing at nothing, load balancers with no healthy targets, old snapshots and machine images retained by a policy no one revisits, dev environments running twenty-four hours a day for a team that works eight, and orphaned data in storage buckets with no lifecycle rules.
Automate the scan rather than doing it once. A weekly job that lists candidates and posts them to a channel converts this from a cleanup project into routine hygiene. Report rather than auto-delete, at least initially — the storage volume that looks abandoned is occasionally the one holding a backup someone needs.
Non-production environments deserve a scheduler. Development and staging that run only during working hours cost roughly a quarter of what they cost running continuously, and nobody is inconvenienced by staging being unavailable at 3am.
5. Data transfer is where the bill hides
Egress is the line item that surprises people, because unlike an instance it does not appear as a thing you provisioned. It appears as a consequence of how your services talk to each other.
Cross-region and cross-availability-zone traffic between chatty services is the usual culprit. Services that exchange high request volumes should sit in the same zone where your availability requirements allow it. Multi-AZ is a reliability decision that has a bandwidth cost, and it should be made deliberately rather than by default.
Putting a CDN in front of static assets moves that traffic off origin egress and onto cheaper edge delivery, while also making the site faster — one of the few changes on this list that improves cost and user experience simultaneously.
Also check what is crossing the boundary at all. Log shipping, backup replication, and monitoring agents can move surprising volumes, and they are easy to overlook precisely because they are infrastructure rather than product traffic.
Storage tiering, the move most lists omit
Object storage is priced by access pattern as well as volume, and almost nobody revisits the tier after upload. Data written once and read rarely — backups, raw logs, exports, processed source files, anything older than a quarter — is usually sitting in the most expensive tier by default.
Lifecycle rules fix this without an application change: transition objects to infrequent-access after thirty days, to archival storage after ninety, and expire what has a genuine end of life. On buckets that have been accumulating for years, this is frequently a larger saving than rightsizing, and it is entirely mechanical.
Two things to check first. Archival tiers charge for retrieval and impose a minimum storage duration, so data you actually read monthly costs more in a cold tier, not less. And versioned buckets retain every previous version indefinitely unless a rule says otherwise — the noncurrent versions are often larger than the current ones. Check whether versioning is on before you conclude the bucket is the size you think it is.
Do this in the right order
Sequence matters, because two of these moves interfere with each other. Delete idle resources and rightsize first, then buy reservations — committing to capacity before you have rightsized locks in the oversized footprint you were about to fix.
A workable sprint: tag and break down spend, delete the obviously idle, rightsize against p95 utilization, move interruptible workloads to spot, then commit to whatever remains stable. That order is also roughly least-risky to most-risky, so an early stop still leaves you better off.
What to watch afterwards
Cost optimization decays. Without a check, the same drift produces the same problem in a year.
Set a budget alert with a threshold you would actually act on, keep the weekly idle-resource scan running, and put a recurring calendar entry to review utilization each quarter. The single most useful metric is cost per unit of business value — per active user, per order, per thousand requests — because unlike total spend it distinguishes a bill that grew because the business grew from a bill that grew because something is wasteful.
If your cost per unit is flat or falling while total spend rises, that is growth. If cost per unit is rising, that is drift, and it is time to run this list again.
Need help applying this to your project?
Book a free consultation →