databases
Aurora DSQL, and the clock doing the hard part

Amazon Aurora DSQL was announced in preview at re:Invent on the third of December: a serverless distributed SQL database, PostgreSQL-compatible, with active-active availability across regions and strong consistency.
Every word in that sentence is a claim that has historically had a catch. Two regions both accepting writes usually means eventual consistency and a conflict resolution strategy you have to reason about. So the question worth asking is not what it does but how, and the answer turns out to be about time.
The thing that is normally hard
Two regions, both taking writes, and every reader seeing a consistent story. The obstacle is agreeing on the order of events that happened in different places.
If Frankfurt and Virginia both commit a transaction at what each believes is the same moment, something has to decide which came first. The usual answers are all unpleasant. Send every write through one region, and you have given up on active-active and added a round trip. Let both proceed and reconcile afterwards, and you have given up on strong consistency and handed application developers a conflict problem. Run a consensus protocol across regions for every transaction, and you have bought correctness with latency.
The reason this is hard is that computers do not agree on the time. Clock drift means two timestamps from two machines cannot be compared, so ordering has to be established by communication instead — and communication between regions is expensive.
What DSQL does instead
It makes the clocks trustworthy.
The Amazon Time Sync Service provides a hardware reference clock to EC2 instances, accurate enough that the uncertainty between two machines is bounded and small. Once you can put a number on how wrong a timestamp might be, timestamps become usable for ordering: if two events are further apart than the uncertainty, their order is known without anybody having to ask.
That changes the shape of a transaction. Reads and writes proceed locally against a snapshot, and the cross-region coordination happens only at commit — a check for conflicts against concurrent transactions, rather than a negotiation for every statement. The expensive part is paid once, at the end, and only by transactions that actually need it.
If that sounds familiar it is because it is the same family of idea as Spanner's TrueTime. Bounded clock uncertainty as a primitive is a decade-old idea in the literature; what is new is it arriving as a service you can call from a Lambda.
The consequences worth noticing
The interesting part of any distributed database is what it asks you to give up, and here it is the transaction model rather than the data model.
Optimistic concurrency at commit means a transaction can fail at the end because something else touched the same rows. Application code has to be prepared to retry — which is ordinary discipline for anyone who has used serialisable isolation, and a genuine surprise to anyone who has only used a single Postgres instance where the lock waits and the transaction simply takes longer.
It also means long transactions are expensive in a new way. A transaction holding a snapshot for a long time has a larger window in which to conflict, so the "read-modify-write across ten seconds of application logic" pattern that a single instance tolerates becomes a retry generator.
And PostgreSQL-compatible is doing careful work in that sentence. It means the wire protocol and a large amount of SQL, not that arbitrary Postgres features and extensions are present. For a preview, the gap between "my client connects" and "my schema runs unchanged" is exactly what an evaluation should be measuring.
Where I would and would not put it
The case it is built for is genuine and narrow: an application that needs to serve writes from more than one region with real consistency, and that has so far been solving it by pinning writes to a primary region and accepting the latency, or by sharding by geography and accepting the complexity.
For everything else, a single Aurora or RDS instance with a read replica is a simpler, cheaper, better-understood thing, and the operational knowledge for it already exists in every team. Distributed SQL is not an upgrade to a database that fits on one machine — it is an answer to a constraint, and most applications do not have that constraint.
The reason I find it worth writing about anyway is the mechanism. Precise time as infrastructure is the sort of dependency that is invisible until it unlocks something, and it has now unlocked the same thing twice at two different companies. It is a good reminder that some problems that look like they need a cleverer algorithm actually need a better measurement.
This is a preview, so none of the above is a recommendation. It is a reading of the design, and the parts I would want to test first are the retry behaviour under contention and how far "PostgreSQL-compatible" actually goes.
Written by
Deyan Peev
Founding Engineer · Sofia, Bulgaria


