Almost every business application we build eventually needs approval chains. A purchase order above a certain amount needs a manager's sign off. A budget needs finance approval before it goes live. A discharge needs a doctor to confirm it. The easy way to build this is to hard code each chain as a single if statement inside the module that needs it. That works fine for the first chain, and turns into a mess by the fifth, because every new rule means another developer has to read and change business logic that is not really theirs to own.

The pattern that has lasted for us is a separate workflow engine that any part of the system can hand a record to, along with which rule applies, and get back a clear state, pending, approved, or rejected, without that original module needing to know how many steps exist or who handles them. The purchase order module's only job is to ask whether this needs approval, and if so, pass it along. It is never the place where the actual chain of approval lives.

If adding a new approval amount, or a new approver, needs a code change and a deployment, the workflow system has not really solved the problem. It has only gathered all the if statements into one file instead of scattering them everywhere. The actual bar we hold ourselves to is this. A business administrator should be able to say purchase orders above ten thousand need a second approval from finance, set that through a normal setting screen, with no engineer involved, and have it work right away.

Every workflow engine ends up needing an escape hatch, an emergency override, a way to skip approval for an urgent case. We never let this become a quiet shortcut. It runs through the same log as a normal approval, clearly marked as an override, with who did it and why recorded. An override that does not show up in the record is no different from having no approval process at all.

A common bug we have seen in homegrown approval systems is letting different parts of the application decide on their own what action comes next, each based on its own copy of the record's status. We keep this decision in one place, inside the workflow engine, and every screen asks that one place what is allowed next, instead of each screen quietly building its own version of the same rules.

An approval sitting in a queue that nobody was told about sits there for a week. We always pair the workflow engine with a notice, email, a message inside the app, or a text message, sent the moment a record lands in someone's queue, along with a way to push it further up if it sits too long without anyone acting on it.


Maybeach Tech builds configurable workflow engines that let business teams change approval rules without waiting on engineering. Get in touch and let us talk about yours.

Related Post

Feature Flags in Production: Shipping Risky Changes Safely

The riskiest moment in any software change is the first time that code runs against production data,...

Plugin Architecture 101: How to Design Software That Grows Without Breaking

Every application that lives a long time faces the same question eventually. How do you keep adding ...