Request/reply pattern

Found an error? Have a suggestion?Edit this page on GitHub

In this tutorial, you'll learn how to implement the request/reply pattern in an AsyncAPI document using a straightforward ping-pong example.

Before we begin, it would be beneficial for you to have a basic understanding of AsyncAPI and Event-Driven Architectures (EDA). If you need a refresher, refer to our Event-Driven Architecture document.

Request/reply is a messaging pattern involving two key components: the requester, which sends a request message, and the replier, responsible for receiving this request and responding with a reply. This pattern fundamentally revolves around these two roles, requester and replier.

Static reply address

Here's how you can implement the request/reply pattern when the response address is known at the compile or design time.

A requester can be configured with the send operation, where it dispatches a message to the ping channel and anticipates receiving a response through the pong channel.

In the below example, the Operation Reply object within the pingRequest operation provides essential details, like the destination for the reply, which is the pong channel. Since the pong channel is configured with only one message, there's no need to explicitly define the reply message. Similarly, the ping channel has just one message, eliminating the need to specify the message sent in the request.

1asyncapi: 3.0.0
2info:
3  title: Ping/pong example with static reply channel
4  version: 1.0.0
5  description: Requester example that initiates the request/reply pattern on a different channel than the reply is using
6channels:
7  ping:
8    address: /ping
9    messages:
10      ping:
11        $ref: '#/components/messages/ping'
12  pong:
13    address: /pong
14    messages:
15      pong:
16        $ref: '#/components/messages/pong'
17operations:
18  pingRequest:
19    action: send
20    channel: 
21      $ref: '#/channels/ping'
22    reply:
23      channel: 
24        $ref: '#/channels/pong'
25components: 
26  messages: 
27    ping:
28      payload:
29        type: object
30        properties:
31          event:
32            type: string
33            const: ping
34    pong:
35      payload:
36        type: object
37        properties:
38          event:
39            type: string
40            const: pong

Dynamic reply address

Occasionally, the destination for a reply cannot be predetermined during the design or compile phase. In such cases, the address for the reply is dynamically determined at runtime, allowing for more flexible and adaptive communication.

In scenarios where the address or reply channel is unknown at design time, the address property can either be set to null or omitted entirely. To define the reply address dynamically, the Operation Reply Address object can be used, allowing for runtime expressions. That enables the requester to specify where the replier should send the reply, detailing the address's location and its specific position within the request.

In this situation, the location property is assigned the runtime expression $message.header#/replyTo. Such an expression indicates that the address for the reply is located within the header of the request, specifically in the replyTo field. This method dynamically determines the reply address based on the content of the request header.

1asyncapi: 3.0.0
2info:
3  title: Ping/pong example with reply specified as dynamic information provided in the runtime
4  version: 1.0.0
5  description: Example document for an application that processes ping requests and replies to the address dynamically specified by the requestor in the message header
6channels:
7  ping:
8    address: /ping
9    messages:
10      ping:
11        $ref: '#/components/messages/ping'
12  pong:
13    address: null
14    messages:
15      pong:
16        $ref: '#/components/messages/pong'
17operations:
18  pingRequest:
19    action: receive
20    channel: 
21      $ref: '#/channels/ping'
22    reply:
23      address:
24        description: Reply is sent to topic specified in 'replyTo' property in the message header
25        location: "$message.header#/replyTo"
26      channel: 
27        $ref: '#/channels/pong'
28components:
29  messages:
30    ping:
31      headers:
32        type: object
33        properties:
34          replyTo:
35            type: string
36            description: Provide path to which reply must be provided
37          requestId:
38            type: string
39            format: uuid
40            description: Provide request id that you will use to identify the reply match
41      payload:
42        type: object
43        properties:
44          event:
45            type: string
46            const: ping
47      correlationId:
48        $ref: "#/components/correlationIds/pingCorrelationId"
49    pong:
50      headers:
51        type: object
52        properties:
53          requestId:
54            type: string
55            format: uuid
56            description: Reply message must contain id of the request message
57      payload:
58        type: object
59        properties:
60          event:
61            type: string
62            const: pong
63      correlationId:
64        $ref: "#/components/correlationIds/pingCorrelationId"
65  correlationIds:
66    pingCorrelationId:
67      location: '$message.header#/requestId'

While the above examples are a simple implementation of the request/reply pattern, in a protocol-agnostic world there are many different ways to represent the request/reply pattern. All of which are supported by AsyncAPI.

Was this helpful?
Help us improve the docs by adding your contribution.
OR
Github:AsyncAPICreate Issue on GitHub