A practical lesson on process-centered services, when a workflow coordinator is useful, and how to keep workflow ownership from expanding into orchestration sprawl.
A workflow-centered boundary exists primarily to coordinate a business process that crosses several domain services. Unlike a capability-oriented service, it may not own the deepest domain model or the most important authoritative data. Its main job is to track progress, coordinate steps, handle retries and compensations, and make the process observable. This pattern is valuable when the workflow itself has meaningful complexity and deserves explicit control.
The risk is obvious: if the coordinator grows too powerful, it can start absorbing domain logic from the services it coordinates. Then the workflow service stops being a process boundary and becomes a central brain for the entire system.
flowchart TD
A["Start process"] --> B["Workflow service"]
B --> C["Payment domain service"]
B --> D["Inventory domain service"]
B --> E["Notification utility"]
C --> B
D --> B
E --> B
B --> F["Process status and compensation"]
What to notice:
This pattern is useful when:
Examples include:
In these cases, keeping the process logic explicit can be healthier than scattering it across event handlers or forcing one domain service to quietly coordinate everything.
A process-centered service can reasonably own:
It should be much more careful about owning:
This distinction keeps the workflow boundary useful instead of overreaching.
The pattern becomes easier to reason about when the service records workflow state explicitly:
1{
2 "workflowId": "ord_1042",
3 "type": "place_order",
4 "currentStep": "reserve_inventory",
5 "status": "WAITING",
6 "lastSuccessfulStep": "authorize_payment",
7 "onFailure": "refund_payment"
8}
What this demonstrates:
That explicitness is one of the main reasons the pattern is valuable.
The pattern becomes unhealthy when the workflow service starts:
This is how a useful process boundary becomes a central bottleneck. The review question should always be:
“Is this logic truly about the process, or is it domain logic that belongs in another service?”
These services can still use asynchronous events, choreography, or commands. The pattern is not defined by protocol choice. It is defined by where the workflow responsibility lives. A process-centered boundary may orchestrate through commands, react to events, or combine both.
That is useful because teams sometimes confuse workflow services with purely synchronous orchestrators. The real issue is ownership of process state and process decisions, not whether the transport is HTTP or messaging.
A team creates an order workflow service that now calculates discounts, checks tax rules, determines fraud policy, and decides inventory reservation priorities because “the workflow already touches all of that.” What is the main problem?
The main problem is that the workflow service is expanding from process coordination into domain ownership. A process-centered boundary is healthy when it tracks and coordinates the workflow. It becomes unhealthy when it absorbs the business rules that should remain inside the participating domain services.