client.realtime is the shared Centrifugo WebSocket client. Realtime support is always included;
the realtime Cargo feature is an empty compatibility flag.
Prefer typed service helpers (client.balances.subscribe, client.trades.subscribe, …). They
return TypedSubscription<T>. Account orders use the private WebSocket instead: see Order stream.
Realtime is binary-only: the transport negotiates centrifuge-protobuf and uses length-delimited
Protobuf control frames and publication payloads. JSON wire mode applies only to ConnectRPC
debugging, never to realtime. Incoming WebSocket messages, frames, and protobuf record/field
lengths are capped at 8 MiB before publication decoding.
Managed order-book and market-overview subscriptions return dedicated types that expose updates() (an mpsc::Receiver) instead of recv() on TypedSubscription. They also expose set_on_error(...) and err(); use the callback so a failed managed book cannot become a silent,
frozen input to quoting logic.
Subscription contract
| API | Behavior |
|---|---|
recv_result().await | Next publication, clean close, or terminal error |
recv().await | Compatibility API; inspect err() after None |
set_on_error(...) | Callback for background transport/feed errors |
err() / take_err() | Latest terminal background error |
is_alive() | Background task still running |
close() | Stop the subscription |
let mut sub = client
.balances
.subscribe(client.default_account_id.as_deref())
.await?; // handshake done
sub.set_on_error(|error| eprintln!("realtime interruption: {error}"));
while let Some(balance) = sub.recv_result().await? {
println!("{balance:?}");
}Order stream
client.orders.subscribe streams the account's live orders over the private WebSocket
(GET /v1/ws/private) and returns a PrivateOrdersSubscription of PrivateOrdersEvent values, not
bare orders. It exposes recv_result(), recv(), and close(). It returns at once: the handshake
result arrives as Connected or Error, and Ready says the stream reached the account's read
boundary. It resumes by itself after a gap or a reconnect. See Streaming. The same stream is available as client.realtime.subscribe_private_orders(account_id).
Handshake before return
Other subscribe helpers wait for the Centrifugo connect/subscribe handshake (including private token
fetch) before returning. Initial auth failures return Err immediately.
Reconnects after a successful handshake use capped exponential backoff with per-subscription
jitter. A successful resubscription resets the backoff. Private connection and subscription tokens
are renewed before they expire; a failed renewal is reported, and the server then ending the
subscription or connection drives the usual resubscribe.
Private channels need Account ID
Private channels require API-key credentials and an Account ID (default_account_id or an
explicit account_id argument).
Fail-closed overflow
Error::QueueOverflow instead of dropping updates.Snapshot-then-stream
Order book and market overview managed subscriptions snapshot via REST, then stream with gap recovery. Their constructors wait for the WebSocket handshake and initial snapshot before returning. Prefer those helpers over wiring raw channels yourself.
Channel naming
Hyphenated private channel segments (for example api-keys) are valid; the SDK signs with
RFC 3986-preserving query encoding.