Routing Slip
The itinerary travels with the message. No central orchestrator, no stateful coordinator: the message lists the stages to traverse itself, each filter reads the next stage, forwards to the indicated channel. The purest pattern of distributed choreography.
Problem
A message must traverse a sequence of stages that depend on its type or content: an EDIFACT INVOIC from a French supplier for a German buyer goes through parse → validate → enrich GLN → translate UBL → sign XAdES → ship via PEPPOL. A US X12 810 goes through parse → validate → translate IDoc → ship to ERP. If each stage must know "where to send next" based on type, the code becomes a spaghetti graph. Coding a centralised Process Manager for each variation creates too much coupling. An approach where the itinerary is given upfront and executed by the stages is needed.
Forces
- Stateless per stage. Each filter reads the slip, does its work, passes the message to the next stage. No persistent state.
- Dynamic itinerary. The slip is built when the message arrives; two similar messages can take different routes.
- No single point of orchestration. The crash of a central coordinator does not freeze the system.
- Degraded observability. Without a coordinator, nobody knows where a message is at time t — must be complemented by a Message History.
Solution
EIP §301 (Hohpe & Woolf, 2003) defines the Routing Slip as a message header carrying an ordered list of stages to traverse. On arrival, an initial dispatcher computes the slip by type and content, and attaches it to the message. Each handler component: (a) reads the first slip step, (b) does its work, (c) pops the step from the slip, (d) sends the message on the channel matching the next step. When the slip is empty, the message has reached its final destination.
The message carries its own itinerary:
{ payload, slip: [step1, step2, step3, step4] }
│
▼
┌─────────┐ pop step1
│ step1 │ ──▶ { payload', slip: [step2, step3, step4] }
└─────────┘
│
▼
┌─────────┐ pop step2
│ step2 │ ──▶ { payload'', slip: [step3, step4] }
└─────────┘
│
▼
(etc.) EDI implementation
The canonical EDI example: cXML PunchOut. When
a buyer launches a PunchOut from its ERP to a supplier's
catalogue, it sends a PunchOutSetupRequest carrying
its return URL embedded — a one-step slip: "when you finish
cataloguing, send me back to this URL with the constructed
basket". The supplier has no prior knowledge of the buyer;
everything is in the message.
<?xml version="1.0"?>
<cXML payloadID="2026-05-14T12:00:00@buyer.example.com"
timestamp="2026-05-14T12:00:00-00:00">
<Header>
<From><Credential domain="NetworkID"><Identity>BUYER</Identity></Credential></From>
<To><Credential domain="NetworkID"><Identity>SUPPLIER</Identity></Credential></To>
<Sender><Credential domain="NetworkID"><Identity>BUYER</Identity></Credential>
<UserAgent>Ediverse Punchout/1.0</UserAgent>
</Sender>
</Header>
<Request>
<PunchOutSetupRequest operation="create">
<BuyerCookie>SESSION-9f2b1a73</BuyerCookie>
<Extrinsic name="UserEmail">jane@buyer.example.com</Extrinsic>
<BrowserFormPost>
<!-- THE routing slip: where the supplier will return the user -->
<URL>https://buyer.example.com/punchout/return?session=SESSION-9f2b1a73</URL>
</BrowserFormPost>
</PunchOutSetupRequest>
</Request>
</cXML>
Reading: the <BrowserFormPost><URL>
field is the cXML routing slip. The supplier does not store
where to return the user; it reads this URL from the message.
Once the basket is built on supplier side, it generates a
PunchOutOrderMessage POSTed to this URL; the user
returns to the buyer site with a basket ready to convert to a
formal order.
Other EDI uses:
- Contextual pipeline slip. A message received
via AS2 from partner X is tagged with
routing-slip = [parse-x12-850, enrich-gln, translate-idoc850, ship-sap]; the same partner in UBL/AS4 mode gets[parse-ubl, validate-peppol, translate-idoc850, ship-sap]. No central component arbitrates. - Extended SBDH. A Standard Business Document Header can carry BusinessScope extensions playing the role of a routing slip: list of next recipients after certain processing (in multi-corner PEPPOL mode).
- Pipeline as data. To ease integration testing and replay, some hubs put the whole route in the message on arrival — testable as a unit flow.
Routing slip vs. process manager
Two dual approaches to orchestrate a sequence:
- Process Manager — centralised state, explicit state machine, driven escalations, native observability, but coupling to a central component and persistent state.
- Routing Slip — state in the message, no coordinator, flat scalability, but fragile observability (needs Message History) and less natural compensation.
Choice by profile: short cycles (< a few minutes), many variations per type, weak real-time audit need → routing slip. Long cycles (days/months), timers and escalations, operator dashboards needed → process manager.
Anti-patterns
- Silent slip. A message without slip landing on a filter: no way to decide what's next. Always attach at entry point, not later.
- Unversioned slip. Stage names evolve over time; a slip generated 6 months ago may point to a stage that no longer exists. Version it.
- Stage modifying the future. A stage adding steps to the slip turns the pattern into an unprovable dynamic routing table. Keep the slip immutable except in explicitly modelled cases.
- No Message History. Without trace of what happened, debugging a broken slip is a nightmare. Couple systematically.
Related patterns
- Process Manager — the centralised stateful alternative.
- Message History — almost mandatory companion for observability.
- Pipes and Filters — each slip step is a filter.
- Content-Based Router — a router inspecting the slip is essentially a routing slip executor.
Sources
- Hohpe G., Woolf B. — Enterprise Integration Patterns, Routing Slip (§301). enterpriseintegrationpatterns.com — Routing Slip
- cXML Reference Guide, Ariba (SAP). Formal documentation of PunchOutSetupRequest / PunchOutOrderMessage, canonical example of an embedded slip. cxml.org
- Apache Camel — Routing Slip EIP. Reference open-source implementation. camel.apache.org — Routing Slip
- UN/CEFACT — SBDH. The Standard Business Document Header allows BusinessScope extensions that can encode a multi-target slip.