Why Invariants Matter
On the one principle that separates resilient systems from fragile ones.
Every system has assumptions that must hold true. A balance that never goes negative. A lock that is always released. A message that is delivered exactly once. These are invariants — properties your system guarantees, no matter what.
When invariants break, everything breaks. Not immediately — that would be kind, a clean crash you could debug. Instead, they break silently. State drifts. Data corrupts. Users see stale reads. Two services disagree on who owns what.
What is an Invariant?
In formal terms, an invariant is a predicate P such that:
1
∀ operation O: P(state) → P(O(state))
If the system starts in a valid state, every valid operation keeps it in a valid state.
In practice, it means:
- A bank account balance is always
>= 0 - A distributed lock is held by at most one node at a time
- Every HTTP request gets exactly one response
- A Rust program never has a dangling pointer
Why Engineers Break Them
Most invariant violations come from missing boundaries, not missing logic.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// The invariant: balance >= 0
fn withdraw(account: &mut Account, amount: u64) {
// This compiles. This passes code review. This breaks at 3am.
account.balance -= amount;
}
// The invariant, enforced:
fn withdraw(account: &mut Account, amount: u64) -> Result<(), InsufficientFunds> {
if account.balance < amount {
return Err(InsufficientFunds);
}
account.balance -= amount;
Ok(())
}
The second version doesn’t just check — it makes the violation unrepresentable at the type level. The caller must handle the error. Rust’s type system turns a runtime prayer into a compile-time guarantee.
The Distributed Problem
Invariants get harder when state lives on multiple machines. CAP theorem tells us we can’t have it all, but it doesn’t mean we give up. We choose our invariants deliberately:
- CRDTs guarantee convergence — the invariant is “all replicas eventually agree”
- Raft/Paxos guarantee linearizability — the invariant is “operations appear sequential”
- Saga patterns guarantee eventual consistency — the invariant is “compensating actions always exist”
The key insight: you don’t avoid choosing invariants. You choose them, or they choose you.
This Blog
INVARIANT is where I document the truths I find in building systems — in Rust, in distributed architectures, in blockchain consensus, and in the emerging chaos of AI agents.
The code changes. The frameworks change. The invariants don’t.
If this resonates, follow along. More posts coming on Rust ownership as an invariant system, CRDTs in practice, and building deterministic agents over probabilistic LLMs.