Skip to main content

Request-Reply

Request-Reply pairs a request message with its response over messaging by using a reply-to channel and a correlation identifier, giving RPC-style two-way exchange while keeping the decoupling of messaging. It requires timeout handling because a reply may never arrive.

Type
Messaging
When to Use
Need Response, Async RPC Over Messaging, Decoupled Two Way Exchange

The Request-Reply pattern enables two-way conversation over a messaging system that is fundamentally one-way. A requestor sends a request message on one channel and expects a reply message on another. It brings RPC-style interaction to asynchronous messaging while preserving decoupling.

The problem it solves is the need for a response. Many interactions require an answer: a query, a command that returns a result, a validation. Plain messaging is fire-and-forget, so request-reply layers a response mechanism on top, pairing each reply with its originating request.

How It Works

The requestor sends a request on a request channel and specifies, usually via a reply-to header, where the response should go. The replier processes the request and sends a reply on that return channel. To match a reply with the right request — essential when many requests are in flight — each request carries a correlation identifier that the replier copies onto the reply.

The reply channel may be shared (all replies come back on one channel, sorted out by correlation id) or private (a temporary per-requestor channel). The requestor can wait synchronously (blocking until the reply arrives or a timeout fires) or handle the reply asynchronously via a callback.

request{ correlationId: X, replyTo: Q } --> replier
replier --> reply{ correlationId: X } on Q --> requestor

When to Use It

Use it when a sender needs a result but you still want the decoupling, buffering, and resilience of messaging — for example asynchronous RPC, service queries over a bus, or command messages that report outcomes. It is the messaging analogue of a synchronous call.

Avoid it when fire-and-forget suffices, and reconsider it when ultra-low-latency synchronous calls are needed, where direct RPC or HTTP may be simpler.

Trade-offs

Request-reply adds correlation handling, reply-channel management, and timeout logic, because the reply may never come. Holding requestor state while awaiting a reply complicates scaling, especially for synchronous waits. It reintroduces a degree of temporal coupling. The benefit is two-way semantics with the reliability and decoupling of messaging.

Related Patterns

It depends on the Correlation Identifier to match replies to requests. It uses Message Channels (often point-to-point) for both directions. When fanning out and collecting many replies, it combines with a Recipient List and an Aggregator (scatter-gather).

Example

A service publishes a PriceQuoteRequest to a request queue with correlationId=abc and replyTo=quotes.reply.123. The pricing service computes the quote and sends a PriceQuoteResponse with correlationId=abc to that reply queue, where the original requestor matches it to the pending request and resolves the call.