DEV Community

Cover image for Aurora Serverless v2: When "I/O Optimized" Actually Costs You More

Aurora Serverless v2: When "I/O Optimized" Actually Costs You More

The Request

It started with a simple Slack message from my manager:

"We've been running on **Aurora I/O Optimized* for a few months. Can we save money by converting back to Standard?"*

We had enabled I/O Optimized previously because the promise of "Free IOPS" sounded perfect for our high-traffic workloads. But without recent validation, we were flying blind.

This is the story of how I validated the costs, the "CloudWatch Trap" I fell into, and why we ultimately decided to revert to Standard—saving the company up to 26% on our database bill.

The Difference: It’s a Billing Flag, Not Hardware

My first step was checking if reverting would hurt performance. I dug into the AWS Documentation and confirmed that switching between Standard and I/O Optimized does not change the underlying hardware. It is purely a billing configuration.

Here is the trade-off (based on eu-west-1 pricing):

Component Standard Model I/O Optimized Model (Our State)
Compute (ACUs) ~$0.14 / hr ~$0.19 / hr
Storage ~$0.11 / GB ~$0.25 / GB
I/O Requests ~$0.22 / Million $0.00

The math seems simple: Were we actually consuming enough IOPS to justify the massive premium we were paying for Compute and Storage?

The "CloudWatch Trap"

To answer that question, I tried to write a Python script to pull metrics from CloudWatch. I calculated the ServerlessDatabaseCapacity (ACUs) using the "Average" statistic over 30 days.

  • The Result: The calculations was not accurate

Why? Granularity.

Aurora Serverless scales second-by-second. If your database spikes to 60 ACUs for 30 seconds and then drops, the AWS billing engine captures that cost perfectly. CloudWatch, however, averages that spike into the surrounding timeframe (often 1-5 minutes), smoothing out the data.

This makes the usage look much lower (and cheaper) than it actually is.

Lesson Learned: Never use CloudWatch averages to calculate your total monthly bill. It is a monitoring tool, not an accounting tool.

The Solution: The "10-Day Snapshot" Method

Since I couldn't trust CloudWatch for the total ACU cost, and AWS Cost Explorer is limited to 14 days of granular resource data, I developed a hybrid approach: The 10-Day Snapshot.

The logic is simple: If we are losing money over a representative 10-day period, we are losing money over the month.

Step 1: The Source of Truth (Cost Explorer)

I used Cost Explorer to get the exact billed amount for Compute (ACUs) for a specific window (e.g., Dec 11 - Dec 20).

  • Dimension: Resource
  • Filter:
  • Usage Type: EU-Aurora:ServerlessV2IOOptimizedUsage (ACU-Hr) (Since we were currently Optimized)
  • Resource: Select the relational databse then selct the DB instances
  • Result: Get the exact amount of the used I/O.

Cost Explorer

Cost Explorer

Step 2: The Variable Costs (CloudWatch)

Since Cost Explorer doesn't easily split out "Storage" vs. "I/O" quantity for a specific custom window, I used the CloudWatch Console to get the raw usage data for the exact same 10-day period.

Here is exactly how I got the numbers:

  1. Navigate to Metrics:

    • Go to CloudWatch > All metrics.
    • Select AWS/RDS > DBClusterIdentifier.
    • Search for your cluster ID (e.g., client-db-01).
  2. Select the Metrics:

    • Check VolumeBytesUsed (for Storage).
    • Check VolumeReadIOPS (for I/O).
    • Check VolumeWriteIOPS (for I/O).
  3. Set the Timeframe:

    • Click the date picker in the top-right.
    • Select Custom > Absolute.
    • Choose the exact same 10-day window you used in Cost Explorer.
  4. Configure the Calculations (Graphed Metrics Tab):

    • For Storage: Set the Statistic to Average.
      • Math: Add the expression m1/1024/1024/1024 to convert raw bytes into GB.
    • For I/O: Set the Statistic to Sum.
      • Math: Add the expression m2+m3 to add Read and Write IOPS together for the Total IOPS.
    • Important: Ensure the "Period" is set to 30 Days (or a custom value like 864000 seconds) so that CloudWatch gives you one single number for the entire duration, rather than a line graph.

The Variable Costs (CloudWatch)

Step 3: The Comparison

Now we have the exact numbers for Total I/O, the Storage, and consumed ACUs.
I put the numbers into a spreadsheet to compare our current costs vs. what we would pay if we switched to Standard.

Scenario A: I/O Optimized (Actual Cost)

  • ACU Cost: (Amount of used ACUs Cost Explorer) * 0.19
  • Storage Cost: Avg GB * $0.248 * (10/30)
  • IOPS Cost: $0

Scenario B: Standard (Projected Cost)

  • ACU Cost: (Amount of used ACUs Cost Explorer) * 0.14
  • Storage Cost: Avg GB * $0.11 * (10/30) (The cheaper storage rate)
  • IOPS Cost: (Total IOPS) / 1,000,000 * $0.22

The Verdict

The results were eye-opening. We were overpaying on every single cluster.

Conclusion

We immediately scheduled maintenance windows and converted all clusters back to Aurora Standard.

The validation proved that while "Optimized" sounds better, sometimes the "Standard" option is the true hero for your budget. If you are currently running on I/O Optimized, take a 10-day snapshot and check your storage costs—you might be surprised by what you find.

Top comments (0)