Geyser · Solana Streaming
Geyser concepts
SubscribeRequest describing what you want, and the server pushes SubscribeUpdate messages back as state changes — no polling, no per-call round trips. The proxy forwards your request to Solana's Yellowstone endpoint unchanged, so the full Yellowstone filter surface is yours.Push, not poll
JSON-RPC makes you ask. You call getAccountInfo on a timer and diff the result, paying a full request round trip every poll and learning about a change only on your next tick. A WebSocket logsSubscribe pushes, but it speaks a narrow slice of the firehose and filters thinly.
Geyser inverts that. The match runs on the server: you declare the accounts, programs, and transaction shapes you care about, and only matching updates cross the wire — the moment they happen, at the commitment you chose. One TCP/TLS session carries every subscription type at once.
What you can subscribe to
A SubscribeRequest is a set of named filter maps. Older write-ups call Geyser a “four types” stream; the real proto surface is wider. Every map below ships in one request, and you mix as many as you need.
| field | bandwidth | what it streams |
|---|---|---|
| slots | low | Slot status as the chain advances — one tiny message per slot. The cheapest heartbeat for tracking chain head. |
| accounts | medium | Account writes, filtered by explicit pubkeys, program owner, or memcmp/datasize predicates. Cost scales with how much data the matched accounts carry. |
| transactions | high | Full transactions matching account include/exclude/required, vote and failed flags. The whole message + meta lands on the wire. |
| transactionsStatus | low | Signature + status only — no instructions, no meta. Use it when all you need is "did tx X land, and in which slot". |
| blocks | high | Whole blocks: every transaction and account update inside them. The heaviest subscription — filter it down or avoid it. |
| blocksMeta | low | Block headers without the per-transaction payload — blockhash, parent slot, block time, tx counts. A fraction of a full blocks stream. |
| entry | medium | Proof-of-history entries as the leader produces them — sub-slot granularity below the block boundary. |
| accountsDataSlice | low | Not a filter but a shaper: an array of {offset, length} ranges that trims account data down to the bytes you actually read. |
| ping | low | In-stream ping toggle the server echoes back — a way to keep a quiet stream warm without opening a side channel. |
Reach for blocksMeta over blocks, and transactionsStatus over transactions, whenever the lighter feed answers your question — the bandwidth gap is large.
Commitment levels
Commitment is the trade between speed and certainty. Set it once per request via CommitmentLevel. When you leave it unset the stream runs at PROCESSED.
| level | latency | rollback risk |
|---|---|---|
| PROCESSED | Lowest — the node has seen the slot but the cluster has not voted on it yet. | Can be dropped on a fork. Treat its data as provisional. |
| CONFIRMED | A supermajority has voted for the slot. A few hundred ms behind PROCESSED. | Reorg is very unlikely but not formally impossible. |
| FINALIZED | Highest — the slot is rooted, roughly 30+ slots back. | Irreversible. Use it when a rollback would corrupt your state. |
commitment filter are rejected with gRPC PermissionDenied; attach a TheRPC API key to unlock CONFIRMED and FINALIZED. See Resilience & keepalive for the exact error and how to handle it.Filters combine
Each map is keyed by a name you pick. Put several named entries under one map to watch unrelated targets in parallel — say raydium_pools and spl_token side by side under accounts. When an update arrives it carries the filter names it matched, so your handler can route on the name instead of re-deriving why the message showed up.
Ready to write filters? The Filters & data slices page covers memcmp, owner predicates, and accountsDataSlice with worked code.