series · 9 articles · 16k words
Aurora PostgreSQL on AWS
Nine hands-on guides to Amazon Aurora PostgreSQL: cluster setup with the reasoning behind each setting, readers and endpoints, slow queries, caching, clones, global databases and write forwarding.
Aurora is PostgreSQL with the storage layer replaced. That one architectural fact explains most of what makes it behave differently from the RDS PostgreSQL you may have used, and most of the features in this series are consequences of it.
In ordinary PostgreSQL, an instance owns its disk. A read replica is a second machine with a second copy of the data, kept in step by shipping the write-ahead log. In Aurora, the storage is a separate distributed service shared by every instance in the cluster, replicated six ways across three Availability Zones. The instances are compute attached to that shared volume.
Once you know that, the rest stops being a list of features:
- A reader is cheap and fast to add because there is no data to copy. You are attaching another compute node to storage that already exists.
- A clone is nearly free and takes minutes because it is copy-on-write against that same storage. You only pay for pages that diverge afterwards.
- Failover is fast because promoting a reader does not involve moving data.
- Storage cost is separate from instance cost, which is why an idle cluster still bills, and why every article in this series ends with a cleanup step.
The endpoints are the part people get wrong
An Aurora cluster hands you more than one hostname, and using the wrong one is the most common cause of “I added a reader and nothing changed”.
- The writer endpoint always points at the current primary. It follows a failover, which is why your application should use it rather than an instance hostname.
- The reader endpoint load-balances across the read replicas.
- Each instance also has its own endpoint, which you almost never want in an application because it does not move when the cluster does.
Adding a reader does not route anything to it. Your application keeps using the writer endpoint until you change it, which means the work of scaling reads is mostly in your code: identifying which queries are safe to send to a replica and sending them there. The reader article proves the replica really is read-only by trying to write to it, then does the routing.
Replica lag is real, and there is a feature about it
A reader is a few milliseconds behind the writer. Usually that does not matter. It matters enormously in the write-then-immediately-read case — a user saves a profile, the page reloads from a replica, and the old data comes back. That is not a bug, it is the design.
Aurora’s answer is write forwarding: let a reader accept a write and forward it to the writer, so one endpoint serves both. It costs latency, and the cross-Region variant costs considerably more of it. The article measures it rather than describing it, which is the right way to decide whether to use it.
Fix the query before you buy the hardware
The slow query article is the one
to read first if something is already slow in production. It goes in a
deliberate order — Performance Insights and CloudWatch before psql, because the
console tells you which query without you having to guess, then
pg_stat_statements to rank precisely, then EXPLAIN ANALYZE to see why. The
fix in that article is a single correct index, and it is 155 times faster.
That ordering is the theme of this whole group. A reader, and then a Valkey cache in front, will both make a slow application faster — the cache-aside article measures a 67× improvement on cached reads. But an index that turns a sequential scan into a lookup is cheaper than either, and it is the only one of the three that does not add a component you now have to operate and invalidate.
What this costs, and the bill you did not mean to run up
Every article ends with a cleanup step, and that is not boilerplate. Aurora bills for storage whether or not anything is querying it, an idle Global Database carries instances in two Regions, and a clone that was meant to last an afternoon is a full-price cluster the next morning. The setup guide picks Dev/Test, provisioned instances and Aurora Standard storage rather than the production defaults specifically so the series can be followed without an unpleasant surprise.
The Region article also documents a trap worth knowing before you meet it: some AWS Regions are opt-in, and adding one to a Global Database from a Region that is not enabled fails in a way the console does not explain.
What you need
An AWS account, the CLI configured, and psql. A couple of the articles use
Python — the cache-aside one, and the Valkey guide. None of them assume prior
Aurora experience, and the setup guide starts from an empty account.
Read them in the order above and you end up with a working cluster, a reader, a cache, a measured slow-query fix, and a clear picture of what Global Database does and does not buy you.
All 9 articles
Get a cluster running
Start here. Every other article assumes a cluster exists, and this one explains why each setting on the creation screen is set the way it is.
Make reads faster
The usual order of operations: find out which query is slow and fix it, then add a reader, then put a cache in front. Doing it in the other order buys hardware to run a bad query faster.
- Finding and Fixing Slow Queries in Aurora PostgreSQL Find slow queries in Aurora PostgreSQL starting from the AWS console: Performance Insights and CloudWatch, then pg_stat_statements and EXPLAIN, for a 155x fix.
- Adding a Read Replica (Reader) to Aurora PostgreSQL Add a reader to Aurora PostgreSQL to scale reads: create the replica, learn the writer vs reader endpoints, prove it is read-only, and route reads to it.
- Valkey on AWS ElastiCache: A Hands-On Guide Set up Valkey on AWS ElastiCache step by step: security groups, an EC2 client, TLS, valkey-cli testing and a Python health check, with the real errors I hit.
- Valkey as a Cache in Front of Aurora PostgreSQL (Cache-Aside) Put Valkey in front of Aurora PostgreSQL with the cache-aside pattern in Python, and measure a real 67x speedup on cached reads, with every gotcha I hit.
More than one Region
Global Database, what it actually replicates, and the feature that exists because cross-Region replicas are read-only and your application does not always know that in advance.
- Adding an AWS Region to Aurora PostgreSQL (Global Database) Turn an Aurora PostgreSQL cluster into a global database: the r-class upgrade, the one reboot, the opt-in Region trap, and how far the thing actually scales.
- Aurora Write Forwarding: Writing Through a Read Replica Let an Aurora read replica accept writes. Hands-on local write forwarding in PostgreSQL, the global cross-Region variant, plus latency, versions and limits.
Other ways to reach the data
Two features that only make sense once you know how Aurora stores things: a full copy of production that costs almost nothing, and SQL over HTTPS with no connection at all.
- Cloning an Aurora PostgreSQL Cluster (Copy-on-Write) Create a copy-on-write Aurora clone in minutes, prove it is isolated from the source, and learn when to use one, when to delete it, and where the limits are.
- Running SQL Over HTTPS with the RDS Data API (Aurora PostgreSQL) Run SQL over HTTPS on Aurora PostgreSQL with the RDS Data API: no persistent connection, no VPC, IAM auth, from the browser Query Editor and the CLI.