Skip to content

Tolerant Reader / Strict Writer Policy

Interface strictness policy — instantiates Asymmetric Interface Tolerance Calibration

Sets the interface's standing regime as deliberately asymmetric — strict about what the system emits, liberal about what it accepts — and writes that choice down as policy rather than leaving it to each parser.

Tolerant Reader / Strict Writer Policy is the archetype's namesake move stated as a standing rule: emit conservatively, accept liberally, on purpose and in writing. Its defining contribution is the decision itself — it fills in the strictness matrix's asymmetric cell and defines how wide the accept side may open, so the interface's tolerance is a governed choice rather than an accident of whatever each implementer happened to code. It does not itself lint output or normalize input; it declares the regime those tools then carry out. The point of writing it down is that "be liberal in what you accept" is only safe when paired with a bound: the policy states both which asymmetry the interface runs and how far the tolerance extends before it stops.

Example

A city's open-data platform ingests spreadsheets from dozens of departments — police, transit, parks — each maintained by different people with different habits: date formats, column names, encodings, stray header rows. A brittle importer would reject most of them and generate endless tickets. So the platform adopts a tolerant-reader / strict-writer policy. As a reader it accepts a wide, explicitly-bounded envelope: several date formats, case-insensitive headers, common encodings, blank lines. As a writer it emits exactly one canonical form to every downstream consumer — ISO dates, a fixed schema, UTF-8 — no exceptions. The policy document names both sides: here is the list of input variations we tolerate (and everything outside it is rejected, not guessed); here is the single output shape we guarantee. Departments get frictionless ingestion; every dashboard and API downstream sees one clean shape, because the messiness was absorbed at the reader and never re-emitted.

How it works

  • Name the regime explicitly. The policy states the interface is strict-out / liberal-in — one cell of the strictness matrix — so the asymmetry is a recorded decision, not an emergent one.
  • Bound the accept side. "Liberal" is defined as a specific enumerated envelope of tolerated variations, with a hard edge beyond which input is rejected rather than charitably interpreted.
  • Delegate enforcement. The strict-emit clause is handed to an output linter; the normalization of accepted variants to a canonicalizing parser. The policy sets direction; other mechanisms execute it.
  • Keep the two sides from leaking. Crucially, tolerated inbound variety is never propagated outbound — what the reader accepts loosely, the writer still emits strictly, so tolerance stops at the boundary.

Tuning parameters

  • Accept-envelope width — how many inbound variations are tolerated. Wider eases integration but enlarges the surface the reader must handle correctly and safely.
  • Asymmetry direction — the usual strict-out / liberal-in can be flipped to strict-in / liberal-out for a source-of-truth publisher; the policy is where that per-direction choice is made.
  • Envelope explicitness — whether tolerated variants are enumerated or left to "be reasonable." Enumerated envelopes are safe and testable; vague ones invite scope creep and silent protocol expansion.
  • Repair visibility — whether accepted-but-nonstandard input is silently normalized or normalized-and-flagged, trading a quiet interface against a signal that a producer is drifting.
  • Review cadence — how often the envelope is revisited, so "temporary" tolerances don't harden into a permanent second contract.

When it helps, and when it misleads

Its strength is resilience without decay when — and only when — both halves are honored: strict emission keeps the ecosystem's de-facto contract from rotting, while bounded liberal acceptance keeps harmless variation from causing needless failure. Writing the regime down is what makes it auditable and testable instead of a folk practice scattered across parsers.

Its danger is the half-applied version. The interface-design canon is Postel's robustness principle — "be conservative in what you send, be liberal in what you accept"[1] — and its much-discussed failure is that liberal acceptance, left unbounded and unmonitored, teaches producers that the written contract is optional: the real protocol quietly becomes whatever receivers happen to tolerate, and every reader must forever bug-for-bug match every other. The classic misuse is invoking "tolerant reader" to justify accepting anything while quietly neglecting the strict-writer half — the discipline that actually holds the contract. The guard is to bound and enumerate the accept envelope, monitor what enters it, and enforce the emit side with real teeth: tolerance with an edge and a gauge, never tolerance as a shrug.

How it implements the components

  • strictness_regime_matrix — it is the filled-in matrix for this interface: the recorded per-direction decision that emission is strict and acceptance is liberal.
  • inbound_acceptance_envelope — it defines the bounded set of inbound variations the receiver will tolerate, and the hard edge past which input is rejected rather than guessed.

It declares but does not enforce: the strict-emit side is carried out by Strict Output Linter, the actual normalization of accepted variants by Lenient Parser with Canonicalizer, and the specific treatment of unrecognized fields by the Unknown-Field Handling Rule.

References

[1] Postel's robustness principle — "be conservative in what you do, be liberal in what you accept from others," articulated by Jon Postel in the early TCP specifications. It is the origin of the strict-writer / tolerant-reader stance, and its much-discussed downside — that unbounded acceptance lets the de-facto protocol drift away from the written one — is exactly why this policy insists the accept side be bounded and the emit side enforced.