Postel's Law: Be Conservative in What You Send, Liberal in What You Accept

Your API receives a field with an unexpected type. The client sent "42" where the schema says 42. Reject the request, or coerce the string to an integer? Both answers have production consequences. The choice you make encodes your position on L12 — Postel's Law.

L12 is the Robustness Principle: be conservative in what you send; be liberal in what you accept. It is one of the oldest engineering laws in networked systems. It is also one of the most misapplied. The version most engineers remember is a slogan. The version that survives contact with production is a discipline.

This article covers what the law says, where it holds, where it breaks, and the specific signal that tells you which side of the line your system sits on.


What the law actually says

Parse inputs permissively. Produce outputs conservatively.

Permissive parsing means your system handles variation that does not affect correctness. Two date formats. A field named user_id in one request and userId in the next. A trailing whitespace character. Missing optional fields. An integer sent as a numeric string. The parser normalises all of these into a single internal representation.

Conservative output means your system emits one canonical form. Not the form the receiver requested. Not the form the last integration expected. The form your specification defines. Every response looks identical, field by field, format by format.

The law asks you to be asymmetric. The input side absorbs the messiness of the real world. The output side refuses to add to it.


Why the law exists

Networked systems accumulate producers over time. Every producer interprets the specification slightly differently. Some fields drift. Some encodings vary. Some clients skip parts of the protocol they did not understand. A receiver that rejects every deviation refuses most of its real traffic.

This is AT3 — Simplicity vs Flexibility. A strict parser is simpler. It has one code path. It rejects anything that does not match the schema exactly. A permissive parser is more flexible. It has many code paths — one for each variation it tolerates. Postel's Law chooses flexibility on the input side and simplicity on the output side.

The engineering reason is asymmetric power. You control what you send. You do not control what others send. Refusing to normalise input pushes the cost onto every caller. Refusing to normalise output pushes the cost onto the receiver, which multiplies across every consumer of your service.


The failure mode the law introduces

FM8 — Schema/Contract Violation. This is the failure mode Postel's Law is designed to prevent on the input side and, in its overreach, causes on the output side.

A strict parser exposes FM8 loudly. A caller sends the wrong shape. The request fails with a clear error. The caller sees the error immediately. The contract is enforced at the boundary.

A permissive parser hides FM8. A caller sends the wrong shape. The parser normalises it. The request succeeds. The caller never learns the contract was wrong. The next release of the parser tightens one rule. Every caller who was silently relying on the old tolerance breaks at once.

This is the paradox. Permissive parsing prevents small contract violations by absorbing them. It creates large contract violations by hiding them. Every tolerated variation becomes an undocumented feature. Every undocumented feature has consumers. Every consumer breaks when the tolerance is removed.

The critique in the source is direct. A system that accepts too wide a range of inputs silently may never surface encoding errors until they become FM9 — Silent Data Corruption. The parser coerced the string. The value was interpreted as an integer. Two systems downstream read the same field with different rules. The data diverges. No alert fires. The corruption compounds.


The engineering rule that survives production

The law as slogan is dangerous. The law with judgment is useful. The distinction is one sentence.

Be liberal in accepting variation that does not affect correctness. Be strict about variations that do.

Variation that does not affect correctness is presentational. Whitespace. Field name casing. The order of properties in a JSON object. Optional fields absent versus explicitly null. An integer sent as a numeric string when the type is unambiguous. Normalise these. The caller's intent is clear. The system's behaviour is identical whether the parser tolerated the variation or the caller had sent the canonical form.

Variation that affects correctness is semantic. A date in an unknown format. A currency amount without a currency code. A field the sender inserted that the spec does not describe. An enum value the schema does not list. Reject these. The caller's intent is not clear. Two implementations of the parser will make different guesses. Silent coercion is silent divergence.

The test is not "can I parse this." The test is "will every parser of this input agree on what it means." If the answer is yes, be liberal. If the answer is no, be strict.


The output half is not optional

Most discussion of Postel's Law focuses on the input side. The output side is the half that keeps the ecosystem workable.

Conservative output means your service emits one form. If the spec allows dates in three formats, you pick one and always send it. If field names may be camelCase or snake_case, you pick one and always emit it. If a field may be absent or explicitly null, you choose one convention and hold it.

The reason is Hyrum's Law's cousin. Every variation you emit becomes a variation some consumer depends on. If half your responses omit an optional field and half include it as null, some consumer has written a code path for each. The day you unify the two, that consumer breaks. You did not change the contract. You changed a behaviour the contract never guaranteed. The consumer depended on it anyway.

Conservative output narrows the surface area of accidental contracts. It gives you room to change internals without breaking callers. It is the discipline that keeps the input-side liberality safe.


Where the law lives in your architecture

Every boundary in your system is a place to apply L12. The API accepting external requests. The database driver serialising a row. The message queue consumer parsing an event. The config loader reading a file. Each one has an input side and an output side. Each one has to answer the same question: what do I tolerate, what do I reject, and what shape do I emit.

The pattern that scales is a normalisation layer at every boundary. Inputs are parsed with defined tolerances and translated into an internal canonical representation. Outputs are serialised from the canonical representation into the single canonical wire form. The internal core operates on one shape only. The boundary layer absorbs the variation.

This has two consequences. The core code stays simple — it never handles the variations. The boundary layer stays observable — every tolerated variation is a single named code path, easy to log, easy to measure, easy to remove when a caller finally sends the canonical form.


The signal that tells you this applies to your system

Two signals, in this order.

The first: you find a bug caused by a client sending malformed input, and the parser silently accepted it. The system produced wrong output. No error was raised. This is FM9 leaking through a parser that was too liberal. The rule you were missing is the strict-when-semantic half of the law.

The second: you ship a small change to your API — you tighten a validation rule, you rename a field in the response, you drop a header — and three integrations break within a week. The clients were depending on behaviour your spec never promised. This is FM8 arriving because your output side was not conservative enough. Every observable variation in your responses is a contract you did not intend to sign.

If either signal appears in your incident history, you are on the wrong side of L12 somewhere. The fix is not more validation or less validation. The fix is naming, at every boundary, which variations are presentational and which are semantic — and enforcing the asymmetry the law describes.


The full framework treatment — compression blocks, three-level exercises, and the complete AT/FM mapping — is in the Reference Book, Chapter 13 (Engineering Laws). Free chapter available at computingseries.com/books/ref.