The rules always end up in the code
I noticed something about my own career recently, and it was not flattering at first.
In 2017 I built backend services on top of an in-house BPMN workflow engine — a system whose whole purpose was to hold business processes as models rather than as code. In 2020 I built something engine-like myself, to hold the business rules for a prediction API. It worked, and it is still the part of that design I am least sure was the simplest answer available.
In 2025 I started building agents that pull business rules back out of code that no longer explains itself.
Same problem, three times, approached from three directions, roughly ten years apart. Once I saw it I could not unsee it.
The problem
Every business rule starts as a sentence somebody says out loud.
Orders over this amount need approval. This customer type gets that discount. If the appointment is within 24 hours, do not allow self-service cancellation.
Then it gets written down, maybe. Then it gets implemented. Then the sentence and the implementation drift apart, because the implementation is what runs and the sentence is what someone wrote in a document in 2019.
Five years later, the only authoritative statement of the rule is the code. And by then the person who wrote it has left, and the person who asked for it has left, and what remains is a condition on line 400 that nobody dares remove because something, somewhere, probably depends on it.
This is not a failure of discipline. It is what happens by default, everywhere, to everyone.
Why the obvious fix does not hold
The obvious fix is to keep the rules outside the code. Model them. Put them in an engine, a rules table, a BPMN diagram, a configuration file. Give the business a place to see and change them without a developer.
I have now been on three sides of this, and my honest read: it works, and then it stops working.
It stops working because the model can only express what its designers anticipated. The first rule that does not fit gets implemented as an exception — in code, next to the engine, “just for now.” Then a second. Within a couple of years the authoritative rules are split across two places, and the modelled ones are the incomplete half, which is worse than having one messy source, because now people trust something that is only mostly true.
The engine did not fail. It just could not absorb reality faster than reality arrived.
What I think is actually true
The rules end up in the code because the code is what executes. Anything that is not executing is a description, and descriptions drift from behaviour unless something forces them not to.
So the durable question is not how do we keep the rules out of the code. It is:
Can we read the rules back out of what actually runs?
For most of my career the answer was: yes, in principle, and nobody will pay for it. Reading a rule back out meant an engineer reading a codebase carefully, understanding intent from structure, and writing down what they found. Expensive, slow, and boring enough that it only happened during migrations, when it was already urgent.
That is the part that changed. Reading intent out of a large codebase and writing it in language a business person can check is now something a machine does adequately and cheaply. Not perfectly. Adequately — which is a different economic category from what came before, because it moves the work from a project someone must approve to something you can just do.
What I would not claim
That you can point a model at a repository and receive the truth.
The output needs an engineer who can tell a real rule from an accident of implementation. A great deal of what looks like a business rule is a workaround for a bug fixed years ago, or a constraint from a system that has since been replaced. A model reports both with equal confidence. Deciding which is which requires knowing what the business actually does, which is the same judgement the job always required.
What changed is the ratio. The reading is cheap now, so the expensive part is the part that was always worth paying for — someone deciding what matters.
Why it is worth doing before you need it
Nobody funds this work on its own merits. It gets funded when there is a migration, an acquisition, a regulation, or a supplier being replaced — at which point it is on the critical path and the estimate is a guess.
But the excavation does not require the deadline. It just usually waits for one.
If your organisation runs software older than about a decade, the rules that govern your business are already partly illegible, and you already know which system people mean when they say “nobody really understands that one.” Making it explain itself is possible now for a fraction of what it cost five years ago.
Ten years, three attempts, and the thing I would tell my 2017 self: stop trying to keep the rules out of the code. Get good at reading them back out.