WebSocket Events
Connection
Section titled “Connection”Connect to the WebSocket endpoint:
ws(s)://your-host:3000/v1/wsAll messages are binary-encoded using BSATN (Binary SpacetimeDB Typed Notation) by default. A JSON mode is available for development (append ?format=json).
Message types
Section titled “Message types”Client → Server
Section titled “Client → Server”| Message | Description |
|---|---|
Authenticate | Provide a JWT token |
CallReducer | Invoke a reducer |
Subscribe | Subscribe to a SQL query |
Unsubscribe | Cancel a subscription |
OneOffQuery | Execute a single read-only SQL query |
Server → Client
Section titled “Server → Client”| Message | Description |
|---|---|
IdentityToken | Auth confirmation, token, identity |
SubscribeApplied | Initial state snapshot for a new subscription |
TransactionUpdate | Incremental delta (inserts + deletes) for a committed transaction |
ReducerCallResponse | Result of a reducer call |
Error | Protocol or reducer error |
Protocol flow
Section titled “Protocol flow”Client Server │──── Connect ────────────────►│ │◄─── IdentityToken ──────────│ │ │ │──── Subscribe(query) ───────►│ │◄─── SubscribeApplied ───────│ (initial snapshot) │ │ │──── CallReducer ────────────►│ │◄─── ReducerCallResponse ────│ │◄─── TransactionUpdate ──────│ (delta pushed to all subscribers) │ │ │──── Unsubscribe ────────────►│JSON mode (development)
Section titled “JSON mode (development)”For debugging, use ?format=json:
const ws = new WebSocket('ws://localhost:3000/v1/ws?format=json');
ws.send(JSON.stringify({ type: 'Authenticate', token: 'eyJ...'}));
ws.send(JSON.stringify({ type: 'Subscribe', query: 'SELECT * FROM agent_state', query_id: 1}));
ws.onmessage = (event) => { const msg = JSON.parse(event.data); console.log(msg.type, msg);};TransactionUpdate shape
Section titled “TransactionUpdate shape”{ "type": "TransactionUpdate", "subscription_id": 1, "tx_id": 12345, "timestamp": 1735689600000000, "reducer": "record_agent_message", "identity": "abc123", "tables": { "agent_state": { "inserts": [ { "id": 42, "session_id": "session-abc", "role": "user", "content": "Hello" } ], "deletes": [] } }}Backpressure
Section titled “Backpressure”If a client cannot consume deltas fast enough, the server applies backpressure:
- Outgoing buffer fills to
ws_send_buffer_bytes(default: 1 MB) - Server pauses delta delivery for that client
- Client is given
ws_backpressure_timeout_ms(default: 5000) to drain the buffer - If timeout is exceeded, the connection is closed with a
4008 Backpressurecode
Tune in config.toml:
[server]ws_send_buffer_bytes = 2097152 # 2 MBws_backpressure_timeout_ms = 10000Reconnection
Section titled “Reconnection”The TypeScript SDK handles reconnection automatically with exponential backoff. Manual reconnection should:
- Re-authenticate with
Authenticate - Re-subscribe to queries — the server returns a fresh
SubscribeAppliedsnapshot - Process any in-flight
TransactionUpdatemessages from the server (the server may have buffered them)