Open systems
Why variable values belong in the model now while an administration surface remains a separate, deferrable decision.
Model client-owned variability as data now. Build the administration surface only when its users and change frequency justify the cost.
A system is delivered once and lived in for years. Everything you carve into it as a constant is a thing that will be wrong later, and a question you had to ask to get it right now. Both costs are avoidable.
Design open systems: the client sets things to match how they work, rather than reshaping how they work to match a rigid flow.
The qualifier — two decisions, not one
"Make everything configurable" is its own failure. But the escape hatch is not "then hardcode it" — it is that configurability is two separate decisions, taken on different tests.
1 — Is the schema ready?
Does the record carry the identifier, the version reference, the foreign key to something the client may later administer?
Decided by reversal cost. If adding it later means a data migration, do it now — always.
This is cheap today and unrecoverable tomorrow. It is never traded away, whatever the budget or the client's size. The org chart, the process version and the category reference all live here.
2 — Is the administration surface built?
The screen, the validation, the governance, the rollback.
Decided by who will use it and how often the value changes.
Deferrable, and often should be. A client with no administrator gets a settings screen frozen at its defaults. In the meantime the value lives in a versioned configuration artefact that you change on their behalf — not in the specification, and not in a constant in the code.
The trap this closes: "we cannot afford the admin screen, so we'll hardcode it." That sentence conflates the two decisions and pays the only irreversible cost in the pair.
What each decision obliges you to build
Schema readiness obliges one thing, and it is small. The record holds a reference to the value rather than the value itself, and the reference survives the value being retired or renamed. Do it now, always.
Handing the client the controls obliges four more. These are the price of the surface, and they scale with who may touch it:
- Validation before a change takes effect. A value that can be set to an incoherent state and discovered in production is worse than a hardcoded one. References resolve, no unreachable state, no dead end, every value mapped.
- Withdrawal safety. Retiring something that live records depend on makes them unreachable with no visible error. Nothing is deleted; things are retired; retirement is refused while dependencies exist.
- Governance. Who may change it, whether a change needs approval, how it is rolled back, and the trail it leaves. A change to how public money moves is reviewed whether or not it needs a deployment.
- History. Old records keep the meaning they had, with the labels they carried at the time.
These four do not gate the schema
Their weight depends on who holds the controls:
| Who changes the value | What you owe |
|---|---|
| You, in a versioned configuration artefact | Validation and history. Governance is your review; rollback is republishing. |
| A trained administrator at the client | All four, with a real screen and a real audit trail |
| Anyone with an admin login | All four, plus approval on anything touching money or access |
Cannot fund the right column yet? Stay in the left one. Never resolve it by putting the value back into a constant — that is the one move that costs a migration to undo.
Where the line actually falls
The slogan is configuration changes the path, never the walls. It settles the argument about what misconfiguration is allowed to cost. It does not decide each field on its own — almost everything is a configurable value inside a fixed invariant.