Skip to main content

At a glance

Capabilityv1v2
Real-time transaction stream
Account include / exclude / required filters
Ping and version checks
Change filters live, without reconnecting
Named filters with accept / reject acknowledgements
Enriched transaction fields (fee payer, priority fee, compute units, program IDs, writable accounts, size)
Resolved address-lookup-table accounts
Slot lifecycle stream (alive / complete / dead)
Per-message sequence numbers for gap detection
Idle heartbeats
Both v1 and v2 give you the decoded transaction: signatures, account keys, instructions, the message header, and any address-lookup-table references. What v2 adds is enrichment on top of that (the pre-computed fields above), plus the live-subscription, slot, and liveness features. Enrichment is opt-in; see below.

More data, fewer RPC calls

With v1 you get the decoded transaction and work out the rest yourself. Anything past the core fields is on you: who paid the fee, what the priority fee was, which accounts are writable, and the real accounts behind a versioned transaction’s lookup tables. v2 can do that work for you. Turn on enrichment and each transaction also carries the fields below.
To get…On v1 you…On v2 (enrichment on)
The full account list of a versioned (v0) transactionMake a full RPC call per transaction to fetch the lookup table, then resolve the indexes yourselfAlready resolved and included (loaded_writable_addresses / loaded_readonly_addresses)
The fee payerDerive it from the account keys and headerIncluded (fee_payer)
The priority fee and compute-unit limitParse the compute-budget instructions yourselfIncluded (priority_fee, compute_limit)
The writable accountsCompute them from the header and resolved lookup tablesIncluded (writable_accounts)
The program IDs the transaction touchesWalk every instructionIncluded (program_ids)
The transaction sizeReconstruct and measure the transactionIncluded (tx_size)
The lookup-table row is the big one. A versioned transaction does not carry its full account list. It carries a reference to an on-chain lookup table plus a set of indexes. On v1, to learn which accounts the transaction actually touches, you make a full RPC call to fetch that table and then resolve the indexes yourself, for every transaction. An RPC request and response is far slower than receiving the stream itself, and it sits right on your critical path. v2 resolves it server-side before the transaction reaches you, so that call disappears. The other rows never hit the network, but they are still work your client repeats on every transaction. v2 does it once, on our pipeline, and ships the answer inline.
Enrichment is opt-in and off by default. Flip it on per subscription (include_enrichment: true on a filter) whenever you want the extra fields. It is subscription-wide: if any active filter turns it on, every transaction the session receives is enriched.

Manage your stream without reconnecting

In v1 you set your filters once, in the message that opens the stream. To watch something different you drop the connection and open a new one, losing the warm stream while you reconnect. v2 keeps the stream open and lets you add and remove filters as you go. You give each filter your own filter_id, the server acknowledges every add and remove (and tells you why if it rejects one), and every transaction lists the filter_id values it matched. Run several filters on one connection, change them on the fly, and always know which filter produced a given transaction.

Follow the chain with slot events

v2 adds a second, separate stream, SubscribeSlots, that v1 has nothing like. You get an event when a slot starts (ALIVE), finishes (COMPLETE), or is skipped or times out (DEAD), along with that slot’s leader and parent. It is a cheap way to track where the chain is instead of inferring it from the transaction flow.

Know when you have missed something

Two things v1 never gave you:
  • Every v2 message, transactions and slot events alike, carries a sequence number that climbs by one. See a gap and you know you dropped a message.
  • When a stream goes quiet, v2 sends a Heartbeat about once a minute, stamped with the server’s clock. That keeps the connection alive through NAT and load-balancer idle timeouts, and tells a quiet stream apart from a dead one.

Why this adds up to a faster result

  • A whole RPC call removed. Resolving a lookup table on v1 is a full RPC request and response, much slower than the stream itself. v2 does it for you, so that call never sits between a transaction arriving and you acting on it.
  • Work done once, not per client. Enrichment is computed on our low-latency pipeline instead of in every client, every time.
  • No reconnect gaps. Changing filters live means you never drop the stream to re-subscribe.
  • Loss and stalls are visible immediately through sequence numbers and heartbeats, instead of being inferred after the fact.

Which should you use

Use v2 for new integrations. It is where enrichment, slot events, live filters, and the liveness signals live, and where every new capability lands. v1 stays fully supported and has no set retirement date, so an existing v1 client can keep running as it is. We do encourage moving over, though: as more traffic consolidates onto v2, it frees the capacity we dedicate to v1 today for the next generation of OrbitFlare streaming. Either way, migrating is a change in your client code, not your connection: same endpoints, same authentication, running side by side.

See Also

Jetstream v2 Overview

The streaming model, connecting, and best practices.

v2 Protocol Reference

Full v2 Protocol Buffer specification, endpoints, and code generation.

Jetstream (v1)

The v1 overview, client examples, and filtering guide.

Support

For technical support or questions about Jetstream v2, please contact our support team or join our Discord community.