Process Manager
The full life of an EDI order lasts days, even months: PO sent, functional ack, business ack, delivery ASN, invoice, payment. The Process Manager is the stateful conductor maintaining each cycle's state and triggering actions / escalations.
Problem
An EDI exchange is never an isolated message: it is a conversation. A PO (ORDERS) expects a functional ack (CONTRL / 997), a business ack (APERAK / 855), a delivery (DESADV / 856), an invoice (INVOIC / 810), a payment (REMADV / 820). Each step has its expected timing, escalations on absence, compensation on cancellation. If each microservice only knows its step, nobody owns the end-to-end view; orders get lost silently. A component owning the full cycle state is needed.
Forces
- Long-running persistent state. The cycle lasts weeks; impossible to keep state in a process's memory.
- Asynchronous, out-of-order reception. The 855 can arrive before or after the 856 depending on partners. The manager must cope.
- Timers and escalations. If 855 has not arrived in D+7, trigger a chase; D+14, escalate to operator; D+30, open a business ticket.
- Compensation. If an order is cancelled after ASN, send a return message, credit inventory, cancel the invoice if already issued.
- Observability. At any time you must be able to list current cycles, their state, their next deadline.
Solution
EIP §312 (Hohpe & Woolf, 2003) defines the Process Manager as a central component that: (a) instantiates a state machine per business cycle (per PO, per interchange), (b) reads incoming messages and applies transitions, (c) maintains per-state timers to detect non-replies, (d) emits commands or compensation messages. State is persisted (relational DB or event store) to survive restarts. It is the centralised counterpart to distributed choreography; each has its place (see Newman's orchestration vs. choreography discussion).
ORDERS ───▶ ┌──────────────────────────┐
│ Process Manager (PO-12) │
ORDRSP ───▶ │ state: PO_CONFIRMED │
│ started: 2026-05-01 │
DESADV ───▶ │ timers: │
│ - ASN expected D+5 │
INVOIC ───▶ │ - INV expected D+30 │
│ - REMADV expected D+60│
REMADV ───▶ │ compensations: │
│ on_timeout(ASN) │
└──────────────────────────┘
│
▼
emits commands / events
on pipeline channels EDI implementation
Walmart 850 → 855 → 856 → 810 → 820 cycle (US PO). EDIFACT equivalent: ORDERS → ORDRSP → DESADV → INVOIC → REMADV.
# PO state machine (Walmart 850→855→856→810→820)
states:
- INITIATED # PO created internally
- SENT # 850 sent to supplier (ack'd 997)
- CONFIRMED # 855 received (accept, change or reject)
- SHIPPED # 856 ASN received
- INVOICED # 810 INVOIC received
- PAID # 820 remittance sent
- CLOSED # full cycle
- CANCELLED # PO cancelled en route
transitions:
INITIATED -> SENT: on send_purchase_order
SENT -> CONFIRMED: on receive 855
CONFIRMED -> SHIPPED: on receive 856
SHIPPED -> INVOICED: on receive 810
INVOICED -> PAID: on send 820
PAID -> CLOSED: automatic
(any) -> CANCELLED: on cancel command
timers:
SENT timeout 7d -> escalate(no-855)
CONFIRMED timeout 30d -> escalate(no-shipment)
SHIPPED timeout 30d -> escalate(no-invoice)
INVOICED timeout 30d -> escalate(unpaid)
Reading: each created PO instantiates a machine at status
INITIATED. On each receipt of an expected message
(855, 856, 810…), the transition fires. If a timer expires
before the transition, an escalation is emitted on a dedicated
channel (edi.escalation.po.unconfirmed for
example), which can feed a dashboard, an operator mail, or an
automatic retry.
- B2B PunchOut (cXML). The PunchOut cycle has a
manager tracking state between
PunchOutSetupRequest,PunchOutSetupResponse, basket selection,PunchOutOrderMessagereturn, conversion to a formal order. If the user abandons mid-flow, timer + cleanup. - Vendor Managed Inventory (VMI). The INVRPT (inventory) → ORDERS (generated) → DESADV (delivery) cycle is driven by a manager computing thresholds and triggering orders automatically.
- B2G CTC invoicing. A manager tracks invoice sent → tax authority ack received → buyer acceptance received → payment received, with regulatory timers (e.g. FE-B2B 24h pre-validation).
Timeouts and compensation
Three types of timer actions:
- Automatic chase. Resend an 850 if no 997 within 1h.
- Human escalation. Open an incident if no 855 within 7d (partner not responding).
- Compensation. Cancellation after ASN? Send a return message, credit inventory, cancel the invoice if already issued — a sequence of compensating actions undoing prior work.
Anti-patterns
- In-memory state. A restart loses 100% of current cycles. State always persistent.
- No timer. Without timers, a silent partner goes unnoticed until an operator stumbles on it. Always timers + alerts.
- Forgotten compensation. Cancelling an order without cancelling the already issued invoice creates serious accounting incidents. Track each reversible step.
- Too tight coupling. A process manager that calls microservices directly instead of emitting commands on the bus loses decoupling.
- Non-idempotent saga. Receiving the same 855 twice must be idempotent (transition once). Otherwise double invoicing.
Related patterns
- Routing Slip — the dynamic stateless alternative (choreography).
- Message History — history of traversed steps, fed by the manager.
- Exception flow — the escalation matrix driven by the manager.
- Aggregator — used by the manager to consolidate partials.
Sources
- Hohpe G., Woolf B. — Enterprise Integration Patterns, Process Manager (§312). enterpriseintegrationpatterns.com — Process Manager
- Garcia-Molina H., Salem K. — SAGAS, ACM SIGMOD 1987. The academic reference for the saga pattern, the formal model of compensable long-running transactions.
- Newman S. — Building Microservices, O'Reilly, 2nd ed. 2021, chapter 6. The orchestration vs. choreography debate and its modern treatment.
- X12 Implementation Guide — 850/855/856/810/820 cycle. The canonical US PO message sequence, practical reference for the state machine.