The question this answers
What if a node does not just fail, but lies — and should my system care?
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.
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 "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 tolerant | Byzantine tolerant | |
|---|---|---|
| Nodes to tolerate f faultsprotocol | 2f+1 | 3f+1 |
| Tolerate 1 faultprotocol | 3 nodes | 4 nodes |
| Message authenticationprotocol | Optional; TLS at the transport is typical | Required per message, and verifiable by third parties |
| Communication roundsprotocol | One round to a majority | An additional all-to-all round to detect equivocation |
| What a wrong answer doesprotocol | Can violate safety with one faulty node | Is outvoted and attributable |
| Typical usetypical | Databases, coordination services, most infrastructure | Permissionless ledgers, avionics, some clearing systems |
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.
- • 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.
- • 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.
- • 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.
- • 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.
- • 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.
- • 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.
- • 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 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.
- • 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.
- • 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
- n1 — faulty: says A to some, B to others
- n2 — heard "A"
- n3 — heard "A"
- n4 — heard "B"
- n5 — heard "B"
- 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.
What people believe, and what is true
Byzantine means malicious.
It means arbitrary. Bit flips, corrupted storage reads and version skew all produce Byzantine behaviour with no attacker present.
We do not need it because our network is private.
A private network addresses the adversary, not corruption. Whether that is sufficient is a decision worth making explicitly rather than by default.
Byzantine tolerance would make us safe from bad data.
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.
Raft with TLS is Byzantine-tolerant.
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
- ⚡ 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.
- 💬 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?