The problem: agree on one value, even when things break#
TL;DRthe 30-second version
- Consensus is getting a set of machines to agree on one value even though machines crash and messages get lost — and the hard part is never deciding two different values.
- Paxos splits the work across three roles: proposers suggest a value, acceptors vote on it, and learners find out what was chosen. A value is chosen once a majority of acceptors accept it.
- It runs in two phases. Phase 1 (prepare/promise) claims the right to propose using a proposal number; Phase 2 (accept/accepted) tries to get a value accepted by a majority.
- One rule carries all the safety: before proposing its own value, a proposer must adopt the highest-numbered value that any acceptor has already accepted. That is what stops two different values from ever both being chosen.
- Single-value (single-decree) Paxos decides one thing. Multi-Paxos runs it for a whole stream of decisions with a stable leader that skips Phase 1 — which is exactly a replicated log.
- Paxos is proven correct but notoriously hard to understand and implement. Raft repackages the same guarantees in a form people can actually build — that is why Raft exists.
Picture three servers that together store one small piece of shared truth — say, the value in the first slot of a replicated log. Google's Chubby lock service works exactly like this: a small group of replicas has to agree on each entry in a tiny database, and every other Google system leans on that agreement. Two clients show up at the same moment. One wants the slot to hold the command set x = 5. The other wants set x = 8. The servers must agree on exactly one of these, and once they agree, that answer can never change.
This would be easy if machines never failed and messages always arrived. They don't. A server can crash at any instant — mid-decision, before replying, right after replying. A message can be dropped, delayed for a minute, or arrive out of order. There is no shared clock and no way to tell a crashed server apart from a slow one. The one thing we assume is that machines are honest: a server can go silent, but it never lies about what it accepted. (Tolerating liars is a harder problem called Byzantine consensus, and Paxos does not attempt it.)
The naive fix is to pick one server as the boss and let it decide. That works until the boss crashes — now nobody can decide, and the whole system is stuck. So we can't lean on any single machine. We need the group to agree even while some members are down or unreachable.
The trick is to require a majority — more than half the servers. This is the same quorum idea from /quorum: with three servers, any two form a majority, and here is why that number is magic. Any two majorities of the same group must share at least one server, because two groups of two, drawn from three, always overlap. So if one value is accepted by a majority, and later some other value tries to get accepted by a majority, at least one server is in both majorities — and that server remembers the first value. Overlap is the seed of the whole safety argument. Everything below is machinery to make sure that shared server actually forces the two majorities to agree.
The three roles#
Paxos describes the protocol in terms of three roles, not three machines. In a real system one server usually plays all three at once, but keeping them separate makes the logic clear.
- Proposer — puts a value forward and tries to get it chosen. In our example, the client wanting set x = 5 is behind a proposer. Several proposers can be active at the same time, each pushing its own value.
- Acceptor — votes. Acceptors are the memory of the system: a value is chosen only when a majority of acceptors have accepted it, and acceptors remember what they've promised and accepted. The three servers are the acceptors.
- Learner — finds out which value won, so it can act on it (apply the command, answer a client). A learner does no voting; it just needs to be told the outcome once a majority has accepted.
Phase 1: prepare and promise#
A proposer can't just tell the acceptors set x = 5 and count votes. If two proposers did that at once, some acceptors might accept one value and some the other, with no majority for either — deadlock. So before proposing any value, a proposer first earns the right to propose. That's Phase 1.
Every attempt to propose carries a proposal number: a number that is unique to that proposer and only ever goes up. Think of it as a priority tag — a higher number outranks a lower one. (Making them unique is simple in practice: each proposer draws from a separate set, like proposer P using 1, 4, 7 and proposer Q using 2, 5, 8, so two proposers can never pick the same number.)
- The proposer picks a proposal number higher than any it has used, and sends a prepare(n) message with that number to the acceptors. It says nothing about the value yet — this is just a request to reserve the right to propose.
- An acceptor that receives prepare(n) compares n to the highest prepare it has already answered. If n is not higher, it ignores the message. If n is higher, it makes a promise: it will refuse any future proposal numbered below n.
- Along with that promise, the acceptor reports back the value it has already accepted, if any — and the number that value came in under. If it has accepted nothing, it says so.
- If a majority of acceptors promise, the proposer has won the right to move to Phase 2. If it doesn't hear back from a majority, it gives up, picks an even higher number, and tries again.
Two things just happened, and both matter. The promise is a commitment to the future: an acceptor that promised for number n has slammed the door on every proposal numbered below n. The report is a window into the past: the proposer now knows what values, if any, are already floating around in the system. Phase 2 uses both.
Phase 2: accept and accepted#
Now the proposer names a value. But here is the rule that everything hinges on — it does not always get to name its own value.
- The proposer looks at the reports it collected in Phase 1. If any acceptor reported an already-accepted value, the proposer must take the value that came with the highest proposal number and propose that — dropping its own value. Only if every acceptor reported 'accepted nothing' is the proposer free to propose the value it actually wanted.
- It sends an accept(n, value) message to the acceptors, carrying the same number n from Phase 1 and the value it just settled on.
- An acceptor that receives accept(n, value) accepts it — unless, in the meantime, it has promised for a number higher than n. If it has, it ignores the message; its newer promise wins. Otherwise it records the value and reports 'accepted'.
- Once a majority of acceptors have accepted the same (n, value), that value is chosen. It is now the decision, forever. Learners are told, and the system moves on.
Walk our example through it, because the payoff is in the details. Proposer P (for set x = 5) runs Phase 1 with number 1, gets promises from all three acceptors, and sends accept(1, x = 5). But only acceptor A1 receives it before the network hiccups — one acceptor, not a majority. So x = 5 is accepted by A1 but not yet chosen.
Now proposer Q (for set x = 8) runs Phase 1 with number 2. A1 promises and reports 'I already accepted x = 5 under number 1'; A2 and A3 promise and report nothing. Q has a majority of promises, so it may proceed — but the rule bites. One acceptor reported an accepted value, so Q must propose that value, not its own. Q sends accept(2, x = 5), abandoning x = 8. All three accept, and x = 5 is chosen. Q wanted x = 8 and was forced to help x = 5 win instead.
The one rule that keeps a decision safe#
Why must a proposer adopt an already-accepted value instead of pushing its own? Because it cannot tell whether that value has already been chosen. In the example, when Q saw that A1 had accepted x = 5, Q had no way to know if x = 5 had quietly reached a majority somewhere and become the final decision. If it had, and Q proposed x = 8 anyway and got it accepted by a majority, the system would now hold two different chosen values — the exact disaster consensus must prevent.
The adopt-the-highest rule closes that gap. Any proposal that comes after a value could have been chosen is forced to carry that same value forward. So once a value reaches a majority, every later proposal proposes it too, and no competing value can ever slip through. This is the heart of Paxos. The prepare/promise dance and the proposal numbers exist for one purpose: to make sure a new proposer always sees any value that might already have won, and is compelled to keep it alive.
PredictFive acceptors. Some value v has been accepted by three of them — a majority — so v is chosen. A new proposer now runs Phase 1 with a fresh, higher number. Can it ever get a different value chosen?
Hint: How many acceptors must reply to its prepare, and how many of those must have seen v?
No. Its prepare needs promises from a majority — 3 of 5. Any group of 3 acceptors overlaps the 3 that accepted v in at least one server (3 + 3 = 6 > 5, so they must share one). That shared acceptor reports v as an accepted value. By the adopt-the-highest rule, the new proposer is forced to propose v, not its own value. This is exactly why a chosen value is permanent: majority overlap guarantees the next proposer sees it, and the rule guarantees it keeps it. The magic number is the overlap, computed: any two majorities of the same set must share a member.
Go deeperUnder the hood: the invariant that makes the proof work
Lamport states the safety guarantee as a single invariant, usually called P2c: if a proposal with number n and value v is issued, then there is a majority of acceptors such that either none of them has accepted any proposal numbered less than n, or v is the value of the highest-numbered proposal less than n that any of them has accepted.
Phase 1 is precisely how a proposer establishes that invariant before issuing a proposal. By collecting promises from a majority, it learns the highest-numbered value any of them has accepted, and Phase 2 forces it to use that value. Induction on the proposal number then shows that once a value is chosen, every higher-numbered proposal carries the same value — so no two different values can ever both be chosen. The two phases and the proposal numbers are not arbitrary; they are the minimum needed to keep P2c true through crashes and lost messages.
From one value to a log: Multi-Paxos#
Everything so far decides one value — a single slot. This is called single-decree Paxos, one decree, one decision. But a real system doesn't want to agree on one value; it wants to agree on an ordered stream of them: command 1, then command 2, then command 3 — a replicated log, the same thing /raft builds. Replay that agreed log on every server and they all end up identical.
The obvious approach is to run a separate instance of single-decree Paxos for each slot in the log. That works and it's correct, but it's wasteful: every slot pays for its own Phase 1, a full round-trip just to claim the right to propose, before it can even name a value.
Multi-Paxos removes that waste. The insight is that Phase 1 doesn't mention any particular value — it just claims proposing rights using a number. So one proposer runs Phase 1 once, for all future slots at the same time, and becomes the stable leader. After that, for each new command it only runs Phase 2: send accept, wait for a majority, done. One round-trip per command instead of two. The expensive prepare phase happens only when leadership changes.
Go deeperUnder the hood: what keeps two leaders from both running Phase 2
Nothing in Paxos forbids two proposers from both believing they are the leader — a network split can leave an old leader still trying to drive commands while a new one takes over. Safety survives this anyway: the loser's accept messages carry a lower proposal number, so acceptors that have since promised to the higher-numbered leader simply ignore them. No wrong value can be chosen; the stale leader just fails to make progress.
For efficiency, though, you want to avoid two leaders fighting at all. Real systems grant the leader a lease — a time-bounded permission to be the sole leader, renewed by heartbeats — so that during the lease no other node tries to take over. This is a performance and liveness optimization layered on top of the safety Paxos already gives you for free; it trades a small assumption about clocks for far fewer wasted rounds. The same lease idea powers fast leader reads (see /raft's read path) and distributed locks (/distributed-locks).
What it costs#
Paxos buys safety with round-trips and messages, and the bill is easy to read once you know the two phases.
- Latency, single-decree: two round-trips to a majority — one for prepare/promise, one for accept/accepted. Each round-trip finishes as soon as the fastest majority of acceptors reply, so the slowest acceptor never gates you — only the ones you needed to form a majority.
- Latency, Multi-Paxos steady state: one round-trip per command. The leader already holds proposing rights, so each command needs only Phase 2. This is the number that matters in practice — the two-round cost is paid once per leadership, not per command.
- Fault tolerance: a group of 2f+1 acceptors tolerates f failures and still has a majority of f+1 alive. Three acceptors survive one failure; five survive two. Even sizes buy nothing — four acceptors still need a majority of three and tolerate only one failure — so groups are almost always 3 or 5.
- Messages: each phase is on the order of N messages out and N back, linear in the group size. Consensus groups stay small (3 or 5) for exactly this reason; you scale data by running many independent groups, not one huge group.
Under the hood: why it can't promise to always finish
Paxos guarantees it will never choose two different values — that safety holds no matter what the network does. It does not guarantee it will always choose a value promptly. Those are different promises, and Paxos deliberately keeps only the first.
The reason is a famous result. In 1985, Fischer, Lynch, and Paterson proved that in a fully asynchronous system — one with no bound on how long messages can take — no algorithm can guarantee that a group of processes reaches consensus if even a single process might crash. This is the FLP impossibility result. You cannot have both guaranteed safety and guaranteed termination when the network can delay messages arbitrarily. Something has to give, and every real consensus algorithm gives up guaranteed termination, keeping safety.
You can even see the failure to terminate directly in Paxos. Suppose two proposers keep leapfrogging each other. Proposer P runs prepare(1); before P can finish Phase 2, proposer Q runs prepare(2), which makes the acceptors refuse P's accept. P retries with prepare(3), which makes them refuse Q's accept. Q retries with prepare(4), and so on forever. Each proposer keeps invalidating the other's proposal, and no value is ever chosen. This is called dueling proposers, or livelock — the system is busy but stuck.
Paxos vs Raft: why Raft exists
Paxos is correct. Its safety is proven, it's been battle-tested at Google for two decades, and Multi-Paxos is as powerful and efficient as any consensus protocol. So why did the field invent Raft in 2014, and why do most new systems reach for Raft instead?
The honest answer is understandability. Lamport's papers describe single-decree Paxos — how to agree on one value — beautifully. But turning that into a working replicated log means filling in a lot the papers leave open: how leaders are elected, how the log is kept gap-free, how membership changes, how it all fits together. The Google engineers who built Paxos into Chubby wrote a whole paper (Paxos Made Live) about the gap between the algorithm and a real system, and it is full of problems the theory never mentions. Raft's authors put it bluntly: Paxos is exceptionally difficult to understand, and its architecture is a poor foundation for building practical systems.
Raft delivers the same guarantee — a replicated log agreed by a majority, surviving f failures out of 2f+1 nodes — but it is designed from the start around understandability. It makes the leader mandatory and central, keeps the log free of gaps, and specifies leader election and membership change as core parts of the protocol rather than exercises for the reader. It is, in a real sense, Multi-Paxos with the practical pieces built in and the presentation reworked so a normal engineer can implement it correctly from the paper. Watch it run in /raft/sim — that is the consensus you'll actually build.
| Paxos | Raft | |
|---|---|---|
| Core question answered | Agree on one value (single-decree) | Agree on an ordered log (built in) |
| Leader | Optional; leadership is an add-on (Multi-Paxos) | Mandatory and central; election is part of the protocol |
| Log | Slots can be decided out of order, leaving gaps | Append-only, gap-free, follower mirrors the leader |
| Primary design goal | Minimal, general consensus theory | Understandability and buildability |
| Real-world use | Google Chubby, Spanner, Megastore | etcd, Consul, CockroachDB, TiKV, Kafka KRaft |
The takeaway for an interview: Paxos and Raft are equivalent in power. Raft is not a better algorithm; it is a more teachable and buildable packaging of the same idea. Paxos is the theory everyone cites; Raft is the version most teams ship.
When you actually need this
Consensus — Paxos, Raft, or any relative — is expensive: a majority round-trip per decision, small groups only, and no progress at all when there's no reachable majority. You pay that price only when you genuinely need a single, strongly consistent, ordered source of truth.
- Reach for it when correctness demands one agreed answer: cluster metadata and configuration, leader election, distributed locks (/distributed-locks), transaction status. These are small, must-be-consistent, and can't tolerate two conflicting answers.
- Skip it when staleness is fine. A cache, a like counter, analytics rollups, or any workload happy with eventual consistency should not pay a consensus round-trip — a leaderless, gossip, or Dynamo-style design gives higher availability and throughput.
- Availability vs consistency: under a network split, only a side with a majority can decide; a side without one refuses to make progress. Consensus always chooses consistency over availability. That's the right trade for a source of truth and the wrong one for bulk data.
- It doesn't scale by adding voters. More acceptors means slower quorums and more messages, not more throughput. You scale by sharding the data across many independent small consensus groups.
Where Paxos runs in the wild
Paxos, almost always in its Multi-Paxos form, sits under some of the most important infrastructure ever built — usually as a coordination core that a larger system leans on, not as the whole system.
- Google Chubby — the lock service and small-file store that most of Google's infrastructure uses to elect leaders and hold configuration. Its replicas keep a consistent database using Multi-Paxos; it's the original industrial Paxos deployment, described in the Paxos Made Live paper.
- Google Spanner — the globally-distributed database uses Multi-Paxos per shard (a group of replicas per data range) to keep each range's writes consistent across data centers, combined with synchronized clocks for global ordering.
- Google Megastore — an earlier storage layer that ran Paxos per entity group to give strongly consistent replication across regions for App Engine applications.
- Apache ZooKeeper uses ZAB, and etcd, Consul, CockroachDB, and TiKV use Raft — protocols that are Paxos-family in spirit (a leader plus majority agreement) but chosen over raw Paxos precisely because they're easier to implement. That preference is the whole 'why Raft' story, playing out in production.
Common misconceptions & gotchas
Can two different values ever both be chosen if the timing is bad enough?
No — that's the one thing Paxos guarantees absolutely, through any pattern of crashes, delays, and lost messages. Once a value is accepted by a majority, majority overlap forces every later proposer's Phase 1 to see it, and the adopt-the-highest rule forces them to propose it. Two conflicting values can't both reach a majority. What Paxos does not promise is that it always chooses promptly (see the FLP result and dueling proposers).
Does a proposer get to propose the value it wanted?
Only if no acceptor in its Phase 1 majority has already accepted something. If any has, the proposer is forced to re-propose the highest-numbered accepted value it saw, dropping its own. This feels counterintuitive — you asked to set x = 8 and ended up helping x = 5 win — but it's exactly what prevents a value that might already be chosen from being overwritten.
Isn't a higher proposal number just a timestamp or a version?
No. It's a per-proposer priority tag that only ever increases and is unique across proposers. It orders competing proposals so acceptors know which to honor and which to refuse. It is not wall-clock time and it says nothing about which value is 'newer' or 'better' — a higher number can be forced to carry an older value.
Why does everyone say Paxos is so hard if the core is just two phases?
The single-decree core really is small. The difficulty is everything you must add to make it a usable system: running many instances for a log, electing and leasing a stable leader, filling log gaps, changing the set of acceptors safely, snapshotting, and handling the failure cases the papers gloss over. Raft's contribution was to specify those parts as part of the protocol — which is why it's the one people actually build.
In an interview
Lead with the problem Paxos solves, stated tightly: get a group of unreliable machines to agree on one value, and never decide two different ones, despite crashes and lost messages. Then name the three roles (proposer, acceptor, learner) and the two phases (prepare/promise, then accept/accepted).
The trap that separates a real answer from a memorized one is the safety rule. Don't just say 'two phases' — explain that in Phase 2 a proposer must adopt the highest-numbered value any acceptor already accepted, and say why: it can't tell whether that value has already been chosen, so it must keep it alive. If you can walk the dueling-example where a proposer is forced to abandon its own value, you've shown you understand Paxos rather than reciting it.
Then close the loop the interviewer is fishing for: single-decree Paxos decides one value; Multi-Paxos runs it per log slot with a stable leader that skips Phase 1, which is a replicated log. Paxos and Raft give the same guarantee; Raft exists because Paxos is hard to understand and build, so most systems ship Raft. Naming that relationship — same power, different teachability — is the strong finish.
References & further reading
- Lamport — Paxos Made Simple (2001) — the readable one: single-decree Paxos and Multi-Paxos in a few pages. Read this first.
- Lamport — The Part-Time Parliament (1998) — the original Paxos paper, told as a Greek-island parable — famously hard, the reason 'Made Simple' exists.
- Chandra, Griesemer & Redstone — Paxos Made Live: An Engineering Perspective (2007) — Google's account of turning Paxos into Chubby — the gap between the algorithm and a working system.
- Ongaro & Ousterhout — In Search of an Understandable Consensus Algorithm (Raft, 2014) — the Raft paper; its introduction is the definitive statement of why Paxos is hard and why Raft was built.
- Fischer, Lynch & Paterson — Impossibility of Distributed Consensus with One Faulty Process (1985) — the FLP result: why no consensus algorithm can guarantee both safety and termination in an asynchronous network.