Top data quick wins on AWS: where your storage bill leaks

Introduction

Storage is the part of an AWS bill that grows quietly. Nobody notices a single gp2 volume, a forgotten snapshot, or a logging bucket sitting in Standard for three years. Each line looks trivial. But storage is cumulative by nature. Data gets created, almost never deleted, and rarely moved to a cheaper class once the access pattern cools off. After a couple of years, that quiet accumulation is a meaningful slice of the bill, and almost none of it is doing useful work.

The good news is that storage is also where the lowest-risk savings live. Unlike compute, where rightsizing carries some operational risk, most storage optimizations are either fully reversible or carry no production impact at all. Migrating a volume type, moving an object to a colder class, deleting a detached resource. None of these touch a running application when done correctly. This article walks through six storage quick wins, in the order we apply them on an audit.

None of them is exotic. All of them are documented by AWS. The difficulty, as always, is not technical. It is that nobody in the organization is explicitly tasked with going to look.

EXECUTIVE SUMMARY

Six data quick wins, in execution order. Migrating gp2 volumes to gp3 (same baseline performance, 20% cheaper, in-place), cleaning up orphaned storage (detached volumes, stale snapshots, unused AMIs), applying S3 lifecycle policies to move cold data to Standard-IA and Glacier, setting CloudWatch Logs retention on log groups that keep data forever, right-sizing RDS storage and backups, and offloading static files from EBS to S3 instead of paying for oversized volumes on EC2.

Typical cumulative savings run 20% to 40% of the storage bill, most of it realizable in the first week. Every lever uses native AWS tooling (Cost Explorer, Cost and Usage Report, CloudWatch metrics, S3 Storage Lens) and none of the six requires downtime on a correctly architected workload.

SOMMAIRE

Why storage leaks so quietly

Compute waste announces itself: an idle instance shows up in monitoring, a flat CPU graph is hard to miss once you look. Storage waste does the opposite. A detached EBS volume keeps the exact same line item on the bill as an attached one. A snapshot from a deleted AMI looks identical to a snapshot you still need. An S3 bucket full of logs from 2022 costs the same per GB whether anyone reads them or not. There is no signal that anything is wrong, which is precisely why it accumulates.

The audit work here is mostly archaeology. You go through the storage layer resource by resource, cross-reference what is actually attached, accessed, or referenced, and separate the live data from the dead weight. None of it is glamorous. All of it pays.

Migrate gp2 volumes to gp3

This is the first thing we look at, because it is the closest thing to free money AWS offers. gp3 volumes deliver the same baseline performance as gp2 (3,000 IOPS and 125 MB/s included) at 20% lower cost per GB ($0.08 vs $0.10 per GB-month), with the added benefit of being able to provision IOPS and throughput independently of size. There is no performance trade-off and, for volumes under 1 TiB, gp3 is actually faster out of the box.

The migration happens online via modify-volume, with no detach and no reboot. The application keeps running throughout. Detection is a one-liner: aws ec2 describe-volumes --filters Name=volume-type,Values=gp2. On a mature account we routinely find that 60% to 90% of general-purpose volumes are still on gp2, simply because they were created before gp3 existed and nobody went back.

The only caveat: gp2 on volumes above 1 TiB gets more than 3,000 baseline IOPS (3 IOPS/GB), so before migrating a large volume, check its actual IOPS usage in CloudWatch and provision matching gp3 IOPS if needed. Even with paid extra IOPS, gp3 almost always comes out cheaper. For the vast majority of volumes, it is a straight 20% cut with zero downside.

Delete orphaned storage

Orphaned storage is the dead weight of past projects. Three targets account for almost all of it. First, detached EBS volumes in available state: a volume that outlived its terminated instance keeps billing at full rate. Second, orphaned snapshots: snapshots whose source AMI has been deregistered, or manual snapshots taken “just in case” years ago. Third, unused AMIs and their backing snapshots, which quietly hold storage long after the image stopped being deployed.

Detection runs through the CLI: describe-volumes filtered on State=available, describe-snapshots --owner-ids self cross-referenced against active AMIs, and describe-images --owners self against running instances. On a mature account, the three combined frequently add up to several hundred euros per month of pure waste.

The action is never blind deletion. Detached volumes get snapshotted before deletion (a cheap insurance against “we actually needed that”). Snapshots get checked against any AMI that still references them. This discipline costs a little time and avoids the one catastrophic mistake that makes everyone afraid of cleanup in the first place.

Apply S3 lifecycle policies

S3 is where the largest storage savings usually hide, and where they are most often left on the table. The reason is structural: applications write to a bucket in S3 Standard and never think about it again. But most data has a clear access lifecycle, hot for the first weeks, then progressively colder. Logs, backups, analytics exports, and archived user content are almost always written once and read rarely after the first month.

A lifecycle policy moves objects automatically across storage classes based on age. The cost difference is dramatic: Standard-IA is roughly 45% cheaper than Standard, Glacier Instant Retrieval around 80% cheaper, and Glacier Deep Archive over 95% cheaper, all while keeping the data immediately or near-immediately retrievable depending on the class. For buckets where the access pattern is genuinely unpredictable, S3 Intelligent-Tiering handles the transitions automatically for a small monitoring fee.

Set retention on CloudWatch Logs

CloudWatch log groups created without an explicit retentionInDays setting keep their logs forever, at $0.03 per GB-month after ingestion. On an account with a few hundred verbose log groups, that accumulation routinely passes the terabyte mark, none of which anyone will ever query past the first month.

Detection is direct: aws logs describe-log-groups --query 'logGroups[?retentionInDays==null]'. The fix is one command per group, setting retention to match the actual business need — 30 days for pre-production, 90 or 365 for production depending on compliance requirements. The saving is modest in absolute terms (a few hundred euros a month on a large account) but the effort is near zero, and it stops the bleed permanently rather than just draining it once.

Right-size RDS storage and backups

RDS storage has two common forms of waste. The first is over-provisioned storage: a database allocated 1 TB of gp2 at creation “to be safe”, now using 200 GB and never growing. Unlike EC2, RDS storage cannot shrink in place, so this one is identified for a planned migration rather than treated as an instant quick win — but flagging it matters. The second, easier form is manual snapshot sprawl: hundreds of manual DB snapshots accumulated over years, plus automated backups with retention windows far longer than the business actually requires.

Detection: describe-db-instances for allocated vs used storage, and describe-db-snapshots --snapshot-type manual for the snapshot count. Deleting redundant manual snapshots and aligning automated backup retention to the real recovery requirement (often 7 days instead of an accidental 35) is a same-week action with no production impact. Migrating RDS storage from gp2 to gp3 applies here too, with the same 20% logic as for EBS.

Offload static files from EBS to S3

This is the one that takes a small amount of architectural thought, but it is so common it earns its place in the list. Plenty of applications serve static assets — images, PDFs, user uploads, exports, build artifacts — straight off the EBS volume attached to an EC2 instance. As that content grows, the volume is resized upward, and you end up paying premium block-storage prices for what is effectively a file archive. gp3 at $0.08/GB-month is roughly 3.5 times the cost of S3 Standard, and an order of magnitude more than colder S3 classes.

The fix is to move static assets to an S3 bucket and serve them from there, optionally fronted by CloudFront for caching and lower egress. The application change is usually small (swap a local filesystem path for an S3 URL or presigned link), and the payoff is double: the EBS volume shrinks back to what the OS and application actually need, and the static content lands on storage that is both cheaper and infinitely scalable. On content-heavy applications, this single move can cut the per-instance storage footprint by more than half.

“Storage never tells you it’s wasted. An idle instance shows up as a flat CPU graph, a forgotten terabyte just sits there looking exactly like a useful one. The whole job is going to look, resource by resource, at what’s actually attached, accessed, or referenced.”

Julien MAUCLAIR

CTO, Co-Foundeur Stralya

What to tackle after these six

The six quick wins above cover the storage waste that comes from neglect rather than design. They are reversible, low-risk, and fast to realize. But they deliberately leave aside three deeper storage topics that deserve a dedicated effort, because they require more time, more coordination, and in some cases an application change.

The first is data transfer optimization. Cross-AZ and cross-region data transfer charges are often a larger line item than the storage itself, and they usually stem from poor data placement, such as a database in one AZ read constantly by services in another, or analytics jobs pulling raw data across regions. Fixing this means rethinking where data lives relative to where it is processed, an architecture conversation rather than a quick win.

The second is backup and disaster recovery strategy. Centralizing backups through AWS Backup, defining consistent retention tiers, and testing actual restore procedures is essential work, but it is a project with a governance dimension, not a one-week cleanup. The quick win here is deleting redundant snapshots. The real work is building a coherent backup policy that prevents the sprawl from coming back.

The third is storage format and engine choices for data-heavy workloads, such as choosing Parquet over CSV for analytics, picking the right RDS engine and instance class, or deciding between DynamoDB on-demand and provisioned capacity. These decisions have large cost implications but belong to the application and data teams, not to a generalist storage cleanup.

These three, we leave in their place, in an optimization roadmap over three to six months, after the quick wins. Trying to redesign data placement on an account where half the volumes are still on gp2 is, once again, starting the marathon at the last kilometer.

Conclusion

Storage optimization is unglamorous work. There is no keynote about deleting orphaned snapshots, no architecture diagram that gets more elegant because you set a log retention policy. But it is among the highest-return, lowest-risk work available on an AWS account, precisely because the waste is invisible and therefore untouched. The savings have been sitting there, accumulating, waiting for someone to go look.

On an account of meaningful size, the cumulative effect of these six actions lands around 20% to 40% of the storage bill, most of it realizable within the first week and almost none of it carrying production risk. It is maintenance, not transformation, and like all maintenance, the only thing standing between the account and the savings is the decision to actually do it.

TAKE IT WITH YOU

Download this use case in PDF

Get this detailed PDF about this articles

E-mail

By submitting your email you agree to receive this case study and occasional updates from Stralya. We don’t share your data — see our privacy policy.

Let's Talk AWS

A project, an infra drifting, a bill spiraling. Tell us what's blocking you in Miami, we'll come back with a plan.