Failure Models

Byzantine Failures, and Why You Probably Do Not Assume Them

A Byzantine fault is a component that does something arbitrary rather than simply stopping: answering differently to different peers, returning well-formed nonsense, or behaving correctly until it matters. Tolerating it costs 3f+1 nodes, signatures and an extra round — which is why almost nobody does, and why that choice deserves to be explicit.

▶ Run the lab

The question this answers

The question

What if a node does not just fail, but lies — and should my system care?

The guarantee — the property claimed, and its scope

A crash-fault-tolerant protocol guarantees nothing whatsoever in the presence of a single Byzantine participant: a node that is up and answering incorrectly can violate safety in a system designed for 2f+1. A Byzantine-fault-tolerant protocol guarantees safety and liveness while at most f of 3f+1 participants misbehave arbitrarily.

Everything below is bought to hold this sentence. "Strongly consistent" with no scope attached is a slogan, not a guarantee — read what it actually covers, and what it explicitly does not.

What a node knows — observation versus inference

A node knows the messages it received and whether they are internally well-formed and correctly signed. It cannot know whether the *content* is honest, and it cannot know whether other nodes received the same content — unless the protocol makes that checkable, which is precisely what Byzantine agreement protocols are for and what ordinary ones are not.

A node knows its own state and the messages that arrived. Everything else is inference from evidence that was already stale. "B has not replied in five seconds" is knowledge; "B is down" is a decision — and usually the bug.

What guarantee?What does a node know?How does it work?What can fail?How does it fail?Where is coordination?What holds under failure?How does it recover?How would you know?What is the simpler thing?
byzantinetrustcorruptionconceptual

What "arbitrary" actually covers

The name comes from a thought experiment about generals coordinating an attack when some of them may be traitors, and it is unfortunate in one respect: it makes people think of malice, when the model is simply *unconstrained behaviour*. Under a crash model, a node’s only permitted misbehaviour is to stop. Under a Byzantine model it may do anything the protocol allows a message to express, including things no honest implementation would do.

The behaviours worth having in mind: equivocation — telling node A one thing and node B another, which is the behaviour that breaks quorum arguments, since two nodes can each hold a majority-backed but different view. Well-formed falsehood — a value that passes every validation and is simply wrong. Selective participation — behaving correctly except in the specific circumstances that matter, which is indistinguishable from bad luck. Delayed betrayal — behaving correctly for a long time, which is why "it has been fine so far" is not evidence.

The causes are more mundane than the name suggests. Memory bit flips in a machine without ECC. A storage device returning stale or corrupted blocks after an incomplete write. A firmware bug. Two versions of a service deployed simultaneously with an incompatible interpretation of the same field. A compromised host. Only the last one involves an adversary, and the first two occur at measurable rates in any large fleet.

Crash / omission tolerantByzantine tolerant
Nodes to tolerate f faultsprotocol2f+13f+1
Tolerate 1 faultprotocol3 nodes4 nodes
Message authenticationprotocolOptional; TLS at the transport is typicalRequired per message, and verifiable by third parties
Communication roundsprotocolOne round to a majorityAn additional all-to-all round to detect equivocation
What a wrong answer doesprotocolCan violate safety with one faulty nodeIs outvoted and attributable
Typical usetypicalDatabases, coordination services, most infrastructurePermissionless ledgers, avionics, some clearing systems
Crash-tolerant versus Byzantine-tolerant

Why 3f+1, in one paragraph

The arithmetic is worth understanding because it explains the cost. With n nodes and up to f faulty, you must be able to make progress after hearing from only n − f nodes, since the faulty ones may simply never answer. Among those n − f responses, up to f may be from Byzantine nodes telling you something false. So the honest responses number at least n − 2f, and for the honest ones to outnumber the false ones you need n − 2f > f, giving n > 3f. Hence 3f+1.

Contrast the crash case: a node that fails simply does not answer, so every answer you receive is honest. You need only that any two quorums intersect, giving n > 2f. The entire extra cost of Byzantine tolerance comes from the fact that a received answer might be a lie, and therefore cannot be counted as evidence on its own.

The second cost, equally important, is that a quorum is no longer sufficient on its own. A Byzantine node can equivocate, so nodes must also verify that everyone was told the same thing — which requires an extra communication phase where nodes exchange what they heard. That is why Byzantine protocols have more rounds, and why their message complexity grows faster with cluster size.

The honest position for ordinary infrastructure

Almost every distributed database, queue and coordination service in common use assumes non-Byzantine faults, and that is a reasonable engineering decision when all participants are inside one trust boundary and one operator. The threats the model would address are cheaper to handle by other means: TLS prevents tampering in transit, access control prevents unauthorised participants, code review and deployment controls address the compromised-host case, and — critically — checksums address corruption.

That last one deserves emphasis, because it is the Byzantine fault that actually occurs. A storage device returning a corrupted block is a node giving a well-formed wrong answer, which is Byzantine by definition. The response is not a Byzantine consensus protocol; it is end-to-end checksums, so the wrong answer is detected as wrong rather than voted on. This is a targeted defence against the specific arbitrary behaviour that happens in practice, at a rounding error of the cost — and it is worth checking whether your storage layer, your network protocol and your application actually have it, because the assumption that "something below me checksums this" is frequently false.

Where the choice genuinely flips is when participants are outside your trust boundary: a public ledger where anyone may join, a consortium where the members are separate legal entities with conflicting interests, or a safety-critical system where a sensor may fail in an arbitrary rather than a fail-stop manner. In those settings the extra node and the extra round are the price of the problem, not overhead.

  • Inside one trust boundary: assume crash faults, and defend corruption with checksums.
  • Across trust boundaries: the assumption stops being defensible, and 3f+1 is the price.
  • Transport tampering: TLS, not a consensus protocol.
  • Unauthorised participants: authentication and authorisation, not fault tolerance.
  • Silent corruption: end-to-end checksums, verified where the data is used rather than where it is stored.

The half-measures that are worth taking

You do not have to choose between full Byzantine tolerance and nothing. Several cheap practices buy meaningful protection against the arbitrary behaviours that actually occur.

Verify rather than trust. Where one component computes something another depends on, having the consumer check the result — a checksum, a re-derived total, a range assertion — turns a silent wrong answer into a loud one. This is defence in depth applied to correctness rather than to security.

Make claims attributable. Signed or at least authenticated messages mean that when something wrong appears, you can determine which component produced it. Without attribution, a corrupted value propagated through three services is nearly impossible to trace to its origin.

Cross-check independent derivations. Where two systems should agree — a ledger and an accounting system, a search index and its source — a periodic comparison catches arbitrary faults that no individual health check would. This is the same reconciliation machinery that partial failure requires, doing double duty.

Treat clients as Byzantine, always. This one is not optional. Anything outside your trust boundary — a browser, a mobile app, a partner integration — may send arbitrary input, and the server must validate rather than trust. Security owns this thoroughly, and it is worth noticing that it is the same model: you simply already apply Byzantine assumptions at the edge, and choose not to apply them internally.

Key points

  • A Byzantine fault is arbitrary behaviour, not necessarily malicious — corruption and version skew qualify.
  • Equivocation, telling different nodes different things, is the behaviour that breaks ordinary quorum arguments.
  • 3f+1 is required because a received answer may be a lie and cannot count as evidence by itself.
  • Most infrastructure assumes non-Byzantine faults; that is defensible inside one trust boundary and should be explicit.
  • The Byzantine fault that actually happens is silent corruption, and its answer is end-to-end checksums, not a consensus protocol.

The chain, answered

Every field here is required, which is why no lesson in this domain can recommend a design without naming what an operator sees when it fails, what survives the partition, what repairs it afterwards, and the simpler thing to consider first.

How it works
  • Each node signs its messages so that a claim is attributable and cannot be forged by a relay.
  • A proposal is broadcast, and nodes exchange what they received to detect equivocation.
  • A node accepts a value only after seeing matching reports from more than two thirds of participants.
  • Faulty nodes are outvoted rather than merely absent, and their misbehaviour is attributable after the fact.
  • Progress requires 2f+1 matching responses out of 3f+1, which is why the cluster must be larger.
What can fail at the boundary
  • A node tells different peers different things and both peers believe they have majority support.
  • A storage device returns a well-formed but corrupted value that passes every schema validation.
  • A partially-deployed version interprets a field differently and produces consistently wrong results.
  • A host is compromised and participates correctly in the protocol while producing dishonest values.
  • Memory corruption produces a wrong value in a component with no checksum on the path.
How it fails — what an operator sees
  • Split agreement through equivocation: two subsets of a cluster commit different values, each believing it had a quorum. The operator sees two divergent logs with no partition in the network metrics.
  • Silent corruption propagated: a wrong value is read, used and re-written by downstream systems. The operator sees the error only when a reconciliation or a customer finds it, by which time it has been copied several times.
  • Version-skew disagreement: two deployed versions disagree on a field’s meaning. The operator sees results that differ depending on which instance served the request, correlating with deploy percentage rather than with any input.
  • Undetectable origin: a wrong value appears in three systems and nothing records which produced it first. The operator spends the incident on archaeology rather than on remedy.
Where coordination is required
  • Byzantine agreement requires more participants and more rounds than crash-tolerant agreement, which shows up directly as write latency and as message volume growing with cluster size.
  • The additional round exists specifically to make equivocation detectable; without it, a quorum is not evidence of a single shared value.
  • Signatures move part of the cost to CPU and make claims verifiable by parties who did not observe the original exchange — which is what allows accountability after the fact.
What still holds under failure
  • A Byzantine-tolerant protocol keeps its safety and liveness properties while at most f of 3f+1 nodes misbehave.
  • A crash-tolerant protocol offers nothing under a single Byzantine fault — not degraded correctness, nothing.
  • End-to-end checksums keep working regardless of protocol, which is why they are the highest-value partial measure.
How it recovers
  • Detect: checksum verification at the point of use, and cross-system reconciliation for values that two systems should independently agree on.
  • Contain: quarantine the suspect component rather than restarting it, so the evidence survives.
  • Recover: rebuild the affected data from a source verified independently, not from a peer that may have copied the fault.
  • Reconcile: trace the propagation of the wrong value, which requires attribution to have been recorded before the incident.
  • Verify: confirm the checksums pass end to end after repair, rather than confirming the systems now agree — they can agree on the wrong value.
How you would know
  • Checksum mismatch counts at every layer that computes them, as a first-class metric rather than a log line.
  • Reconciliation disagreements between systems that derive the same quantity independently.
  • Version distribution during and after a deploy, correlated with result differences — the cheapest detector of version-skew faults.
  • Provenance on derived values: which component produced this, and from which inputs.
When it helps
  • When participants span trust boundaries — separate organisations, public participation, or an environment where a host may be compromised.
  • When the cost of an incorrect committed value is catastrophic and irreversible, as in safety-critical control or settlement systems.
When it hurts
  • Inside a single operator’s infrastructure it multiplies node count, latency and code complexity against threats that access control and checksums already address.
  • It also creates a false sense of coverage: a Byzantine protocol does not protect against a bug present in every replica, which is a far more common cause of consistent wrong answers.
Simpler alternatives
  • End-to-end checksums: covers the corruption case, which is the Byzantine fault that actually occurs, at negligible cost.
  • Authentication and authorisation at every boundary: removes the unauthorised-participant threat without touching the consensus protocol.
  • Independent verification: have a second, differently-implemented path re-derive critical values and compare.
  • Reduce the trust surface instead: keep the components that must agree inside one boundary, so the Byzantine question does not arise.

Equivocation is what breaks an ordinary quorum

Equivocation is what breaks an ordinary quorum
A crash-tolerant protocol assumes a node that answers is telling the truth. One node that answers differently to different peers is outside that assumption — and one is enough.
quorum
3 of 5
crash faults tolerated
2
Byzantine faults tolerated
0
two conflicting decisions
possible
n1 tells one group "commit A" and the other "commit B". Both messages are well formed and correctly authenticated.protocol
n1 ↔ n2: lossyn1 ↔ n3: lossyn1 ↔ n4: lossyn1 ↔ n5: lossyn1 · candidate · up — faulty: says A to some, B to othersn1↑ candidaten2 · follower · up — heard "A"n2· followern3 · follower · up — heard "A"n3· followern4 · follower · up — heard "B"n4· followern5 · follower · up — heard "B"n5· followerlossylossylossylossy
lossy
  • n1 — faulty: says A to some, B to others
  • n2 — heard "A"
  • n3 — heard "A"
  • n4 — heard "B"
  • n5 — heard "B"
What each node believes
  • n2believes “the cluster decided A (3 of 5 said so, counting n1)”✕ and it is false
  • n5believes “the cluster decided B (3 of 5 said so, counting n1)”✕ and it is false

Every node above is acting on what it believes. Nothing in the cluster tells the mistaken one that it is mistaken.

n1 counts itself in both groups: 2 honest nodes plus n1 make a quorum of 3 for A, and 2 honest nodes plus n1 make one for B. Both quorums are legitimate by the count, and the two halves of the cluster now hold different histories. Every node behaved correctly except one, and that one never crashed — it answered.
"Byzantine" means arbitrary, not malicious. Bit flips, corrupted storage reads and version skew all produce it with no attacker present. For ordinary infrastructure inside one trust boundary, assuming crash faults is defensible and should be explicit — and the arbitrary fault that genuinely happens, silent corruption, is answered with end-to-end checksums rather than with 3f+1. Across a trust boundary, the assumption stops being defensible and the larger cluster is the price.
protocolThe counts follow from the quorum argument. 2f+1 makes any two quorums share a node, which is sufficient only if that shared node is honest; 3f+1 with an all-to-all echo round makes a received answer checkable, which is why the cluster must be larger and the round trips more numerous.

What people believe, and what is true

Claim

Byzantine means malicious.

Reality

It means arbitrary. Bit flips, corrupted storage reads and version skew all produce Byzantine behaviour with no attacker present.

Claim

We do not need it because our network is private.

Reality

A private network addresses the adversary, not corruption. Whether that is sufficient is a decision worth making explicitly rather than by default.

Claim

Byzantine tolerance would make us safe from bad data.

Reality

It makes you safe from a minority producing bad data. A bug in the shared implementation produces the same wrong answer everywhere and is voted through unanimously.

Claim

Raft with TLS is Byzantine-tolerant.

Reality

TLS prevents tampering in transit between honest endpoints. It provides nothing against an endpoint that is itself wrong, which is the entire Byzantine case.

Go deeper

Only the levels this lesson can honestly fill — a missing level is a claim nobody had.

Overview

A Byzantine fault is a component doing something arbitrary rather than stopping. Tolerating it needs 3f+1 nodes and signatures. Most systems reasonably assume it away — but should say so, and should checksum, because corruption is a real Byzantine fault.

Practical

Decide explicitly whether any participant sits outside your trust boundary. If none does, assume crash faults and spend the effort on end-to-end checksums, attribution on derived values, and reconciliation between systems that should independently agree. Treat every client as Byzantine, because it is.

Advanced

The arithmetic: with n nodes and f Byzantine, progress must be possible after n−f responses, of which f may be false, so honest responses number n−2f and must exceed the false ones — hence n > 3f. Crash faults need only quorum intersection, n > 2f, because a crashed node stays silent rather than lying. The second structural cost is equivocation: a quorum alone no longer certifies a single value, so protocols add an all-to-all phase in which nodes report what they were told, making a two-faced proposer detectable. That phase is why message complexity is quadratic in cluster size and why Byzantine clusters stay small.

Apply it

Reason about this
  • A replica begins returning subtly wrong values for one table after a disk incident. Trace what each layer of a typical stack would and would not detect.
Interview questions
  • 💬 Give an example of a Byzantine fault with no attacker involved.
  • 💬 Why does Byzantine tolerance need 3f+1 rather than 2f+1?
  • 💬 What is equivocation and why does it break an ordinary quorum argument?