RPC subscriptions

Get notified of changes to the blockchain

RPC subscriptions let your application receive live updates from the network instead of polling for them. They are delivered over a WebSocket endpoint and surface as async iterators in Kit, which fit naturally into modern JavaScript control flow.

Kit aims to support every method documented in the Solana RPC WebSocket methods docs. As with HTTP RPC, you can either browse the methods in the official documentation or rely on TypeScript autocompletion in your editor.

Installation

You will typically install Kit alongside the RPC plugin package, which provides both HTTP and WebSocket connectivity.

npm install @solana/kit @solana/kit-plugin-rpc

If you only need subscriptions and prefer not to use a Kit client, the lower-level createSolanaRpcSubscriptions function is available directly from @solana/kit.

Create a subscriptions client

The bundle plugins from @solana/kit-plugin-rpc install both client.rpc and client.rpcSubscriptions in one step. You do not need to manage two separate transports.

import {  } from '@solana/kit';
import {  } from '@solana/kit-plugin-rpc';
import {  } from '@solana/kit-plugin-signer';
 
const  = await ().(()).(());

By default, the WebSocket endpoint is derived from the HTTP endpoint by swapping http/https for ws/wss. If your provider hosts the two endpoints at different URLs, pass rpcSubscriptionsUrl explicitly in the plugin configuration.

Subscribe to slot notifications

Subscriptions return an async iterator. The most idiomatic way to consume one is a for await loop, which keeps reading notifications until the underlying subscription ends.

const  = await .
    .()
    .({ : .(10_000) });
 
for await (const  of ) {
    .('The network advanced to slot', .);
}

The .subscribe({ abortSignal }) step is mandatory because every subscription must be tied to an AbortSignal. This forces you to think up front about when the subscription should end and prevents leaks.

Cancel subscriptions

You may want to cancel a subscription before it ends naturally — for example, when a component unmounts in a UI. Pass an AbortController so that calling .abort() from anywhere in your code stops the iterator gracefully.

const  = new ();
const  = await .
    .()
    .({ : . });
 
// Stop receiving notifications after the user navigates away.
.();

AbortSignal.timeout(ms) is a convenient shortcut when you simply want a fixed duration. For one-off subscriptions, that single line is often all you need.

Subscribe to account changes

Account subscriptions notify you whenever an account's data changes onchain. The shape of the notification mirrors the response of getAccountInfo, so the same encoding and commitment options apply.

import {  } from '@solana/kit';
const  = ('GdnSyH3YtwcxFvQrVVJMm1JhTS4QVX7MFsX56uJLUfiZ');
const  = await .
    .(, { : 'confirmed' })
    .({ : .(60_000) });
 
for await (const  of ) {
    .('Account changed:', .);
}

If you only need a one-off read of an account, fetchEncodedAccount is usually a better fit. Use subscriptions for live, ongoing updates.

Handle disconnects and errors

Long-lived subscriptions can disconnect for many reasons — flaky networks, server restarts, or connection limits — and errors can be raised at any point during iteration. Wrap the iteration in a try/catch so your application can react gracefully.

import {  } from '@solana/kit';
const  = ('GdnSyH3YtwcxFvQrVVJMm1JhTS4QVX7MFsX56uJLUfiZ');
const  = await .
    .(, { : 'confirmed' })
    .({ : .(60_000) });
 
try {
    for await (const  of ) {
        .('Account changed:', .);
    }
} catch () {
    // Reconnect, log, surface a UI error, etc.
}

Depending on your application, you may want to recreate the subscription with a fresh AbortSignal after a disconnect, possibly using a small backoff to avoid thrashing the server.

Use subscriptions without a client

If you do not need a Kit client, you can build an RpcSubscriptions object directly with createSolanaRpcSubscriptions. This is the lower-level building block the plugins use under the hood.

import { ,  } from '@solana/kit';
 
const  = (('wss://api.mainnet-beta.solana.com'));
const  = await 
    .()
    .({ : .(10_000) });

This is useful when you want maximum tree-shaking, when you are writing a library that should not assume a client, or when you only need a tiny subset of the subscriptions API.

Choose a WebSocket endpoint

For light development or personal use, the public WebSocket endpoints maintained by the Solana Foundation work the same way as their HTTP counterparts.

  • wss://api.mainnet-beta.solana.com
  • wss://api.testnet.solana.com
  • wss://api.devnet.solana.com

In production, your HTTP and WebSocket endpoints should match — both clusters and providers — to avoid subtle mismatches between the data each transport returns. Most RPC providers offer paired endpoints; consult their documentation for the exact URLs they expect you to use.

Next steps

On this page