There are two ways to keep a system out of a bad state, and they are not equally reliable. The first is to allow the bad state to exist and guard against it — check, at every place that matters, that things are consistent, and handle it when they aren’t. The second is to arrange your data so the bad state cannot be represented in the first place, so there is simply no arrangement of values that expresses it. The first is a promise you have to keep at every call site, forever. The second is a fact you establish once, in the shape of the data, and then never think about again.

The difference shows up in the failure mode. Consider the classic example: an object with a nullable “error” field and a nullable “result” field, where the intent is that exactly one is set. Nothing in that structure enforces the intent. Both can be null; both can be set; the type permits all four combinations when only two are legal, and now every piece of code that reads the object has to remember to handle the impossible ones — or, more honestly, most of them won’t, and one of those two illegal combinations will eventually occur and meet code that didn’t expect it. The invariant lived in everyone’s head and in a comment, which is to say it didn’t really live anywhere.

Now model the same thing as a single value that is either a result or an error, and never both and never neither. The illegal combinations aren’t guarded against; they’re unrepresentable — there is no way to construct the object in a state where both are present or both are absent, so no reader ever has to consider it. You didn’t move the check to a better place; you deleted the need for the check by making the bad state not exist. That’s the qualitative jump: from “we validate against the bad state” to “the bad state is not a thing that can happen,” and the second is enormously stronger because it doesn’t depend on anyone remembering anything.

This is the constructive answer to the two problems the earlier posts described. State is hard because each mutable, independent piece multiplies the configurations the system can be in — so the move is to make the illegal configurations impossible to express, collapsing that space to only the legal ones. Duplicated facts drift because nothing forces two copies to agree — so the move is to structure things so there’s one representation that can’t disagree with itself. In both cases the technique is the same: push the invariant down into the shape of the data, where it’s enforced by construction, instead of leaving it up in the logic, where it’s enforced by vigilance.

You can’t do this for every constraint — some invariants are genuinely dynamic and have to be checked at runtime, and pretending otherwise leads to contortions worse than the problem. But far more is expressible in the shape of data than people habitually use: making illegal combinations unrepresentable, replacing a pile of loosely related nullable fields with a value that can only hold the states that are actually valid, letting the structure carry the rule instead of a convention everyone is trusted to follow. Every invariant you move from vigilance into structure is one you can stop worrying about — one fewer place the system can quietly end up somewhere it was never supposed to be. The best state bug is the one the data model made impossible to write.