Converting Aurora Serverless to provisioned for cost and performance
Serverless is a scaling tool, not a default
Aurora Serverless scales capacity up and down automatically, which is genuinely useful when your load is bursty or unpredictable. The trouble is that it gets adopted as a default for databases whose load is nothing like that, and at scale the per-capacity-unit price makes it an expensive way to run a steady workload.
I think of Aurora Serverless less as a permanent home for a steady database and more as a temporary configuration that helps you discover the capacity a database actually needs, so you can then move it to a right-sized provisioned instance. If a database has been running at a roughly constant capacity for a year, it is not a Serverless workload.
Reading the capacity pattern before touching anything
On a recent engagement I converted a couple of a client’s Aurora Serverless databases to provisioned instances. Before proposing the change, I did the usual deep-dive on the capacity data.
It showed their Aurora capacity had been pretty much constant over the previous 15 months, with only minor fluctuations within a day. That is nowhere near the burstable pattern where Serverless earns its premium. With that established, I determined the appropriate provisioned instance type for each database from its actual CPU and memory profile, and helped roll the change out to production through the client’s normal deployment process.
The cost for those databases went from about $450 a day to about $100 a day, before any rate optimization. That is roughly $125,000 annualized, and it brought the total savings for that client to over $680,000 across a few months of work.
The change made them faster, too
The interesting part was not just the cost. Query latency and jitter both improved noticeably after the conversion.
The reason is the hardware underneath. On provisioned Aurora you choose the instance type, so we put these databases on R7g instances using Graviton 3, which is a newer generation than what Aurora Serverless runs on under the hood. Newer silicon, better latency. It would have been better still on R8g with Graviton 4, but those instance types were not yet available in the London region where this workload runs, so that is an update for later.
This is the part people miss: moving off Serverless for a steady workload is not a cost-versus-performance tradeoff. For a constant-capacity database you often get both, because you get to pick a modern instance type instead of taking whatever the managed layer gives you.
While you are in there: I/O Optimized versus Standard
Right-configuring Aurora is not only about Serverless versus provisioned. The other lever that moves real money is the storage configuration: Aurora I/O Optimized versus Aurora Standard.
I/O Optimized is effectively insurance against unpredictable I/O charges. You pay more for storage and compute but you stop paying per-request I/O costs, which for a busy cluster can otherwise spike to tens of thousands of dollars a month on their own. The mistake I see is applying it everywhere, including to clusters whose Standard I/O costs would be small.
On one client with 179 Aurora clusters, 124 were configured as I/O Optimized. When we actually costed each one out, only 9 of them were genuinely better off as I/O Optimized, but those 9 would have cost about $30,000 a month more under Standard, almost as much as all the others combined. The other 115 would save roughly $7,400 a month if moved back to Standard. The answer is not “always” or “never”; it is per-cluster, based on each cluster’s real I/O profile.
The pattern
Both of these come down to the same discipline: look at the workload’s actual behavior over a long enough window, then match the configuration to it, rather than accepting whichever default it was created with.
If you run Aurora at scale and are not sure your Serverless and I/O configurations still match your workloads, book a discovery call or reach out on LinkedIn.
-Cristian