Skip to content

Commit 80a1be0

Browse files
mattheworiordanclaude
authored andcommitted
docs: add channel-level echo param documentation
New echo.mdx page covering why echo is the default, per-channel suppression use cases, multi-language code examples, and interaction with connection-level echoMessages. Updates channel options overview, API types reference, advanced pub-sub cross-reference, and sidebar nav. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 79989dd commit 80a1be0

File tree

5 files changed

+152
-2
lines changed

5 files changed

+152
-2
lines changed

src/data/nav/pubsub.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,10 @@ export default {
184184
name: 'Deltas',
185185
link: '/docs/channels/options/deltas',
186186
},
187+
{
188+
name: 'Echo',
189+
link: '/docs/channels/options/echo',
190+
},
187191
{
188192
name: 'Encryption',
189193
link: '/docs/channels/options/encryption',

src/pages/docs/api/realtime-sdk/types.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2199,7 +2199,7 @@ Channel options are used for <If lang="javascript,nodejs,java,swift,objc,csharp"
21992199

22002200
| Property | Description | Type |
22012201
|----------|-------------|------|
2202-
| <If lang="javascript,nodejs,java,swift,objc">params</If><If lang="csharp">Params</If> | Optional [parameters](/docs/channels/options) which specify behaviour of the channel. | <If lang="java">`Map<String, String>`</If><If lang="javascript,nodejs,objc,csharp,swift">`JSON Object`</If> |
2202+
| <If lang="javascript,nodejs,java,swift,objc">params</If><If lang="csharp">Params</If> | Optional [parameters](/docs/channels/options) which specify behaviour of the channel. Supported params include [`rewind`](/docs/channels/options/rewind), [`delta`](/docs/channels/options/deltas), [`occupancy`](/docs/presence-occupancy/occupancy), and [`echo`](/docs/channels/options/echo). | <If lang="java">`Map<String, String>`</If><If lang="javascript,nodejs,objc,csharp,swift">`JSON Object`</If> |
22032203
| <If lang="javascript,nodejs,java,swift,objc">cipher</If><If lang="csharp">CipherParams</If> | Requests encryption for this channel when not null, and specifies encryption-related parameters (such as algorithm, chaining mode, key length and key). See [an example](/docs/api/realtime-sdk/encryption#getting-started) | [`CipherParams`](/docs/api/realtime-sdk/encryption#cipher-params)<If lang="javascript,nodejs"> or an options object containing at a minimum a `key`</If><If lang="java"> or a `Param[]` list containing at a minimum a `key`</If><If lang="ruby"> or an options hash containing at a minimum a `key`</If> |
22042204

22052205
</If>
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
---
2+
title: Echo
3+
meta_description: "The echo channel option enables per-channel control over whether a client receives its own published messages."
4+
---
5+
6+
By default, clients receive their own messages when subscribed to a channel they publish on. This is useful in many applications because it means every subscriber, including the publisher, renders state from the same stream of messages. For example, in a chat application or collaborative editor, a client can publish a message and then update its UI only when that message arrives back on the channel, guaranteeing that all participants see the same ordering and state.
7+
8+
However, this is not always desirable. A client streaming pricing updates, publishing telemetry data, or sending tokens via [AI Transport](/docs/ai-transport) does not need to hear its own messages echoed back. Suppressing echo on these channels reduces unnecessary bandwidth and message processing.
9+
10+
Set `echo` to `false` in the channel `params` to suppress echo on a per-channel basis. As `echo` only applies to channel subscriptions, it is only available when using the realtime interface of an Ably SDK, or when using [SSE](/docs/protocols/sse) or [MQTT](/docs/protocols/mqtt).
11+
12+
## When to suppress echo <a id="when"/>
13+
14+
Suppressing echo per-channel is useful when a client publishes and subscribes on the same channel but does not need its own messages back:
15+
16+
- **Streaming data**: A client publishing live pricing updates, sensor readings, or telemetry to a channel does not need those messages echoed back. Suppressing echo avoids redundant processing and reduces bandwidth.
17+
- **AI token streaming**: An [AI Transport](/docs/ai-transport) agent publishes tokens at high frequency and subscribes for steering or control messages. Echoing every token back to the publishing agent is wasteful.
18+
- **RPC over channels**: A caller publishes a request and subscribes for the response on the same channel. The caller already knows what it sent.
19+
- **Mixed workloads**: Some channels on a connection need echo, such as collaborative editing where a client confirms its updates, while others do not, such as notification or logging channels.
20+
21+
The connection-level [`echoMessages`](/docs/api/realtime-sdk/types#client-options) option disables echo across all channels on a connection. The `echo` channel param provides finer control, disabling echo on specific channels while leaving others unaffected.
22+
23+
## Suppress echo on a channel <a id="suppress"/>
24+
25+
Set the `echo` param to `false` when obtaining a channel instance:
26+
27+
<Code>
28+
```realtime_javascript
29+
const channel = realtime.channels.get('{{RANDOM_CHANNEL_NAME}}', {
30+
params: { echo: 'false' }
31+
});
32+
33+
await channel.subscribe((message) => {
34+
// Only receives messages from other clients, not from this client
35+
console.log('Received:', message.data);
36+
});
37+
```
38+
39+
```realtime_nodejs
40+
const channel = realtime.channels.get('{{RANDOM_CHANNEL_NAME}}', {
41+
params: { echo: 'false' }
42+
});
43+
44+
await channel.subscribe((message) => {
45+
// Only receives messages from other clients, not from this client
46+
console.log('Received:', message.data);
47+
});
48+
```
49+
50+
```realtime_java
51+
ChannelOptions channelOpts = new ChannelOptions();
52+
channelOpts.params = new HashMap<>();
53+
channelOpts.params.put("echo", "false");
54+
55+
Channel channel = ably.channels.get("{{RANDOM_CHANNEL_NAME}}", channelOpts);
56+
57+
channel.subscribe(new Channel.MessageListener() {
58+
@Override
59+
public void onMessage(Message message) {
60+
// Only receives messages from other clients, not from this client
61+
System.out.println("Received: " + message.data);
62+
}
63+
});
64+
```
65+
66+
```realtime_go
67+
channel := realtime.Channels.Get("{{RANDOM_CHANNEL_NAME}}", ably.ChannelWithParams("echo", "false"))
68+
69+
_, err := channel.SubscribeAll(context.Background(), func(msg *ably.Message) {
70+
// Only receives messages from other clients, not from this client
71+
log.Println("Received:", msg.Data)
72+
})
73+
if err != nil {
74+
log.Panic(err)
75+
}
76+
```
77+
78+
```realtime_flutter
79+
final channel = realtime.channels.get('{{RANDOM_CHANNEL_NAME}}');
80+
const channelOptions = RealtimeChannelOptions(
81+
params: {'echo': 'false'},
82+
);
83+
84+
await channel.setOptions(channelOptions);
85+
channel.subscribe().listen((message) {
86+
// Only receives messages from other clients, not from this client
87+
print('Received: ${message.data}');
88+
});
89+
```
90+
</Code>
91+
92+
## Interaction with connection-level echo <a id="connection-level"/>
93+
94+
The channel-level `echo` param works alongside the connection-level [`echoMessages`](/docs/api/realtime-sdk/types#client-options) setting:
95+
96+
| Connection `echoMessages` | Channel `echo` param | Result |
97+
|---------------------------|---------------------|--------|
98+
| `true` (default) | Not set | Messages echoed |
99+
| `true` (default) | `false` | Messages suppressed on this channel |
100+
| `false` | Not set | Messages suppressed (connection-level) |
101+
| `false` | `false` | Messages suppressed |
102+
103+
The channel-level param only adds suppression. If the connection already has `echoMessages` set to `false`, echo is suppressed regardless of the channel param.
104+
105+
<Aside data-type='note'>
106+
The `echo` channel param only affects messages. Presence events are always delivered regardless of the echo setting.
107+
</Aside>

src/pages/docs/channels/options/index.mdx

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ redirect_from:
77
- /docs/realtime/versions/v1.1/channel-params
88
---
99

10-
Channel options can be used to customize the functionality of channels. This includes enabling features such as [encryption](/docs/channels/options/encryption) and [deltas](/docs/channels/options/deltas), or for a client to retrieve messages published prior to it attaching to a channel using [rewind](/docs/channels/options/rewind).
10+
Channel options can be used to customize the functionality of channels. This includes enabling features such as [encryption](/docs/channels/options/encryption) and [deltas](/docs/channels/options/deltas), retrieving messages published prior to attaching using [rewind](/docs/channels/options/rewind), or controlling per-channel [echo](/docs/channels/options/echo) behavior.
1111

1212
<Aside data-type='note'>
1313
Looking for message throughput optimization? For channels with high-frequency updates where only the latest value matters, see [Conflation](/docs/pub-sub/guides/data-streaming#conflation). For server-side message grouping, see [Server-side batching](/docs/pub-sub/guides/data-streaming#server-side-batching).
@@ -444,6 +444,43 @@ This feature enables clients to subscribe to LiveObjects updates in realtime eve
444444

445445
For more information see the [inband objects](/docs/liveobjects/inband-objects) documentation.
446446

447+
### Echo <a id="echo"/>
448+
449+
By default, clients receive their own messages back when subscribed to a channel they publish on. This is not always desirable — for example, a client streaming pricing updates or publishing telemetry data does not need its own messages echoed back. The [`echo`](/docs/channels/options/echo) channel param suppresses echo on individual channels, regardless of the connection-level [`echoMessages`](/docs/api/realtime-sdk/types#client-options) setting.
450+
451+
<Code>
452+
```realtime_javascript
453+
const channelOpts = { params: { echo: 'false' } };
454+
const channel = realtime.channels.get('{{RANDOM_CHANNEL_NAME}}', channelOpts);
455+
```
456+
457+
```realtime_nodejs
458+
const channelOpts = { params: { echo: 'false' } };
459+
const channel = realtime.channels.get('{{RANDOM_CHANNEL_NAME}}', channelOpts);
460+
```
461+
462+
```realtime_java
463+
ChannelOptions channelOpts = new ChannelOptions();
464+
channelOpts.params = new HashMap<>();
465+
channelOpts.params.put("echo", "false");
466+
467+
Channel channel = ably.channels.get("{{RANDOM_CHANNEL_NAME}}", channelOpts);
468+
```
469+
470+
```realtime_go
471+
channel := realtime.Channels.Get("{{RANDOM_CHANNEL_NAME}}", ably.ChannelWithParams("echo", "false"))
472+
```
473+
474+
```realtime_flutter
475+
final channel = realtime.channels.get('{{RANDOM_CHANNEL_NAME}}');
476+
const channelOptions = RealtimeChannelOptions(
477+
params: {'echo': 'false'},
478+
);
479+
480+
await channel.setOptions(channelOptions);
481+
```
482+
</Code>
483+
447484
## Modes <a id="modes"/>
448485

449486
Channel mode flags enable a client to specify which functionality they will use on the channel.

src/pages/docs/pub-sub/advanced.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,8 @@ By default, clients will receive their own messages if they are also subscribed
866866

867867
Set the [`echoMessages`](/docs/api/realtime-sdk/types#client-options) property of `ClientOptions` to `false` to disable this behavior. This will stop clients from receiving the messages that they published themselves, but they will continue to receive messages published by others.
868868

869+
To suppress echo on individual channels rather than the entire connection, use the [`echo` channel param](/docs/channels/options/echo). This is useful when a connection needs echo on some channels but not others.
870+
869871
This property is only available using the realtime interface of an SDK, as it isn't possible to subscribe to messages using the REST interface.
870872

871873
### Transient publishing <a id="transient-publish"/>

0 commit comments

Comments
 (0)