Learn · Publish and subscribe
Publishers
Publish through a participant, retry one logical send, and reconcile its acknowledgment with delivery.
A publisher is a participant or agent performing a write. The TypeScript SDK exposes publication on RoomClient and ChannelClient; you do not need a separate publisher service or lifecycle object.
Publish through the participant boundary
For a channel event, RMC requires event:publish on the channel ID. For a channel-less event, the event type is the resource. RMC derives the actor from the authenticated participant and reloads current authority when processing the queued command.
Publication is serialized by the room runtime and committed to SQLite before readers are notified. A waiting application callback does not hold that room's publication queue. The architecture walkthrough follows these steps through the implementation.
Keep one identity for one send
// Keep this object until the send succeeds or the user abandons it.
const pending = {
clientEventId: crypto.randomUUID(),
channelId: "chat",
type: "text.message.committed",
payload: {text: "Please check the shipment."},
};
// room is an authorized RoomClient. Retry calls send again unchanged.
const send = () => room.publish(pending);
const committed = await send();
A network error may occur after the commit but before its HTTP response reaches the client. Reuse the event ID, payload, and metadata for that logical send. Generating another ID makes another publication.
The key is unique across the room. RMC checks the original actor and publication metadata before returning an earlier event. Compatible retries are first-write-wins for callers authorized to read the original. A publish-only caller cannot use a changed payload to retrieve a hidden event; its retry payload must be semantically equal JSON. See the full retry contract.
Reconcile the acknowledgment and the stream
The publish response and a subscription callback can describe the same committed event. Use its event ID to deduplicate your view. If you show an optimistic message, keep the pending send identity and reconcile it with the server acknowledgment instead of appending another row blindly.
The SDK does not automatically retry HTTP publication. Your application owns pending sends, retry/backoff, and user-visible errors. Multiplexed subscriptions have their own transport reconnection behavior.
The exact checks and commit boundary are in publication.go and runtime.go. Publication tests cover authority, collisions, and retries.