Lecture 8: Enterprise Integration Patterns
Understand the Enterprise Integration Patterns (EIP) catalogue: message channels, routing patterns, transformation patterns, and process coordination patterns including Saga and CQRS ā with examples and when to apply each.
Enterprise Integration Patterns (EIP) are a catalogue of proven solutions to recurring integration problems. Originally documented by Gregor Hohpe and Bobby Woolf in their 2003 book of the same name, the 65 patterns in the catalogue describe every fundamental mechanism needed to build messaging-based integration systems. This lecture covers the most important patterns and ā critically ā when to use each.
What Are Enterprise Integration Patterns?
Patterns are reusable solutions to known problems. In software architecture, a pattern is not code you copy ā it is a description of a solution structure that you adapt to your context.
EIPs describe solutions to problems like:
- How do I route a message to the right recipient based on its content?
- How do I split a batch message into individual messages?
- How do I collect responses from multiple systems and combine them?
- How do I coordinate a multi-step business process without distributed transactions?
Why learn patterns instead of just technology? Because the patterns are technology-independent. Whether you use Apache Camel, MuleSoft, Azure Logic Apps, or Node.js ā the underlying patterns are the same. Knowing the pattern name also enables precise communication with colleagues and documentation.
Pattern Category 1: Message Channels
A Message Channel is the pipe through which messages flow. Different channel types serve different purposes.
Point-to-Point Channel
One message, one receiver. The channel guarantees that each message is consumed by exactly one consumer.
Producer āāāŗ [Queue] āāāŗ Consumer
(one of N consumers gets each message)Use: task queues, work distribution, any case where each message should be processed once.
Publish-Subscribe Channel
One message, multiple receivers. Each subscriber gets its own copy.
Producer āāāŗ [Topic] āāāŗ Subscriber A
āāāŗ Subscriber B
āāāŗ Subscriber CUse: event notifications, broadcasting state changes, feeding multiple downstream systems.
Dead Letter Channel
Where failed messages go after exhausting retries. Every production channel should have one.
Queue āāāŗ Consumer (fails repeatedly)
ā (after max retries)
[Dead Letter Queue] āāāŗ Operations team alertDatatype Channel
A channel dedicated to a specific message type. Consumers subscribe to channels for the message types they handle.
[order.placed channel] āāāŗ Inventory, Billing
[customer.updated channel] āāāŗ CRM Sync, Notification
[payment.failed channel] āāāŗ Finance, Customer SupportPattern Category 2: Message Construction
Command Message
A message that tells the receiver to perform an action. The sender expects the action to happen.
{ "type": "SendEmail", "to": "user@example.com", "subject": "Order confirmed", "body": "..." }Event Message
A message that announces something that happened. The sender does not know or care what consumers do with it.
{ "type": "OrderPlaced", "orderId": "ORD-1234", "placedAt": "2026-04-18T10:30:00Z" }Document Message
A message that transfers a data document ā no command, no event. The receiver stores or processes the document.
{ "type": "InvoiceDocument", "invoice": { "invoiceId": "INV-5678", ... } }Request-Reply
A command message paired with a reply address. The sender specifies where to send the result:
{
"type": "ValidateAddress",
"address": { ... },
"replyTo": "validation.results.queue",
"correlationId": "abc-123"
}Pattern Category 3: Message Routing
Content-Based Router
Routes a message to different channels based on its content.
incoming message
āāā if region = "EU" ā EU-orders queue
āāā if region = "US" ā US-orders queue
āāā if region = "APAC" ā APAC-orders queueUse case: route orders to regional fulfilment centres; route support tickets by product category.
Implementation consideration: keep routing logic simple and fast. Complex routing rules that require database lookups slow the entire pipeline.
Message Filter
Passes only messages that meet a condition; discards the rest.
all order events ā [Filter: amount > 10000] ā high-value-orders queueUse case: a downstream system only cares about a subset of events from a busy topic.
Splitter
Takes one message containing multiple items and splits it into individual messages ā one per item.
batch of 500 customer records
ā [Splitter]
ā customer record 1
ā customer record 2
ā ...
ā customer record 500Use case: process a batch file one record at a time; fan out an order's line items to inventory checks.
Aggregator
Collects related messages and combines them once a completion condition is met.
items for order 1234:
item A arrives ā buffer
item B arrives ā buffer
item C arrives ā buffer
(all 3 items received) ā [Aggregator] ā complete order 1234Completion conditions:
- All expected messages received (when the count is known)
- Timeout reached (emit whatever has been collected)
- A "complete" signal message arrives
Use case: collect all line items before sending the complete order to the warehouse; wait for all sub-task responses before proceeding.
Resequencer
Collects out-of-order messages and reorders them before delivering to the consumer.
arrives: msg-3, msg-1, msg-4, msg-2
ā [Resequencer]
ā delivers: msg-1, msg-2, msg-3, msg-4Use case: ordered processing when the transport does not guarantee order (e.g., multiple parallel consumers, then ordered delivery to a legacy system).
Scatter-Gather
Sends the same request to multiple receivers simultaneously, collects their responses, and aggregates into a single reply.
price-check request
ā [Scatter] ā Supplier A ā price response A
ā Supplier B ā price response B
ā Supplier C ā price response C
ā [Gather] ā lowest price resultUse case: price comparison, parallel data enrichment, multi-system validation.
Pattern Category 4: Message Transformation
Message Translator
Converts a message from one format or schema to another.
Source format (SAP IDoc) ā [Translator] ā Target format (JSON REST payload)This is one of the most common integration operations. Every system has its own data model; the translator maps between them.
Envelope Wrapper / Unwrapper
Wraps a message in an envelope with metadata for routing and tracking, then strips the envelope at the destination.
payload
ā [Wrapper]: add correlation-id, timestamp, source, target
ā route through integration layer
ā [Unwrapper]: strip envelope, deliver payload to targetClaim Check
When a message payload is too large to pass through the broker efficiently, store the payload in external storage and send a reference (the "claim check") instead.
large payload (10MB order document)
ā [Store in blob storage]
ā send message: { "claimCheck": "storage://orders/ORD-1234.json" }
Consumer receives message
ā fetches full payload from storage using claim checkUse case: large documents, binary files, images in integration flows.
Normaliser
Routes messages of different formats to appropriate translators so all consumers receive a consistent format.
SAP IDoc order āāāŗ
REST JSON order āāāŗ [Normaliser] ā canonical order format
CSV order batch āāāŗPattern Category 5: System Management
Control Bus
A separate channel for control messages ā start, stop, reconfigure, health check ā distinct from the data channel.
Data channel: actual business messages
Control channel: health checks, monitoring commands, configuration updatesMessage History
Each component adds its identity to the message header as it passes through. Enables tracing the full route a message took.
message.history: [order-service, integration-layer, transformation-service, warehouse-api]Message Store
Store a copy of every message that flows through the integration layer. Enables replay, debugging, and audit.
Saga Pattern
The Saga pattern manages distributed transactions across multiple services when there is no distributed lock available.
A saga is a sequence of local transactions. Each transaction updates one service's data and publishes an event triggering the next transaction. If any step fails, compensating transactions undo the previous steps.
Example: Order Fulfilment Saga
Step 1: Reserve inventory ā success: publish InventoryReserved
Step 2: Charge payment ā success: publish PaymentCharged
Step 3: Book shipment ā success: publish ShipmentBooked
If Step 3 fails:
Compensate Step 2: Refund payment
Compensate Step 1: Release inventory reservationTwo Saga Coordination Styles
Choreography: each service listens for events and decides its next action. No central coordinator.
OrderPlaced ā [Inventory Service] ā InventoryReserved ā [Payment Service] ā ...Orchestration: a central saga orchestrator sends commands to each service and waits for results.
Orchestrator ā command: ReserveInventory ā [Inventory] ā InventoryReserved
Orchestrator ā command: ChargePayment ā [Payment] ā PaymentChargedWhen to use choreography: loosely coupled services where adding steps should not require changing existing services.
When to use orchestration: when the workflow must be visible, traceable, and centrally managed (financial transactions, compliance-critical workflows).
CQRS (Command Query Responsibility Segregation)
CQRS separates the write model (commands that change state) from the read model (queries that return data).
Write side:
Command ā validate ā update write model ā emit event
Read side:
Event ā update read model (optimised for query)
Query ā read model returns dataWhy separate them?
- Write models enforce business rules and ensure consistency
- Read models are optimised for query patterns ā denormalised, pre-joined, cached
- Read models can be rebuilt from events at any time if they become inconsistent or need a new shape
- Read models can be scaled independently from write models
CQRS in integration: when a system receives events from an integration, it builds a local read model from those events rather than querying the source system on demand.
Idempotent Receiver
Every message consumer must be designed as an idempotent receiver ā processing the same message twice must produce the same result as processing it once.
Why: at-least-once delivery means duplicates happen. Network timeouts can cause the sender to retry a message the receiver already processed.
Implementation:
On receive message:
1. Check if message ID exists in processed-messages table
2. If yes: return success (already processed, no-op)
3. If no: process message, then insert message ID into tableThe processed-messages table needs a TTL ā old entries can be deleted after the retry window closes (e.g., 24 hours).
Pattern Reference Summary
| Pattern | Problem it solves | |---------|-------------------| | Point-to-Point Channel | Route message to exactly one consumer | | Pub-Sub Channel | Deliver message to all interested consumers | | Dead Letter Channel | Store unprocessable messages for investigation | | Content-Based Router | Route based on message content | | Message Filter | Discard messages that don't match a condition | | Splitter | Break batch into individual messages | | Aggregator | Collect related messages into one | | Scatter-Gather | Parallel multi-target request with aggregated response | | Message Translator | Convert between data formats | | Claim Check | Handle large payloads by reference | | Saga | Coordinate distributed transactions with compensation | | CQRS | Separate write model from read model | | Idempotent Receiver | Safe handling of duplicate message delivery |
Lecture 8 Summary
- Enterprise Integration Patterns are a technology-independent catalogue of solutions to recurring messaging and integration problems.
- Channel patterns define the communication topology: point-to-point (one consumer) vs. pub-sub (all subscribers).
- Routing patterns ā content-based router, filter, splitter, aggregator, scatter-gather ā are the building blocks of any complex integration flow.
- Transformation patterns ā translator, normaliser, claim check ā handle the challenge that every system speaks a different data language.
- The Saga pattern replaces distributed transactions with a sequence of local transactions and compensating actions.
- CQRS separates the write model (consistency, business rules) from the read model (optimised for queries, independently scalable).
- Every consumer must be an idempotent receiver ā duplicates are a normal condition in at-least-once delivery systems.
Next: Deep Dive ā Messaging Systems
Enjoyed this article?
Explore the Integration Engineering learning path for more.
Found this helpful?
Leave a comment
Have a question, correction, or just found this helpful? Leave a note below.