Subscriptions
Polling works, and for most applications it is enough. When it is not, the context can subscribe to account updates instead.
Subscriptions are context-owned, which is the important detail: an update arriving over a subscription goes through the same validation and lands in the same cache as a normal read. A subscribed fleet and a fetched fleet are the same cached snapshot, not two views that can disagree.
Configure the reference provider
Section titled “Configure the reference provider”Inject an application-owned Kit RpcSubscriptions<AccountNotificationsApi> into
createRpcSubscriptionProvider from @aephia/atlas-kit/client. The factory does
not create a socket, accept a URL, or retain credentials. Nothing subscribes
until you explicitly call ctx.data.subscribe() or a capability’s watcher.
Illustrative setup with an existing Kit connection and account provider:
import type { AccountNotificationsApi, RpcSubscriptions } from '@solana/kit';import { createRpcSubscriptionProvider, createSageContext,} from '@aephia/atlas-kit/client';import type { AccountProvider } from '@aephia/atlas-kit/client';
function createLiveContext( rpcSubscriptions: RpcSubscriptions<AccountNotificationsApi>, provider: AccountProvider,) { return createSageContext({ cluster: 'zink-ptr', provider, subscriptions: createRpcSubscriptionProvider({ rpcSubscriptions, identity: { kind: 'websocket', name: 'application-live' }, backoff: { initialMs: 250, maxMs: 30_000 }, }), });}
// Pass your existing connections to createLiveContext(), then register through// ctx.data.subscribe() or watchFleet(). Call ctx.dispose() on teardown.The identity is optional and defaults to websocket / rpc-subscriptions.
Use only a non-secret label: identities are public provenance, never a place for
endpoints or authentication material. Backoff defaults to 250–30,000 ms; supplied
values must be positive safe integers with maxMs >= initialMs or the factory
throws synchronously.
The adapter requests base64 data at the registration commitment (confirmed by
default). Initial registration failure rejects with a sanitized ProviderError
and no automatic retry. Once registered, stream termination or failure starts
one retry loop per registration. Each wait uses equal jitter between half and
all of the capped exponential delay, rounded down to at least 1 ms. Successful
re-registration resets the delay and emits reconnected before account events.
Failed attempts never emit it. Transport exceptions and abort reasons are not
copied into errors or diagnostics. Listener exceptions do not trigger retries.
Explicit unsubscribe, caller abort, and context disposal cancel pending waits and release each Kit registration via its abort signal. Iterator cleanup is best-effort, so a transport that ignores cancellation cannot block teardown or deliver later updates. No transport can guarantee updates during an outage; the context closes that gap with its existing direct-read resynchronization.
Bring your own AccountSubscriptionProvider if your transport needs a different
integration. It must honor cancellation and emit reconnected only after a
successful registration; keep validation, caching, and resynchronization in the
context rather than duplicating them in the provider.
Why the shared cache matters
Section titled “Why the shared cache matters”Without shared identity, a live update and a fetch race each other, and which one your application sees depends on timing. Here they cannot diverge: both write to the same cache slot under the same key.
Updates are translated the same way reads are, so a subscription delivers the SDK’s own snapshot types rather than raw account bytes.
Reconnection
Section titled “Reconnection”Connections drop. When one does, the SDK resynchronises rather than resuming blindly, because the gap between disconnect and reconnect is exactly where missed updates hide.
Reconnects coalesce: a burst of drops produces one resynchronisation rather than one per drop, and a reconnect that arrives while another is in flight is folded into it rather than queued behind it.
Cancellation
Section titled “Cancellation”Subscriptions are cancellable, and disposing a context cancels everything it owns. That matters in a browser, where a component unmounting must not leave a socket delivering updates into a cache nobody reads.
When to reach for this
Section titled “When to reach for this”Prefer polling with a sensible maxAge unless you have a reason not to. It is
simpler, it degrades more gracefully, and for state that changes on the scale
of minutes it is indistinguishable to a user.
Subscribe when you are tracking something that genuinely moves — an active fleet, an order book — and staleness is visible.
Reference
Section titled “Reference”client— subscription exports- Caching and provenance — the cache updates land in