Skip to content

Commit 154102a

Browse files
committed
Address PR comments inc. adding pricing pages for AI Transport and LiveSync
1 parent 3119aa2 commit 154102a

File tree

9 files changed

+166
-199
lines changed

9 files changed

+166
-199
lines changed

src/data/nav/aitransport.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,10 @@ export default {
171171
},
172172
],
173173
},
174+
{
175+
name: 'AI Transport pricing',
176+
link: '/docs/ai-transport/pricing',
177+
},
174178
],
175179
api: [],
176180
} satisfies NavProduct;

src/data/nav/livesync.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ export default {
4343
},
4444
],
4545
},
46+
{
47+
name: 'LiveSync pricing',
48+
link: '/docs/livesync/pricing',
49+
},
4650
],
4751
api: [
4852
{
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
---
2+
title: "AI Transport pricing"
3+
meta_description: "Understand how AI Transport token streaming contributes to your message count, including per-token and per-response patterns."
4+
meta_keywords: "AI Transport pricing, message counting, token streaming, message per response, message per token"
5+
intro: "How AI Transport operations contribute to your message count and strategies to optimize costs."
6+
---
7+
8+
[AI Transport](/docs/ai-transport) uses standard Pub/Sub messaging. Each token or message published to Ably counts as an inbound message, and each delivery to a subscriber counts as an outbound message.
9+
10+
## AI Transport operations <a id="operations"/>
11+
12+
The following table shows how AI Transport operations contribute to your message count:
13+
14+
| Operation | Messages counted |
15+
| --- | --- |
16+
| Token publish (per-token) | 1 inbound message per token |
17+
| Token publish (per-response with [append rollup](/docs/ai-transport/token-streaming/token-rate-limits#per-response)) | Multiple tokens conflated into fewer inbound messages |
18+
| Token delivery | 1 outbound message per subscriber |
19+
| [Persistence](/docs/storage-history/storage) storage | 1 additional message per stored message |
20+
21+
The total cost depends on the [token streaming pattern](/docs/ai-transport/token-streaming#token-streaming-patterns) you choose. With per-token streaming, each token is a separate inbound message. With [message-per-response](/docs/ai-transport/token-streaming/message-per-response), append rollup conflates multiple tokens into fewer inbound messages, reducing costs. For example, 300 tokens can be conflated to approximately 100 inbound messages.
22+
23+
<Aside data-type="further-reading">
24+
For how all Ably products count messages, see [message counting](/docs/platform/pricing/message-counting).
25+
</Aside>
26+
27+
## Channels and connections <a id="channels-connections"/>
28+
29+
Each channel used for token streaming contributes to your [channel count](/docs/platform/pricing#channels). Ably bills each connected client for [connection minutes](/docs/platform/pricing#connections) per minute of connection time.
30+
31+
## Cost optimization <a id="optimization"/>
32+
33+
### Use message-per-response streaming
34+
35+
The [message-per-response](/docs/ai-transport/token-streaming/message-per-response) pattern with [append rollup](/docs/ai-transport/token-streaming/token-rate-limits#per-response) conflates multiple tokens into fewer inbound messages, significantly reducing costs compared to per-token streaming.
36+
37+
### Use ephemeral messages
38+
39+
Mark messages as [ephemeral](/docs/pub-sub/advanced#ephemeral) to exempt them from persistence, rewind, resume, and integrations. Use this for streaming tokens where history is not needed.

src/pages/docs/chat/pricing.mdx

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,67 +3,70 @@ title: "Chat pricing"
33
meta_description: "Understand how Chat SDK features contribute to your message count, including messages, typing indicators, reactions, and cost optimization strategies."
44
meta_keywords: "chat pricing, message counting, typing indicators, reactions, cost optimization"
55
intro: "How Chat SDK features contribute to your message count and strategies to optimize costs."
6-
redirect_from:
7-
- /docs/chat/message-billing
86
---
97

108
The [Chat SDK](/docs/chat) is built on top of [Pub/Sub](/docs/pub-sub). All Chat operations generate Pub/Sub messages that follow the same counting rules.
119

12-
<Aside data-type="further-reading">
13-
For how all Ably products count messages, see [message counting](/docs/platform/pricing/message-counting). For package comparison and volume discounts, see the [pricing](https://ably.com/pricing) page.
14-
</Aside>
15-
1610
## Chat operations <a id="operations"/>
1711

1812
The following table shows how Chat operations contribute to your message count:
1913

2014
| Operation | Messages counted |
2115
| --- | --- |
22-
| [Send message](/docs/chat/rooms/messages) | 1 inbound message |
16+
| [Messages](/docs/chat/rooms/messages) ||
17+
| Send message | 1 inbound message |
2318
| Message delivery | 1 outbound message per subscriber |
24-
| [Update message](/docs/chat/rooms/messages#update) | 1 inbound message |
19+
| Update message | 1 inbound message |
2520
| Message update delivery | 1 outbound message per subscriber |
26-
| [Delete message](/docs/chat/rooms/messages#delete) | 1 inbound message |
21+
| Delete message | 1 inbound message |
2722
| Message deletion delivery | 1 outbound message per subscriber |
2823
| [History](/docs/chat/rooms/history) retrieval | 1 message per retrieved message |
29-
| [Typing indicator](/docs/chat/rooms/typing) keystroke | 1 inbound message; repeats every heartbeat interval (default 10s) |
24+
| [Typing indicators](/docs/chat/rooms/typing) ||
25+
| Typing keystroke | 1 inbound message; repeats every heartbeat interval (default 10s) |
3026
| Typing indicator delivery | 1 outbound message per subscriber per heartbeat |
31-
| [Typing indicator](/docs/chat/rooms/typing) stop | 1 inbound message |
27+
| Typing stop | 1 inbound message |
3228
| Typing stop delivery | 1 outbound message per subscriber |
33-
| [Room reaction](/docs/chat/rooms/reactions) | 1 inbound message |
29+
| [Reactions](/docs/chat/rooms/reactions) ||
30+
| Room reaction | 1 inbound message |
3431
| Room reaction delivery | 1 outbound message per subscriber |
3532
| [Message reaction](/docs/chat/rooms/message-reactions) send | 1 inbound message |
3633
| [Message reaction](/docs/chat/rooms/message-reactions) delete | 1 inbound message |
3734
| Message reaction summary delivery | 1 outbound message per subscriber; multiple reactions may be rolled up into a single summary |
38-
| [Presence enter](/docs/chat/rooms/presence) | 1 inbound message |
39-
| [Presence leave](/docs/chat/rooms/presence) | 1 inbound message |
40-
| [Presence update](/docs/chat/rooms/presence) | 1 inbound message |
35+
| [Presence](/docs/chat/rooms/presence) and [occupancy](/docs/chat/rooms/occupancy) ||
36+
| Presence enter | 1 inbound message |
37+
| Presence leave | 1 inbound message |
38+
| Presence update | 1 inbound message |
4139
| Presence event delivery | 1 outbound message per presence subscriber |
42-
| [Occupancy](/docs/chat/rooms/occupancy) event | 1 outbound message per subscriber (generated on membership changes, debounced up to 15s) |
43-
| [Moderation](/docs/chat/moderation) action | 1 inbound message; triggers a message update or delete which follows standard delivery |
40+
| Occupancy event | 1 outbound message per subscriber (generated on membership changes, debounced up to 15s) |
41+
| [Moderation](/docs/chat/moderation) ||
42+
| Moderation action | 1 inbound message; triggers a message update or delete which follows standard delivery |
43+
44+
<Aside data-type="further-reading">
45+
For how all Ably products count messages, see [message counting](/docs/platform/pricing/message-counting).
46+
</Aside>
4447

4548
## Rooms, channels, and connections <a id="rooms-connections"/>
4649

47-
Each Chat room maps to underlying Pub/Sub channels. Each room feature (messages, typing, reactions, presence, occupancy) uses its own channel, contributing to your [channel count](/docs/platform/pricing#channels). Ably bills each connected client for [connection minutes](/docs/platform/pricing#connections) in the same way as Pub/Sub.
50+
Each Chat room maps to a set of underlying Pub/Sub channels. Each room feature (messages, typing, reactions, presence, occupancy) uses its own dedicated channel. The total number of channels used by a room depends on which features are active.
51+
52+
Channels contribute to your [channel count](/docs/platform/pricing#channels). The more rooms a client is attached to, and the more features enabled per room, the more channels are consumed.
53+
54+
Ably bills each connected client for [connection minutes](/docs/platform/pricing#connections). Ably counts a connection-minute for every minute a client maintains an open connection, regardless of activity. Clients that remain connected but idle still accrue connection minutes.
4855

4956
## Cost optimization <a id="optimization"/>
5057

5158
### Reduce typing indicator frequency
5259

5360
Increase the `heartbeatThrottleMs` [room option](/docs/chat/rooms#typing) to reduce typing indicator event frequency. The default is 10 seconds. Increase this value in rooms that tolerate delayed typing feedback.
5461

55-
### Disable typing indicators
62+
### Use server-side batching
5663

57-
Disable typing indicators entirely in rooms where they are not needed. This eliminates a significant source of messages, especially in rooms with many participants.
64+
[Server-side batching](/docs/messages/batch#server-side) groups messages into single deliveries. Use this for high-throughput rooms where slight delay is acceptable.
5865

59-
### Use server-side batching
66+
### Detach from unused rooms
6067

61-
[Server-side batching](/docs/guides/pub-sub/data-streaming#solution-server-side-batching) groups messages into single deliveries. Use this for high-throughput rooms where slight delay is acceptable.
68+
[Detach](/docs/chat/rooms#detach) from rooms when they are no longer needed, and [release](/docs/chat/rooms#release) rooms that are no longer in use. This reduces your channel count and connection usage. Close connections when the client is done to stop accruing connection minutes.
6269

6370
### Use occupancy instead of presence
6471

6572
Use [occupancy](/docs/chat/rooms/occupancy) instead of [presence](/docs/chat/rooms/presence) when you only need member counts, not individual identities. This avoids the n-squared presence event fan-out. For example, 200 members joining and leaving generates approximately **80,400 messages**. See [large-scale presence sets](/docs/presence-occupancy/presence#large-presence) for details.
66-
67-
### Enable server-side presence batching
68-
69-
Enable [server-side batching](/docs/presence-occupancy/presence#large-presence) to group presence events. Subscribe to presence updates only on rooms where you need member-level detail.

src/pages/docs/liveobjects/pricing.mdx

Lines changed: 24 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -2,182 +2,57 @@
22
title: "LiveObjects pricing"
33
meta_description: "Understand how LiveObjects operations contribute to your message count, including LiveMap, LiveCounter, synchronization, and REST API usage."
44
meta_keywords: "LiveObjects pricing, message counting, LiveMap, LiveCounter, ObjectMessages"
5-
intro: "How LiveObjects operations contribute to your message count."
5+
intro: "How LiveObjects operations contribute to your message count and strategies to optimize costs."
66
redirect_from:
77
- /docs/liveobjects/concepts/billing
88
---
99

10-
<If lang="javascript">
11-
<Aside data-type='public-preview'>
12-
LiveObjects JavaScript is in Public Preview. Ably is committed to supporting the LiveObjects JavaScript API and welcomes adoption and feedback.
13-
14-
**Building with LiveObjects?** Help shape its future by [sharing your use case](https://44qpp.share.hsforms.com/2fZobHQA1ToyRfB9xqZYQmQ).
15-
</Aside>
16-
</If>
17-
<If lang="swift">
18-
<Aside data-type='experimental'>
19-
LiveObjects Swift is currently Experimental. Its features are still in development and subject to rapid change.
20-
21-
**Building with LiveObjects?** Help shape its future by [sharing your use case](https://44qpp.share.hsforms.com/2fZobHQA1ToyRfB9xqZYQmQ).
22-
</Aside>
23-
</If>
24-
<If lang="java">
25-
<Aside data-type='experimental'>
26-
LiveObjects Java is currently Experimental. Its features are still in development and subject to rapid change.
27-
28-
**Building with LiveObjects?** Help shape its future by [sharing your use case](https://44qpp.share.hsforms.com/2fZobHQA1ToyRfB9xqZYQmQ).
29-
</Aside>
30-
</If>
31-
32-
LiveObjects operations are billed using ObjectMessages. Each ObjectMessage follows the standard inbound/outbound counting pattern.
33-
34-
<Aside data-type="further-reading">
35-
For how all Ably products count messages, see [message counting](/docs/platform/pricing/message-counting). For package comparison and volume discounts, see the [pricing](https://ably.com/pricing) page.
36-
</Aside>
10+
Ably bills LiveObjects operations using ObjectMessages. An ObjectMessage is the unit of change in LiveObjects. Each state mutation, such as setting a key, incrementing a counter, or creating an object, generates one or more ObjectMessages. Each ObjectMessage follows the standard inbound/outbound counting pattern.
3711

3812
## LiveObjects operations <a id="operations"/>
3913

4014
The following table shows how LiveObjects operations contribute to your message count:
4115

4216
| Operation | Messages counted |
4317
| --- | --- |
44-
| [LiveMap](#livemap-operations) set or remove | 1 inbound message per operation |
45-
| [LiveMap](#livemap-operations) create (shallow) | 2 inbound messages (create + assign) |
46-
| [LiveCounter](#livecounter-operations) increment or decrement | 1 inbound message |
47-
| [LiveCounter](#livecounter-operations) create | 2 inbound messages (create + assign) |
18+
| [LiveMap](/docs/liveobjects/map) set or remove | 1 inbound message per operation |
19+
| [LiveMap](/docs/liveobjects/map) create (shallow) | 2 inbound messages (create + assign) |
20+
| [LiveCounter](/docs/liveobjects/counter) increment or decrement | 1 inbound message |
21+
| [LiveCounter](/docs/liveobjects/counter) create | 2 inbound messages (create + assign) |
4822
| ObjectMessage delivery | 1 outbound message per connected client |
4923
| [Synchronization](#synchronization) | 1 message per object synchronized |
5024
| [REST API](#rest-api) fetch | 1 message per object in response |
51-
| [Batch](#livemap-operations) operation | 1 message per operation in the batch |
25+
| [Batch](/docs/liveobjects/batch) operation | 1 message per operation in the batch |
5226

53-
Nested object creation generates additional messages for each nested object. See the [examples below](#livemap-operations) for details.
27+
Nested object creation generates additional messages for each nested object.
28+
29+
<Aside data-type="further-reading">
30+
For how all Ably products count messages, see [message counting](/docs/platform/pricing/message-counting).
31+
</Aside>
5432

5533
## Channels and connections <a id="channels-connections"/>
5634

5735
Each LiveObjects channel contributes to your [channel count](/docs/platform/pricing#channels). Ably bills [connection minutes](/docs/platform/pricing#connections) per minute of connection time for each connected client.
5836

5937
Subscribing to updates does not affect the number of messages received by a client. Any client attached to a channel with the `object-subscribe` capability automatically receives all object messages for that channel. Subscribing to updates on an object adds a listener that is called whenever the client receives updates for that object.
6038

61-
<If lang="javascript">
62-
63-
## LiveMap operation examples <a id="livemap-operations"/>
64-
65-
Removing a key and setting a primitive value always sends one message:
66-
67-
<Code>
68-
```javascript
69-
// One message
70-
await myObject.get('settings').set('theme', 'dark');
71-
72-
// One message
73-
await myObject.get('settings').remove('theme');
74-
```
75-
</Code>
76-
77-
Creating a shallow `LiveMap` sends two messages: one to create the new `LiveMap` object, and one to assign it to the target object:
78-
79-
<Code>
80-
```javascript
81-
// Two messages: create map + assign to 'settings'
82-
await myObject.set('settings', LiveMap.create({
83-
shallow: 'data'
84-
}));
85-
```
86-
</Code>
87-
88-
Nested `LiveMap` or `LiveCounter` objects each generate their own creation messages:
89-
90-
<Code>
91-
```javascript
92-
// Four messages:
93-
// - create visits counter
94-
// - create stats map
95-
// - create settings map
96-
// - assign to 'settings'
97-
await myObject.set('settings', LiveMap.create({
98-
stats: LiveMap.create({
99-
visits: LiveCounter.create()
100-
})
101-
}));
102-
```
103-
</Code>
104-
105-
Batch operations result in a message for each operation included in the batch:
106-
107-
<Code>
108-
```javascript
109-
// Four messages
110-
await myObject.get('settings').batch((ctx) => {
111-
ctx.set('theme', 'dark');
112-
ctx.set('fontSize', 14);
113-
ctx.set('notifications', true);
114-
ctx.remove('oldSetting');
115-
});
116-
```
117-
</Code>
118-
119-
## LiveCounter operation examples <a id="livecounter-operations"/>
120-
121-
Incrementing and decrementing a counter always sends one message:
122-
123-
<Code>
124-
```javascript
125-
// One message
126-
await myObject.get('visits').increment(5);
127-
128-
// One message
129-
await myObject.get('visits').decrement(3);
130-
```
131-
</Code>
132-
133-
Creating a `LiveCounter` sends two messages: one to create the new `LiveCounter` object, and one to assign it to the target object:
134-
135-
<Code>
136-
```javascript
137-
// Two messages: create counter + assign to 'visits'
138-
await myObject.set('visits', LiveCounter.create(0));
139-
```
140-
</Code>
141-
142-
Creating a counter nested within a `LiveMap` also generates messages for the parent map:
143-
144-
<Code>
145-
```javascript
146-
// Four messages:
147-
// - create visits counter
148-
// - create stats map
149-
// - create settings map
150-
// - assign to 'settings'
151-
await myObject.set('settings', LiveMap.create({
152-
stats: LiveMap.create({
153-
visits: LiveCounter.create(0)
154-
})
155-
}));
156-
```
157-
</Code>
158-
159-
Batch operations result in a message for each operation included in the batch:
160-
161-
<Code>
162-
```javascript
163-
// Three messages
164-
await myObject.get('visits').batch((ctx) => {
165-
ctx.increment(5);
166-
ctx.increment(3);
167-
ctx.decrement(2);
168-
});
169-
```
170-
</Code>
171-
172-
</If>
39+
## Cost optimization <a id="optimization"/>
40+
41+
### Prefer flat data structures
42+
43+
Setting a primitive value on a LiveMap costs one message. Creating a nested LiveMap costs two or more messages (one to create the object, one to assign it), plus additional messages for each level of nesting. Flatten your data model where possible to reduce the number of messages per update.
44+
45+
### Minimize objects per channel
46+
47+
Each object on a channel is synchronized when a client attaches or resynchronizes. Fewer objects per channel reduces the cost of synchronization. Distribute objects across channels based on which clients need access to them.
17348

17449
## Synchronization <a id="synchronization"/>
17550

176-
During initial synchronization and resynchronization, each object on the channel is sent as a message.
51+
During initial synchronization and resynchronization, Ably sends each object on the channel as a message.
17752

178-
For example, if a channel contains 10 objects (such as `LiveMap` and `LiveCounter` instances), a client attaching to the channel will receive 10 messages during synchronization.
53+
For example, if a channel contains 10 objects (such as `LiveMap` and `LiveCounter` instances), a client attaching to the channel receives 10 messages during synchronization.
17954

180-
Similarly, if a client becomes disconnected and needs to resynchronize, it will receive messages for each object that needs to be synchronized.
55+
Similarly, if a client becomes disconnected and needs to resynchronize, it receives messages for each object that needs to be synchronized.
18156

18257
Only [reachable](/docs/liveobjects/concepts/objects#reachability) objects are counted. Ably may send [tombstone](/docs/liveobjects/concepts/objects#tombstones) objects to the client, but these will not count towards your usage.
18358

0 commit comments

Comments
 (0)