Comparisons
Pairs engineers genuinely confuse — goal and implementation, MVP and bad prototype, prototype and spike, reversible and irreversible. Neither column wins; what decides is the problem. Each record leads with the confusion, because the confusion is what it costs.
Essential vs accidental complexity
Accidental complexity is mistaken for seriousness: a todo list with a message queue looks more "real" than one without, so the queue is kept, and the invariant that actually mattered — a task is never lost — is never written down. The cost is a system that is hard to change for reasons unrelated to its problem. The other confusion runs the other way: calling something accidental because it is inconvenient, and stripping out the reconciliation logic that the money genuinely required. The test is whether the complexity would exist in every correct solution; if it would, it is essential and must be handled well, and if it would not, it needs a bottleneck or a requirement to justify it.
To know what cannot be simplified away — the parts of the design that will exist in every correct version.
To know what can be removed, and to make each remaining piece justify itself against a measured need.
| Aspect | Essential — complexity the problem itself forces: money must balance, stock must not oversell, messages must arrive in order | Accidental — complexity the solution added: the queue, the cache, the third service, the framework ceremony |
|---|---|---|
| Comes from | The problem | The solution |
| Removable | No — only moved | Yes, at the cost of whatever it was bought for |
| Example in a store | Concurrent purchase of the last unit | A cache in front of a table with a thousand rows |
| Justified by | An invariant or a requirement | A measured bottleneck or a real constraint |
| Sign of the mistake | Treated as optional — "we will handle that later" | Treated as mandatory — "real systems have one" |