Message batching

Ably offers two different types of batching that have distinct use cases:

Server-side batching groups published messages into batches before sending them to subscribers. It is primarily intended for high-throughput scenarios where a large number of messages are being published to a channel in a short period of time. Each batch received by subscribers counts as a single message in terms of billing which can greatly reduce message costs in high-throughput scenarios.

Batch publishing enables clients to publish messages to multiple channels using a single request. It enables the same information to be easily distributed to multiple channels, or different information distributed to many channels, all using a single request. A similar feature is available to retrieve the presence status of multiple channels using a single request.

With server-side batching, Ably groups any messages published within a set period of time into batches, before sending them to subscribers.

It makes messages more cost efficient in high-throughput scenarios by reducing the number of messages being published, as each batch is counted as a single message. This also helps to mitigate the risk of hitting message rate limits at the same time. The interval over which batching occurs is configurable to ensure an appropriate trade off between cost efficiency and user experience, as a higher interval will increase the latency between message deliveries.

Server-side batching is effective in applications such as fan engagement platforms, where key moments in a game, such as points being scored, cause huge surges in the number of reactions and messages. It also enables a higher number of users to be present on a channel.

When configuring server-side batching, you need to configure a batching interval. This is the interval over which messages are batched into groups, in milliseconds. Messages sent to Ably during this interval are temporarily held and aggregated. Once the interval elapses, the collected messages are combined into a single batch and delivered to subscribers as one message.

Each batch can contain up to 200 messages by count or total data size. For example, if you have 210 messages, they will be split into two batches: one with 200 messages and another with 10 messages. If the combined data size of 200 messages exceeds the data limit, the excess will be allocated to a new batch as separate messages.

Use the following steps to configure server-side batching for a channel, or channel namespace:

  1. On your dashboard, select one of your apps.
  2. Go to Settings.
  3. Under channel rules, click Add new rule.
  4. Enter the channel name, or channel namespace to apply server-side batching to.
  5. Check Server-side batching enabled.
  6. Choose a batching interval over which to aggregate messages.
  7. Click Create channel rule to save.

It is possible to publish messages to multiple channels with a single request. A batch request queries an API multiple times with single HTTP request. A batch request has a single set of request details containing the request body, parameters and headers. These are converted into an array of requests to the underlying API. Each individual request to the underlying API is performed in parallel and may succeed or fail independently.

The following is an example of a batch publish request using the request() method to query the batch REST API

Select...
const ablyRest = new Ably.Rest({ key: '<loading API key, please wait>' }) const content = { 'channels': [ 'test1', 'test2' ], 'messages': { 'data': 'myData' } } const batchPublish = await ablyRest.request('post', '/messages', null, content, null); console.log('Success! status code was ' + batchPublish.statusCode)
Demo Only
Copied!

Each batch publish request can contain a single BatchSpec object, or an array of BatchSpec objects. Each BatchSpec object contains a single channel name or an array of channel names in the channels property. The messages property then contains a single message or an array of messages. Each BatchSpec will then publish each of its messages to each of its channels.

For each channel, the messages grouped into a single BatchSpec are published atomically. This means that:

  • Either they will all be successfully published or none of them will
  • The max message size limit applies to the total size of all messages in in a BatchSpec
  • Each BatchSpec will only count as a single message for the purpose of the per-channel rate limit

So if you do not need the atomicity guarantee and might be in danger of exceeding the max message size limit, you can put each message into its own BatchSpec (relative ordering will still be preserved). Conversely, if you are publishing many hundreds of small messages and are in danger of exceeding the max per-channel message rate, you group them into a fewer BatchSpecs.

The batch request as a whole is subject to the following limits:

  • Each request can only include 100 different channels. If the same channel name appears in multiple BatchSpec objects within a single request, it only counts as one channel towards the 100 channel limit per batch request.
  • Each request has a maximum body size of 2MiB.

The following is an example of a single BatchSpec object publishing a single message to 2 channels:

{ channels: ['channel1', 'channel2'], messages: {data: 'My message contents'} }
Copied!

The following is an example of an array of BatchSpec objects. The first publishes a single message to two channels and the second publishes two messages to a single channel:

[ { channels: ['channel1', 'channel2'], messages: {data: 'My message contents'} }, { channels: 'channel3', messages: [ {data: 'My message contents'}, {name: 'an event', data: 'My event message contents'}, ] } ]
Copied!

The following is an example curl request, querying the REST API directly:

curl -X POST https://rest.ably.io/messages \ -u "<loading API key, please wait>" \ -H "Content-Type: application/json" \ --data '{ "channels": [ "test1", "test2"], "messages": {"data": "My test message text" } }'
Demo Only
Copied!

Once all requests have been completed in a batch request, a batch response is returned with three possible outcomes:

Success
If all of the individual requests were successful then an array containing the response of each query is returned in request order.
Failure
If the batch request itself failed before the individual requests were made, then an error response is returned with a status code and error response body. Examples of why the batch request can fail include an authorization failure or an invalid request.
Partial success
If one or more of the individual requests failed the response body contains an error object with the error code 40020 and a status code of 400. The error body contains a batchResponse array of each individual response in request order. The batchResponse can be inspected if there is a need to know the details of each outcome. If you only need to know whether or not the batch request was completely successful then the status code is sufficient.

The examples for each possible outcome will use the following BatchSpec object as the request data:

{ channels: ['channel0', 'channel1', 'channel2'], messages: {data: 'My test message text'} }
Copied!

The following is an example of a successful batch publish response. The response body contains the messageId of each published message and the channel it was published to. The status code is 201:

[ { "channel":"channel0", "messageId":"w234r5t-fr5" }, { "channel":"channel1", "messageId":"vde4sfc0p" }, { "channel":"channel2", "messageId":"nh3exv8ih" } ]
Copied!

The following is an example of a batch publish failure response. The response body contains the details of the error, in this example that the token used for the request has expired. The status code is 401:

{ "error": { "message":"Token expired", "statusCode":401, "code":40140 } }
Copied!

The following is an example of a batch publish partial success response. The successful requests contain the messageId of each published message and the channel they were published to. The failed request contains the channel the request failed for and the details of the error, in this example that the credentials used didn’t have the capability to publish to that channel. The status code for a partial success is always 400:

{ "error": { "message": "Batched response includes errors", "statusCode":400, "code":40020 } "batchResponse": [ { "channel":"channel0", "messageId":"w234r5t-fr5" }, { "channel":"channel1", "messageId":"vde4sfc0p" }, { "channel":"channel2", "error": { "message": "Given credentials do not have the required capability", "statusCode": 401, "code": 40160 } } ] }
Copied!
Server-side batching
v2.0