Why We Decided to Use AWS Aurora

When we first built BoxHero, we chose Amazon RDS for PostgreSQL as our main database.

For the past seven years, we’ve been running on one xlarge Multi-AZ instance and one xlarge read replica. The read replica has been helpful for handling expensive queries and tasks that don’t require strict transaction consistency.

But over time, we started thinking about how we could improve performance and reduce our costs.

This led us to AWS Aurora, Amazon’s database service. Aurora is compatible with PostgreSQL, which meant we didn’t need to change anything in our application code. According to AWS, Aurora can give up to 3 times better throughput than a standard PostgreSQL database. Its biggest feature is that it separates storage and compute, making it more flexible and cost-effective.

In this blog, we share our experience with Aurora, the benefits we've seen, and the cost-saving tips that helped us save $552 per month.

What Is Aurora?

Aurora is a database engine from AWS that’s designed to work with MySQL or PostgreSQL. Unlike traditional RDS databases, Aurora’s storage and compute layers are separate. This allows Aurora to scale better and handle a lot more traffic.

With Aurora, we can add multiple read replicas and only pay for the storage we actually use. This has helped us manage costs and scale our service as our customer base continues to grow.

Benefit 1: Lower Costs

Back when we were using Amazon RDS with gp2 storage, performance depended on disk size. Even though we only needed 100GB, we had to upgrade to 1TB to get better IOPS (Input/Output Operations Per Second).

After a while, AWS introduced gp3 storage, which provided a baseline of 3,000 IOPS regardless of disk size. We switched to gp3 and tried downsizing to 100GB, but the minimum requirements meant we were still stuck paying for around 3TB of storage with Multi-AZ and the read replica.

With Aurora, things work differently. Thanks to its shared storage layer, you only pay once for storage, regardless of how many read replicas you add (up to 15 replicas!).

Availability works differently with Aurora as well. Instead of having a hot standby instance just sitting idle, one of Aurora's read replicas can step in as the primary (writer) if the main instance fails. Instead of paying for an idle instance, you only pay for resources you're actively using.

In our case, we managed to cut our monthly costs from $1,113.96 down to $561.96. Since our CPU usage isn’t very high, we chose the r8g.large instance. If we had gone with r8g.xlarge, our costs would have been similar to the original amount with RDS; however, Aurora gave us an extra 32GB of memory.


RDS Postgres Aurora Postgres
Instance m5.xlarge(4 vCPU, 16GB) $256.32 r8g.large(2 vCPU, 16GB) $258.48
Storage gp3 1TB $115.00 IO optimized 100GB $22.50
Cost for 1 instance $371.32 $280.98
# of instances Multi AZ + Read replica 3 Writer + Reader 2
Total $1,113.96 $561.96

Benefit 2: Read Scalability

Aurora lets you create up to 15 read replicas. They can be added quickly since Aurora doesn’t need to copy the entire database for each replica. Instead, all replicas share the same underlying storage, which helps keep replica lag very low—usually under 100 milliseconds, compared to several seconds on standard RDS PostgreSQL.

This means you can handle a lot more read traffic without slowing down. Adding or removing read replicas becomes much easier, and because the replicas share storage, it’s faster to spin them up.

If you need even more flexibility, you can choose Aurora Serverless, which automatically scales during traffic spikes. However, it’s worth noting that serverless options tend to be more expensive than fixed-size instances.

Benefit 3: Write Scalability

If your write workload grows very large, Aurora offers a "Limitless Database," which automatically distributes data across multiple shards while still appearing as a single database cluster. Aurora Limitless Database can handle massive write volumes at high scale. (Of course, your costs might also become “limitless” if you push it too far.)

How to Upgrade to Aurora

Here’s how we upgraded from RDS PostgreSQL to Aurora in as little as 10 minutes of downtime:

  1. Create an Aurora Replica from your existing RDS PostgreSQL.
  2. Stop all connections and promote the Aurora Replica to a standalone cluster.
  3. Remove the old RDS PostgreSQL instance.

You can find the detailed guide we followed here.

Cost-Saving Tip 1: Reserved Instances

One way we’ve been able to save money on Aurora is by using Reserved Instances. By committing to a 1-year term, we were able to get a significant discount of about 30 to 60% compared to the regular On-Demand pricing.

💡
Newer instance families don’t always offer the same level of discount, and in some cases, they might not even be available for reservation at all.

Another thing we learned is that Reserved Instances only work within the same instance family.

For example, if you have an r5 family Reserved Instance, you can change between sizes in the r5 family (like r5.large and r5.xlarge), but you can’t switch to a completely different family (like r7g).

A 3-year upfront plan offers the lowest price, but it’s also a long commitment. For us, this became an issue when we wanted to upgrade but were locked into a 3-year Reserved Instance, which delayed our switch to Aurora.

Since we wanted to save on costs and have the flexibility to scale over time, we opted for a 1-year All Upfront Reserved Instance instead. It’s been a good option for us so far.

Cost-Saving Tip 2: IO Optimized Instances

With the standard Aurora pricing model, you pay separately for storage and IO, which can make costs harder to predict. But with IO Optimized, you pay a fixed rate.

Based on our experience, we recommend using IO Optimized so that you can do database migrations and upgrades without worrying too much about IO costs.

Cost-Saving Tip 3: Graviton Instances

Graviton instances have a “g” at the end of their instance name, like r8g.large or r7g.large. They run on AWS’s ARM-based CPU called Graviton, which often provides better price-to-performance compared to Intel CPUs. It’s fully compatible with x86 architectures, so our applications run just as well. By choosing Graviton, we’ve been able to cut costs without sacrificing performance.

Our Takeaways from Switching to Aurora

After seven years of using RDS PostgreSQL as our main database, we found that Aurora could offer better performance, storage, and scaling for our read workloads.

At first, the cost of Aurora instances seemed higher, but when we factored in storage and maintenance, the overall costs ended up being lower in the long run. The ability to add up to 15 read replicas and easily scale was also a big plus for our team.

Aurora has been a solid choice for improving database performance while keeping costs manageable for us at BoxHero. If you’re interested in learning more, you can check out the official AWS Aurora documentation.

Start your inventory management with BoxHero All features available in a 30-day free trial!