RPC Infrastructure

Solana WebSocket nodes for live account, log, and slot subscriptions

Polling getAccountInfo on a loop is the first Solana mistake every team makes and the first thing every reviewer flags. Solana exposes a real WebSocket PubSub interface, with subscriptions for accounts, transaction logs, programs, signatures, slots, blocks, and votes. The protocol's been stable since 2021. The hard part isn't subscribing. The hard part is keeping the socket alive under real load, knowing which subscription type fits the question you're asking, and having a clean fallback when blockSubscribe disappears mid-stream because the validator restarted. NoLimitNodes runs WebSocket on the same bare-metal fleet as RPC, with persistent connections that auto-reconnect and an explicit posture on which subscriptions are production-grade and which ones aren't. The endpoint is wss://ws.nln.clr3.org. Auth is the same x-api-key header your RPC client uses.

Sub-10ms pushAll 9 PubSub methodsUp to 100 subs per connectionAuto-reconnectFree tierNo per-message meter
On-chain programs

Every Solana PubSub subscription you can open

the full standard PubSub method set with honest notes on which ones to actually use

EventTypeDescriptionFrequencyLatency
accountSubscribeeventPush every change to a single account by pubkey. The right call for wallet UIs, oracle feeds, and pool reserves.High8ms
logsSubscribeeventStream raw program logs filtered by mentions, all, or vote. Returns base64 log lines, not parsed events.Very high9ms
programSubscribeeventPush every account update under a program. Always pass dataSize and memcmp or you will saturate the socket.Very high10ms
signatureSubscribeeventFires when a transaction reaches the requested commitment level. Auto-unsubscribes after the notification.High8ms
slotSubscribeeventNotification on every slot processed by the validator. The cluster heartbeat; useful for liveness checks.Very high6ms
slotUpdatesSubscribeeventRicher slot stream with first-shred-received, completed, optimistic-confirmation, and root events.Very high6ms
rootSubscribeeventFires when a slot becomes rooted (finalized). Lower frequency than slotSubscribe; useful for settlement.Medium8ms
blockSubscribeeventPushes full blocks with all transactions on the requested commitment. Heavy; not stable across all releases.Medium25ms
voteSubscribeeventStream of validator vote transactions. About 70% of mainnet tx volume; almost always the wrong subscription.Very high7ms

WebSocket performance at a glance

last reviewed 2026-04-28

slotSubscribe push p50
6ms
From cluster slot landing to client receipt, US-East
Verified 2026-04-28
logsSubscribe sustained throughput
~350 msg/s
Per single connection before backpressure kicks in; gRPC after that
Verified 2026-04-28
Connection uptime
99.95%
Persistent socket survival, monthly rolling
Verified 2026-04-28
Subscriptions per connection
100
Hard cap on a single WebSocket connection (Pro and Ultra)

What logsSubscribe and accountSubscribe actually return

Both methods sit on the same socket and look similar in the docs. The shape of the data they push is wildly different, and getting that wrong costs you a week of debugging.

accountSubscribe fires whenever the bytes at a single pubkey change. The notification carries the slot, the lamport balance, the owner program, and the full data buffer in your requested encoding. We default to jsonParsed for token, stake, and vote accounts so you skip the bincode pass; pass base64 if you need raw bytes. Each notification is one account, fully serialized. Easy to reason about. The cost is one subscription per account; tracking a wallet means subscribing to its base account plus every token account you care about.

logsSubscribe is a different beast. The notification carries a transaction signature, the slot, an error field, and an array of log lines straight from the BPF runtime. No parsed instructions, no decoded arguments, no idea which inner instruction emitted which log unless you walk the array yourself. You also get every log from every program the transaction touched, which on a Jupiter swap might be eight programs deep. The filter options are all, allWithVotes, or a { mentions: [...] } object that scopes to transactions touching specific programs or accounts. Always use the mentions filter. all on mainnet is roughly 2,500 messages per second, most of it vote traffic.

The opinion: logsSubscribe is the wrong tool for parsed events. It's the right tool for two narrow cases: a known-program error log feed (you watch for Program log: Error), and a quick-and-dirty signal that anything happened at a program address while you build the proper gRPC pipeline.

How much throughput a WebSocket connection actually has

The protocol gives you a TCP connection with TLS on top and JSON messages over the wire. Three things cap your effective throughput and the order they bite is predictable.

BottleneckWhere it bitesPractical ceiling
JSON parse costClient side~400 msg/s in Node, ~700 in Rust
Single TCP connectionNetwork buffer + head-of-line~30-50 MB/s sustained
Subscription countServer enforces a cap100 subs per connection (NLN)

The first ceiling, the JSON parse, is what kills most production WebSocket setups. A busy programSubscribe on Token-2022 can land 600 messages per second, and a Node handler that does anything besides JSON.parse falls behind. The server can't magically make your client faster, so the messages queue, then drop. We watch teams hit this around the three-week mark of a launch.

The fix is one of two things. Either narrow the subscription (better filters, accountSubscribe per pubkey instead of one big programSubscribe), or change transports. Yellowstone gRPC handles 5,000+ messages per second on a single connection because Protocol Buffers parse in a quarter of the time JSON does and HTTP/2 multiplexes streams so one slow message doesn't block the next.

When to graduate from WebSocket to gRPC

We have an opinion on this and we'll be direct about it. WebSocket is the right transport for two things: account-level UIs (a wallet, a position dashboard, a mint counter), and prototypes where you want to see something working in fifteen minutes. Past those two, gRPC is the right answer.

The signal you've outgrown WebSocket is rarely throughput. It's parsing tax. You start writing your own log decoder, then a discriminator router, then a fallback when the log lines are truncated, then a reconciliation pass when the subscription reconnects mid-stream. Every one of those is solved upstream when you switch to gRPC. The events arrive as protobuf messages with a stable schema. You skip the entire decode layer.

Some specific triggers. If you find yourself running multiple logsSubscribe connections in parallel because one isn't keeping up, switch. If you need to filter by accountInclude and accountExclude on the same stream, switch. If you want vote-free transactions and your logsSubscribe mentions filter is matching too many vote txs because the validator touched them, switch.

What stays on WebSocket: signature confirmation polling replaced by signatureSubscribe, a wallet UI showing a balance update, a slot heartbeat for cluster observability, a programSubscribe with tight filters on a low-volume program. Use the right tool for the question. The endpoint sits on our gRPC product page when you're ready.

Subscription patterns and reconnection that actually works

A WebSocket connection isn't TCP-stable. It will drop. Your client needs to assume that and rebuild state on reconnect, or you'll spend a Saturday wondering why the dashboard stopped updating at 3am.

Heartbeat & ping/pong

We send a ping every 25 seconds. Your client sends a pong back automatically in most libraries. If you go three pings without a pong, treat the connection as dead. A silent socket isn't a healthy socket; it's a TCP connection with a NAT box that gave up half an hour ago and forgot to tell anyone.

Re-subscribe on reconnect

Subscriptions don't survive a reconnect. The new connection has no idea what you cared about. Keep your subscription list in memory and re-send every accountSubscribe and logsSubscribe call as part of your reconnect handler.

Backfill the gap

Between the disconnect and the reconnect, you missed events. Snapshot the slot you last saw, then on reconnect issue a one-shot getSignaturesForAddress or getAccountInfo to backfill. WebSocket has no replay buffer; ours, theirs, no one's.

Idempotent handlers

Reconnect plus backfill means some events arrive twice. Key every downstream effect by signature plus slot or by account pubkey plus update slot. Two notifications with the same key produce the same outcome. This is the cheapest insurance you can buy.

One more pattern that earns its keep: the snapshot-then-stream flow. Open the WebSocket and subscribe first. Once the subscription ack comes back, fire a one-shot getAccountInfo at the same commitment level. Apply the snapshot to your state. From that point, every notification is a delta. You never miss the starting state and you never double-count the moment between the subscribe and the snapshot.

WebSocket vs SSE vs polling: pick the right transport

Solana doesn't expose Server-Sent Events natively, but the comparison still matters because some teams reach for SSE through a proxy and end up worse off. Here's the honest take.

TransportRight forWatch out for
HTTP pollingStatus pages, slow data, cron-style readsRate limits, wasted requests
SSE (server proxy)Pure browser fan-out from a backendOne-way only, no native auth headers
WebSocketLive UIs, account streams, signature acksBrowser can't set headers; backpressure
gRPCIndexers, MEV, programmatic streamsNot browser-native; needs gRPC-Web bridge

For a frontend that needs to show live state, the working pattern is: backend connects to our WebSocket (or gRPC for high volume), fans the relevant slice out to the browser via either WebSocket or SSE. That keeps the auth header on the server, lets you cache and dedupe before the browser sees anything, and gives you a natural place to add business logic between the chain and the UI.

For a backend that needs to react to state, skip SSE entirely. WebSocket if the volume fits, gRPC if it doesn't. Polling only for things that genuinely change slowly: an Epoch boundary, a stake-account state, a once-per-minute price.

Frequently asked questions

It's the PubSub side of the Solana JSON-RPC spec. The same validator that answers HTTP RPC also exposes a WebSocket interface where you subscribe to account changes, log lines, slot progression, signature confirmations, and a few other event types. The push happens within roughly the same time the slot is processed, which on healthy mainnet is well under 100ms wall-clock from the originating tx. The full method set is documented at solana.com/docs/rpc/websocket.

Start streaming Solana over WebSocket in under 60 seconds

Free tier covers prototyping. Pro at $49/mo unlocks the full subscription budget plus blockSubscribe. Ultra at $199/mo lifts the cap to 100 concurrent subscriptions per connection and adds 30 hours of custom dev time.

Ready to get started?

Get your free API key and start building in under 30 seconds.

Talk to Sales