10 min read

The Log is the Database: Formally Verifying Consensus at Scale in Amazon Aurora

Formally Verifying Consensus at Scale in Amazon Aurora

The Log is the Database: Formally Verifying Consensus at Scale in Amazon Aurora

Imagine you are managing a database that handles millions of transactions per second. Your users expect 99.999999999% durability. Now, imagine a back-end storage node fails. Then, a network partition hits, slicing your cluster in half. Simultaneously, a storage garbage collection routine kicks in. In the middle of this chaos, a write operation arrives.

Does that write survive? Is it replicated correctly? If the primary compute node crashes, can the new primary reconstruct the exact state of the world without losing a single byte?

In the world of distributed systems, “probably correct” is synonymous with “eventually broken.” At the scale of Amazon Aurora—a service supporting hundreds of thousands of active databases—the “one-in-a-billion” edge case happens every Tuesday. To sleep at night, AWS engineers don’t just rely on testing; they rely on Formal Verification.

In this deep dive, we’re going under the hood of Amazon Aurora’s log-structured storage engine. We’ll explore how AWS uses TLA+ to formally verify the distributed consensus protocols that keep your data safe, why traditional Paxos wasn’t enough, and how they proved the correctness of a system that treats the log as the database.


The Architectural Paradigm Shift: The Log is the Database

To understand why verification is so hard for Aurora, we first have to understand why Aurora is weird. In a traditional relational database (like standard MySQL or PostgreSQL), the storage layer is essentially a “black box” of block storage. When you change a row, the engine writes to a Write-Ahead Log (WAL) and eventually flushes the modified data pages to disk.

Aurora flipped the script. It decoupled compute from storage.

In Aurora, the compute nodes do not write data pages. They only send log records to a purpose-built, highly distributed storage layer. The storage nodes are “smart”—they receive these log records, organize them, and materialize data pages on demand.

The 4-out-of-6 Quorum

Aurora replicates data across three Availability Zones (AZs), with two copies in each AZ, totaling six replicas.

  • Write Quorum: 4 out of 6.
  • Read Quorum: 3 out of 6.

This configuration is designed to survive the “AZ+1” failure scenario: you can lose an entire data center plus one additional storage node without losing data availability or durability.

But here is the engineering curiosity: Aurora does not use standard Paxos or Raft for this.

Why? Because standard consensus protocols are often “chunky.” They require sequential log replication and can stall if a single node is slow (the “straggler” problem). Aurora’s storage engine is designed for asynchronous, out-of-order log processing to maximize throughput. This introduces a terrifying amount of non-determinism.

How do you prove that out-of-order logs, handled by six different nodes with varying latencies, will always result in a consistent state? Enter Formal Verification.


The Complexity Trap: Why Unit Testing Fails Distributed Systems

If you’re writing a sorting algorithm, unit tests are great. You provide an input, you check the output.

In a distributed storage engine, the “input” isn’t just data; it’s the interleaving of events.

  1. Node A receives Log #101.
  2. Node B receives Log #101.
  3. Node C crashes.
  4. Node A’s disk reports a transient error.
  5. A network partition hides Node D.
  6. The Primary Compute node crashes and reboots.

The number of possible states in this scenario is larger than the number of atoms in the universe. You cannot “test” your way out of this. Even “Chaos Engineering” (like Netflix’s Chaos Monkey) only samples a tiny fraction of the state space.

Formal verification, specifically using TLA+ (Temporal Logic of Actions), allows engineers to write a mathematical specification of the system and use a Model Checker to exhaustively search every possible state the system can ever enter. If there is a sequence of events—no matter how obscure—that leads to data loss, the model checker will find it.


Deep Dive: The Consensus Protocol and TLA+

AWS engineers used TLA+ to model the core of Aurora’s consistency: the Log Management and Recovery Protocol.

The Key Observables

To verify the system, they had to model several critical concepts:

  • LSN (Log Sequence Number): A unique identifier for every log record.
  • VCL (Volume Complete LSN): The highest LSN for which all prior log records are known to be durable.
  • VDL (Volume Durable LSN): The highest LSN that is part of a “quorum” and can be safely acknowledged to the user.

The gap between VCL and VDL is where the magic (and the danger) happens. Because logs arrive out of order, a storage node might have LSN 101, 102, and 104, but be missing 103. In this state, the “Complete” LSN is only 102.

The TLA+ Specification

A TLA+ spec looks less like C++ and more like set theory. You define:

  1. Variables: (e.g., storage_nodes, pending_writes, confirmed_lsns).
  2. Init: The starting state of the system.
  3. Next: A set of “actions” (transitions) that can happen (e.g., WriteLog, CrashNode, AcknowledgeQuorum).
  4. Invariants: The “Rules of the Universe” that must never be broken (e.g., Consistency == TRUE).
---- MODULE AuroraConsensus ----
EXTENDS Naturals, FiniteSets

VARIABLES
    storage_state,  \* What each node has stored
    network_msgs,   \* Messages in flight
    vdl_marker      \* The current Durable LSN

\* The Invariant: We must never lose a committed write
NoDataLoss == \A lsn \in CommittedLSNs :
    CountReplicas(lsn) >= WriteQuorum

Next ==
    \/ \E n \in Nodes : ReceiveLog(n)
    \/ \E n \in Nodes : NodeCrash(n)
    \/ AdvanceVDL
    \/ RecoveryProcess
====

Proving Recovery

The most complex part of Aurora isn’t writing data—it’s Recovery. When a compute node fails, the new node must talk to the storage fleet and determine the “cut-off point.”

Using TLA+, AWS engineers modeled the recovery transition. They discovered that the interaction between “Runtime Quorum” (writes happening now) and “Recovery Quorum” (determining what was written before the crash) was incredibly subtle.

Specifically, they had to prove that if the storage engine acknowledged a write to a client (meaning it reached 4/6 nodes), any subsequent recovery attempt must find that write. TLA+ helped them refine the “Gossip Protocol” used by storage nodes to fill holes in their logs, ensuring that the VDL could always be reconstructed even if the original primary node vanished forever.


The “Hype” vs. The Reality of Formal Methods

In recent years, “Formal Methods” has become a buzzword in high-performance engineering. Some claim it replaces testing. The reality at AWS is more nuanced.

The Substance: TLA+ doesn’t check your C++ code for null pointer exceptions. It checks your logic. It’s a blueprint checker. If your blueprint allows for a bridge to collapse in a high wind, the most expensive steel in the world won’t save it.

The Aurora team didn’t model the entire database—that would be impossible. They focused on the distributed state machine. By isolating the consensus logic from the “boring” parts (like SQL parsing), they were able to find bugs that had existed for months but had never been triggered in the wild.

The “Heisenbug” Discovery

During the formal verification process, the team actually found a potential “deadlock” in the storage node’s cleaning cycle. In a specific scenario involving a full disk and a stalled recovery quorum, a node could stop responding to heartbeats, leading the cluster to believe it was dead when it was actually just “thinking” too hard. This was a bug that would likely never show up in a staging environment but would have caused a massive outage under peak load in production.


Infrastructure at Scale: The Compute Behind the Proof

You might think that checking a model of a few storage nodes is easy. It’s not. As you add more variables (more nodes, more log records), the state space grows exponentially—this is the State Space Explosion.

To verify Aurora, AWS engineers don’t just run the model checker on a laptop. They use:

  1. Model Slicing: Breaking the protocol into smaller sub-properties (e.g., verifying “Election” separately from “Replication”).
  2. Distributed Model Checking: Running TLC (the TLA+ Checker) across a cluster of high-memory EC2 instances.
  3. Constraint Refinement: Limiting the number of “crashes” or “messages” in a single run to keep the state space searchable while still covering all “interesting” interleavings.

This scale of verification is what differentiates “Premium Engineering.” It’s the difference between a startup that hopes its database works and an infrastructure provider that knows it works because the math says so.


How Aurora Handles “The Edge of the Quorum”

One of the most fascinating technical details revealed by formal verification is how Aurora handles reconfiguration.

What happens when a storage node is permanently replaced? In a 4-out-of-6 system, you can’t just swap a node out instantly. You have to transition from one “Membership Set” to another.

Aurora uses a concept called Epochs. Each time the storage membership changes, the Epoch increments. The TLA+ models proved that as long as the VDL is tracked across Epoch transitions using a “Joint Consensus” style approach, the system remains linearizable.

The Storage Node Gossip

Because Aurora is log-structured, storage nodes are constantly “talking” to each other behind the scenes. This is the Gossip Protocol.

  • Node 1: “I have LSNs 1-5 and 7-10.”
  • Node 2: “I have 6! Here, take it.”

This background reconciliation is what allows Aurora to have such high write availability. The compute node doesn’t have to wait for every node to be perfect; it just needs to hit the quorum. The formal proof ensures that the gossip protocol is “stable”—that it eventually converges on the correct log sequence without creating infinite loops or consuming all available IOPS.


Engineering Curiosities: Lessons from the TLA+ Trenches

For those looking to implement formal methods in their own stacks, the Aurora journey offers some profound insights:

  1. Write the Spec Before the Code: Many of the most robust parts of Aurora’s storage engine were designed “on paper” in TLA+ before a single line of C++ was written. It’s much cheaper to fix a logic error in a 500-line TLA+ spec than in a 500,000-line codebase.
  2. Focus on the Transitions: The bugs aren’t in the “states” (e.g., “the node is up”); they are in the “transitions” (e.g., “the node is coming up while another is going down”).
  3. The “Safety vs. Liveness” Balance: TLA+ forces you to define not just that “bad things don’t happen” (Safety), but also that “good things eventually happen” (Liveness). In Aurora, proving that the system won’t deadlock during a storage node failure was just as important as proving it won’t lose data.

The High Bar of Distributed Correctness

Amazon Aurora’s success isn’t just due to its performance or its AWS integration; it’s due to the uncompromising rigor applied to its core storage engine. By treating distributed consensus as a mathematical problem to be solved rather than a software problem to be tested, the Aurora team redefined what we should expect from a cloud-native database.

The move toward formally verified systems is the next frontier of software engineering. As our systems become more distributed and our data volumes explode, we can no longer afford to “hope” for correctness.

Aurora proves that with the right tools (like TLA+), a radical architecture (the log is the database), and a commitment to formal rigor, you can build a system that is both incredibly fast and mathematically certain.

So, the next time you spin up an Aurora cluster and see those sub-millisecond latencies, remember: beneath the surface, there is a set of formal proofs working tirelessly to ensure that no matter what chaos the network throws at it, your data remains an immutable truth.

Technical Takeaways:

  • Decoupled Storage: Moving log processing to the storage layer reduces network overhead but increases consensus complexity.
  • Quorum Systems: A 4/6 quorum provides high durability but requires complex recovery logic.
  • TLA+: A vital tool for exhaustive state-space analysis in distributed systems.
  • VDL vs. VCL: The distinction between “complete” logs and “durable” logs is the heartbeat of Aurora’s consistency model.

More to explore

Keep diving in