Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
89b18f6
Can I delete messages which have been persisted through the history API?
franrob-projects Sep 23, 2025
8ba7875
Is it possible to check if a specific message has been delivered to a…
franrob-projects Sep 23, 2025
2102407
Reliable message ordering for connected clients
franrob-projects Sep 23, 2025
6383ae0
Am I able to check who has read published messages?
franrob-projects Sep 23, 2025
10e5e3c
Client-specified message ID restrictions for multiple messages publis…
franrob-projects Sep 23, 2025
a74ea8e
I'm not receiving messages, how do I debug that?
franrob-projects Sep 23, 2025
6760f8b
Can I see messages sent by Channel or ClientID?
franrob-projects Sep 23, 2025
86cf208
How does Ably count and bill for messages?
franrob-projects Sep 23, 2025
bea9830
How can I reduce my message count?
franrob-projects Sep 23, 2025
da77b58
Is there a maximum number of channels per connection?
franrob-projects Sep 23, 2025
fab7f54
Can I attach and subscribe to channels using wildcards?
franrob-projects Sep 23, 2025
1143cba
How can I implement presence subscriptions efficiently, in terms of l…
franrob-projects Sep 23, 2025
981c2ca
Can I use webhooks or other rules to maintain an external copy of the…
franrob-projects Sep 23, 2025
bea5c08
Why don't presence members leave as soon as I close a tab?
franrob-projects Sep 23, 2025
2a5ca91
I don't understand why I see so many presence messages in my stats.
franrob-projects Sep 24, 2025
ec7d369
Why do you have a limit on the number of members present on a channel?
franrob-projects Sep 24, 2025
be2a852
What does it mean if I see 'Channel Region Inactive' in my logs on th…
franrob-projects Sep 24, 2025
585317d
How to limit user numbers in channels
franrob-projects Sep 24, 2025
40bfd1e
Can I make a History Call to several Channels Simultaneously?
franrob-projects Sep 24, 2025
9b15e8f
Common misconceptions around Ably History
franrob-projects Sep 24, 2025
7c74b55
How synchronized / up to date is channel history betweendatacenters /…
franrob-projects Sep 24, 2025
3fe0fd7
Merge branch 'main' into EDU-2075-remove-channels-fags
franrob-projects Sep 24, 2025
2da0d6a
Tidy up commit
franrob-projects Sep 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/pages/docs/auth/capabilities.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,18 @@ The following capability operations are available for API keys and issued tokens

Although most capabilities need to be enabled for the resource you're using them with, there are exceptions. The `stats` permission only does something when attached to the wildcard resource `'*'`, or a resource that contains that as a subset, such as `'[*]*'`, since stats are app-wide.

## Channel access control <a id="access-control"/>

Ably does not provide numeric limits on channel access. Control channel access using token authentication and capabilities.

Channel access is controlled through:

* [Token authentication](/docs/auth/token) to restrict access by issuing tokens with specific capabilities to authorized users
* Specific `clientId` values in tokens to ensure only certain users can access particular channels
* Granting or restricting specific operations (`subscribe`, `publish`, `presence`) on channels through capability configurations

For private messaging or group chats, design channel naming strategies and use token authentication to ensure users receive tokens with access only to relevant channels.

The `channel-metadata` permission works both ways. When associated with a specific channel or set of channels it allows you to [query the metadata of a channel](/docs/metadata-stats/metadata/rest) to request its status. When associated with the wildcard resource `'*'` it takes on an additional meaning: as well as allowing channel status requests for all channels, it also allows you to [enumerate all active channels](/docs/metadata-stats/metadata/rest#enumerate).

<Aside data-type='note'>
Expand Down
28 changes: 24 additions & 4 deletions src/pages/docs/channels/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,26 @@ With [basic pub-sub](/docs/pub-sub) you create a channel, subscribe to it, and t

To get started with implementing any feature, a client must first create or retrieve an instance of a channel. A channel is created, or an existing channel is retrieved from the `Channels` collection. You can only connect to one channel in a single operation.

### Wildcard channel subscriptions

Wildcard channel subscriptions are not supported when attaching to channels. For example, the following operations are not possible:

```javascript
// This will NOT work - wildcard subscriptions are not supported
var channel = ably.channels.get('foo:*');
channel.attach(); // Attempting to attach to all channels matching foo:* will fail
```

Wildcard subscriptions are not supported for technical and architectural reasons:

* Scalability limitations: attaching to an unbounded number of channels in a single operation does not scale for client devices or servers
* Distributed architecture: Channels are dynamically distributed across available resources and move frequently. Each channel is autonomous to ensure the system remains reliable without a single point of failure. Supporting wildcard subscriptions would require maintaining connections to every server that could possibly run a matching channel
* Data delivery guarantees: Wildcard subscriptions make it impossible to offer the data delivery guarantees and quality of service that Ably provides:
* No deterministic way to know which channels a client is actually attached to at any point in time
* If a client device becomes overloaded or exceeds rate limits, servers would need to selectively drop messages across random channels, making it unclear which messages were missed

Ably connections are multiplexed, so you can attach and detach from channels dynamically over the same connection. This enables you to implement wildcard-like functionality by programmatically managing channel subscriptions as needed.

Channels are identified by their unique name. The following restrictions apply to when naming a channel:

* Channel names are case sensitive
Expand All @@ -61,11 +81,11 @@ Channel channel = realtime.channels.get("{{RANDOM_CHANNEL_NAME}}");
```

```realtime_csharp
IRealtimeChannel channel = realtime.Channels.Get("{{RANDOM_CHANNEL_NAME}}"); realtime
IRealtimeChannel channel = realtime.Channels.Get("{{RANDOM_CHANNEL_NAME}}");
```

```realtime_ruby
channel = realtime.channels.get('{{RANDOM_CHANNEL_NAME}}') realtime
channel = realtime.channels.get('{{RANDOM_CHANNEL_NAME}}')
```

```realtime_python
Expand Down Expand Up @@ -101,11 +121,11 @@ Channel channel = rest.channels.get("{{RANDOM_CHANNEL_NAME}}");
```

```rest_csharp
Channel channel = rest.Channels.Get("{{RANDOM_CHANNEL_NAME}}"); rest
Channel channel = rest.Channels.Get("{{RANDOM_CHANNEL_NAME}}");
```

```rest_ruby
channel = rest.channels.get('{{RANDOM_CHANNEL_NAME}}') rest
channel = rest.channels.get('{{RANDOM_CHANNEL_NAME}}')
```

```rest_python
Expand Down
34 changes: 34 additions & 0 deletions src/pages/docs/messages/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,40 @@ The following are the properties of a message:
| **extras** | A JSON object of arbitrary key-value pairs that may contain metadata, and/or ancillary payloads. Valid payloads include those related to [Push Notifications](/docs/push), [deltas](/docs/channels/options/deltas) and headers |
| **encoding** | This is typically empty, as all messages received from Ably are automatically decoded client-side using this value. However, if the message encoding cannot be processed, this attribute contains the remaining transformations not applied to the data payload |

## Message delivery tracking <a id="delivery-tracking"/>

Ensure a message was successfully published by checking the [history](/docs/storage-history/history) of the channel for your message. It is only possible to check if a device has received a message from the device itself.

Ably does not store per-message delivery logs, nor logs of who is subscribed to a channel at any point in time. This means it is not possible to check which users have received messages retroactively.

### Read receipts and acknowledgments <a id="read-receipts"/>

Ably does not natively support read receipts or message acknowledgments to track who has read published messages. This aligns with the fundamental pub-sub pattern where publishers are decoupled from subscribers.

Since Ably doesn't control how many clients are expected on a channel, it is architecturally difficult to determine who has read or received a message. You can implement a custom read receipt system by having subscribers publish acknowledgment messages when they consider a message received or read:

```javascript
// Subscriber acknowledges reading a message
channel.subscribe('content', (message) => {
// Process the message
console.log('Received:', message.data);

// Send read receipt
channel.publish('read-receipt', {
messageId: message.id,
readBy: clientId,
readAt: Date.now()
});
});

// Publisher listens for read receipts
channel.subscribe('read-receipt', (receipt) => {
console.log(`Message ${receipt.data.messageId} read by ${receipt.data.readBy}`);
});
```

This approach requires application-level implementation and careful consideration of scalability in high-traffic scenarios.

## Message conflation <a id="conflation"/>

Use message conflation to ensure that clients only ever receive the most up-to-date message, by removing redundant and outdated messages. Message conflation will aggregate published messages for a set period of time and evaluate all messages against a [conflation key](#routing). All but the latest message for each conflation key value will be discarded, and the resulting message, or messages, will be delivered to subscribers as a single batch once the period of time elapses.
Expand Down
6 changes: 6 additions & 0 deletions src/pages/docs/metadata-stats/metadata/subscribe.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ The following events are published to `[meta]channel.lifecycle`:

The `data` property of all events is a [`ChannelDetails`](/docs/api/realtime-sdk/channel-metadata#channel-details) object. The [`ChannelDetails.ChannelStatus`](/docs/api/realtime-sdk/channel-metadata#channel-status) which includes [occupancy](/docs/presence-occupancy/occupancy) details varies depending on the event. If the event is specific to a region, such as `channel.region.active` then the occupancy metrics will only be for that region. For other events such as `channel.opened`, the occupancy metrics will be global.

### Understanding regional channel activity

Seeing `channel.region.inactive` events in your [Dev Console](/docs/platform/account/app/console) logs is normal behavior. Channels become active in different regions globally according to where clients are located and Ably's internal placement rules.

A `channel.region.inactive` event indicates that a channel no longer has any clients in that specific region, or that the channel is shutting down altogether. This is part of Ably's normal operation to efficiently manage resources across its global infrastructure.

The following is an example of subscribing to all `[meta]channel.lifecycle` events:

<Code>
Expand Down
12 changes: 12 additions & 0 deletions src/pages/docs/platform/account/app/console.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ The following explains the realtime monitoring tools in the application-wide eve
| **Average application-wide events per second (p/s)** | This metric shows the average number of events occurring per second across your application. For example, if the current rate is 0, no active events are being processed. |
| **Event log table** | The event log table displays a record of events related to the current client's connection status. This table can be used to debug potential issues in your application. |

## Message auditing and logging <a id="message-auditing"/>

The dev console displays messages in realtime for debugging and testing purposes, but does not provide persistent message auditing or logging capabilities. Ably does not currently offer native functionality to view historical messages filtered by specific channels or client IDs for auditing purposes.

If you need to audit or log messages by channel or client ID, implement this functionality on the application side. Consider using:

- [Webhooks](/docs/platform/integrations/webhooks) to send message events to your logging system
- [Message queues](/docs/platform/integrations/queues) to process and store message data
- Client-side logging in your application code

For native message auditing features, [contact support](mailto:support@ably.com) to discuss requirements.

## Channels

The following is a step-by-step instructions for connecting to a channel, publishing messages.
Expand Down
23 changes: 23 additions & 0 deletions src/pages/docs/platform/architecture/message-ordering.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,26 @@ When building globally distributed applications, developers should understand th
The dual ordering system allows applications to choose the appropriate consistency model for their needs. For highly interactive applications where responsiveness is critical, realtime order minimizes latency. For applications that require a consistent historical record, the canonical global order provides a stable view that all components can agree on.

To support both ordering systems efficiently, messages are stored with metadata that tracks their position in multiple sequences. This allows the platform to rapidly retrieve messages in either realtime or canonical global order as needed for different API operations or connection recovery scenarios.

## Message ordering guarantees <a id="ordering-guarantees"/>

Ably delivers messages to persistently connected subscribers on a channel in the order they were published when using the Realtime libraries. Each message sent on a realtime connection has a unique incrementing serial number, enabling this ordering guarantee.

If you publish messages using a Realtime client library, subscribers on that channel anywhere in the world will receive those messages in the same order they were originally published.

### REST publishing considerations <a id="rest-considerations"/>

When publishing using REST client libraries, Ably still guarantees that the order messages are received will be honoured for all subscribers. However, if you are sending messages at a high rate with separate REST requests, it is possible that a later HTTP request may reach Ably before a previous request due to variable network factors outside of Ably's control.

If ordering is important when using REST, consider these approaches:
- Rate limit your HTTP requests
- [Batch messages](/docs/messages/batch) together in a single request
- Use Realtime client libraries to publish messages instead

### Connection recovery edge cases <a id="recovery-edge-cases"/>

Ably supports connection state recovery, so even if a connection is lost and re-established, messages replayed when reconnected will be in sequential order.

However, there is a rare situation where ordering may not be maintained: if a client is disconnected and the server maintaining that client's connection state is terminated or recycled during connection state recovery, messages may potentially be replayed out of order. This behavior is by design to ensure that the backlog of messages held in the connection state do not prevent the new server from sending realtime messages to clients.

If message ordering is required in all cases, consider catching the connection disconnected event and either re-establishing a new connection or manually re-ordering incoming messages following disconnection.
20 changes: 18 additions & 2 deletions src/pages/docs/platform/errors/codes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -672,9 +672,25 @@ Note: In older versions of the ably-java SDK, this error was incorrectly assigne

## 90010: Maximum number of channels per connection exceeded <a id="90010"/>

This error occurs when a Realtime client [attaches](/docs/channels/states#attach) to more channels than the account allows on a single connection. This happens when channels are attached but never explicitly detached, causing the limit to be reached.
This error occurs when a Realtime client [attaches](/docs/channels/states#attach) to more channels than the account allows on a single connection. The error message appears as:

**Resolution:** Review your channel [limits](/docs/platform/pricing/limits#channel) and ensure that channels are explicitly detached when no longer needed.
```
[ErrorInfo: Maximum number of channels per connection MAXCHANNELS exceeded; statusCode=90010; code=400]
```

Where `MAXCHANNELS` is your account's maximum number of channels per connection limit.

This limit exists to ensure that connection state and the load imposed for connection resumption don't become unbounded. With more channels on a single connection, the size of the connection state grows, as does the work required to resume or recover the connection if dropped.

**Resolution:** Use one or more of the following strategies to avoid reaching this limit:

* For SDKs that support transient publishes (ably-js >= 1.0.9, ably-ruby >= 1.1, ably-java >= 1.0.10), call `channel.publish()` without attaching to avoid the channel limit altogether. This is suitable when only publishing messages, not receiving them.
* Call [`channel.detach()`](/docs/channels/states#detach) once finished with a channel to free up the connection slot. This is suitable when using channels for short periods of time.
* REST publishes are stateless and don't attach to channels. This is suitable when publish rates are low or transient publishes aren't supported.
* Distribute channels across multiple realtime connections. This is suitable when hundreds of simultaneous channel attachments are needed.
* Contact Ably to configure higher limits for applications requiring very high channel counts per connection.

Remember that subscribing to a channel (and publishing in SDKs without transient publishing support) will implicitly attach to it, so detaching after these operations helps keep your channel count manageable.

## 90021: Max channel creation rate exceeded <a id="90021"/>

Expand Down
Loading