Why Temporary Exceptions Become Permanent System Rules

Why Temporary Exceptions Become Permanent System Rules

Software systems often contain decisions that begin in the same way. A customer urgently needs a feature, a batch of old data does not match a new format, or a release cannot wait for a complete redesign, so the team adds a special condition. Calling it temporary is not necessarily an excuse. Under the immediate constraints of time, cost and risk, allowing one case to bypass the normal path may be the most sensible option. The difficulty is that once the exception works, it no longer exists in the environment in which it was created.

A standard rule handles many similar cases; an exception handles a smaller case that remains different. Removing that difference properly may require changes to data, interfaces and the processes of several teams. Adding a conditional branch at the edge has a smaller impact, produces an immediate result and appears easier to reverse. Instead of redesigning the core for the exceptional case, the system opens a small side path beside it.

Once that path is used, new relationships begin to form around it. Support staff learn that a particular group of users must take it. Operational reports interpret the data it produces. Other programs begin relying on its observable behaviour, and tests record that behaviour as correct. People who join later may not know why the path was created; they only know that something fails when it is removed. A response designed for one difference gradually becomes a condition shared by many parts of the system.

The costs of keeping and removing it are now uneven. The cost of keeping it is spread across routine maintenance: someone reads an extra branch, runs a few more tests or remembers one additional operating step. The cost of removal arrives all at once. The team must identify every user, check whether old data remains, organise a migration and accept the risk of overlooking a dependency. Even when everyone agrees that the design is untidy, few people will begin a cross-system change merely to make it cleaner.

Distributed responsibility makes the arrangement more stable. The developer who wrote the exception may have left. The customer who requested it may no longer use the system. Current maintainers are responsible for keeping the service running, but no one clearly owns the work of proving that the exception is safe to remove. The original reason can disappear while the conditions that now preserve the exception remain. New constraints have replaced the old justification.

The exception also shapes later design. New features add their own conditions to remain compatible with it. Documentation turns it into an operating step. Monitoring may even use its boundary to interpret system behaviour. At that point it is no longer an isolated patch attached to the system; it is part of the system. Deleting a few lines of code removes the visible form of the exception without replacing the relationships that it carries.

This is why “we will clean it up later” so often fails. Time does not make removal easier by itself. It gives dependencies more opportunities to grow. A more effective approach is to limit the exception's expansion when it is introduced: state its scope, name an owner, observe how often it is used, define a review condition, and prepare a migration path for affected data or users. An expiry date cannot remove an exception automatically, but it can force the team to ask whether the original difference still exists and what dependencies have formed around it.

Temporary exceptions are not automatically bad design. A system must keep operating under real constraints, and a local detour may be exactly what preserves the wider service. The important task is not to forbid exceptions, but to keep them visible, traceable and reversible. Otherwise, a gap opened to accommodate one difference will attract new relationships until the exception to the rule becomes a rule of its own.

Sustenesis Note

An exception persists not only because of its original purpose, but because dependencies, responsibility and risk are redistributed around it. Removing it requires those relationships to be rearranged; cancelling the first special condition is rarely enough.


Discover more from Geoffrey Chen

Subscribe to get the latest posts sent to your email.