Jito bundles versus staked connections

Operations18 min read

Jito bundles buy atomic, ordered execution and a shot at the top of a block. Staked connections buy fast, reliable delivery to the leader. They solve different problems, they are not mutually exclusive, and picking the wrong one costs you either money or fills.


the short version
  • Bundles buy atomic, ordered execution across up to five transactions. Nothing else on Solana gives you that.
  • Staked connections buy admission: the leader reading your packets during contention.
  • They are not competing products. They operate at different layers and compose.
  • If you need atomicity, only a bundle will do. If you need delivery, a bundle is not the tool.

This comparison is usually framed as a choice, and that framing is wrong. Jito bundles and staked connections answer different questions, and the confusion between them leads people to buy the wrong thing and then conclude it did not work.

We sell one of these, so read the disclosure at the end and weigh the rest accordingly. I have tried to write the version I would want to read if I were choosing.

They solve different problems#

Jito bundleStaked connection
Question answeredWill these execute together, in order?Will the leader read my packet?
LayerBlock constructionNetwork admission
AtomicityYes, up to five transactionsNo
Ordering guaranteeYes, within the bundleNo
You pay whenOnly if it landsPer submission
Works with every leaderOnly Jito-enabled leadersYes
Failure modeSilently loses the auctionDelivered, may still not land

Read the first row twice. “Will these execute together” and “will my packet be read” are not competing answers to one question, they are answers to two.

What a bundle actually gives you#

A bundle is up to five transactions submitted to a block engine, which runs an auction and forwards the winners to a Jito-enabled leader for inclusion at the top of the block. Within a bundle, execution is atomic and ordered.

bundle.ts
1import { Connection, VersionedTransaction, SystemProgram, PublicKey } from "@solana/web3.js";
2import bs58 from "bs58";
3
4/**
5 * A bundle is an ordered list of up to five transactions that execute
6 * atomically and in the order given, or not at all.
7 *
8 * The tip is a plain SOL transfer to a tip account, included as an instruction
9 * inside one of the bundled transactions. It is what you bid for inclusion, and
10 * unlike a priority fee it is only paid if the bundle actually lands.
11 */
12const TIP_ACCOUNTS = [
13 "96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5",
14 "HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe",
15 // ...rotate across the published set so you do not create contention on one
16];
17
18export function tipInstruction(from: PublicKey, lamports: number) {
19 const to = new PublicKey(TIP_ACCOUNTS[Math.floor(Math.random() * TIP_ACCOUNTS.length)]);
20 return SystemProgram.transfer({ fromPubkey: from, toPubkey: to, lamports });
21}
22
23export async function sendBundle(blockEngineUrl: string, txs: VersionedTransaction[]) {
24 if (txs.length > 5) throw new Error("a bundle is at most five transactions");
25
26 const res = await fetch(`${blockEngineUrl}/api/v1/bundles`, {
27 method: "POST",
28 headers: { "Content-Type": "application/json" },
29 body: JSON.stringify({
30 jsonrpc: "2.0",
31 id: 1,
32 method: "sendBundle",
33 params: [txs.map((t) => bs58.encode(t.serialize()))],
34 }),
35 signal: AbortSignal.timeout(5_000),
36 });
37
38 const body = await res.json();
39 if (body.error) throw new Error(`bundle rejected: ${body.error.message}`);
40
41 // A bundle id is NOT a landing confirmation. It means the block engine
42 // accepted your submission into the auction. You still have to check.
43 return body.result as string;
44}

The genuinely unique property is atomicity, and it is not replaceable.

atomic.ts
1/**
2 * The case bundles exist for: two operations that are only safe together.
3 *
4 * A liquidation that borrows, liquidates and repays is worthless if the first
5 * two land and the third does not. Sequenced as separate transactions, another
6 * actor can interleave between them. Bundled, either the whole sequence
7 * executes in order or none of it does.
8 *
9 * There is no way to build this out of independent transactions. It is not a
10 * latency optimisation, it is a correctness property, and if you need it then
11 * nothing else on this page substitutes for it.
12 */
13const bundle = [
14 buildFlashBorrow(amount), // 1
15 buildLiquidation(position), // 2
16 buildRepayWithTip(amount, tip) // 3, carries the tip
17];
18
19// All three, in this order, in one block. Or nothing.
20const bundleId = await sendBundle(BLOCK_ENGINE, bundle);

You cannot build that out of independent transactions. Between transaction two and transaction three, anyone can act. If your strategy has a window in which a partial execution is unsafe, a bundle is not an optimisation, it is the requirement.

The limits worth knowing

  • Not every leader runs Jito. When the current leader does not, bundles have nowhere to go for that slot. Coverage is high but it is not universal, and the gaps are invisible to you.
  • The auction is an auction. Losing is the normal case, not an error, and it produces no failure at submission time.
  • A bundle id is not a confirmation. It means the block engine accepted your entry.
  • Five transactions, and the whole bundle must fit the block.
status.ts
1/**
2 * Confirm a bundle landed. The bundle id is a receipt for the auction, not
3 * for the chain.
4 *
5 * Bundles fail silently and often: you lost the auction, the simulation failed
6 * at the block engine, or the leader for that slot was not running Jito. None
7 * of those produce an error at submission time.
8 */
9export async function bundleLanded(blockEngineUrl: string, bundleId: string) {
10 const res = await fetch(blockEngineUrl, {
11 method: "POST",
12 headers: { "Content-Type": "application/json" },
13 body: JSON.stringify({
14 jsonrpc: "2.0", id: 1,
15 method: "getBundleStatuses",
16 params: [[bundleId]],
17 }),
18 });
19
20 const { result } = await res.json();
21 const status = result?.value?.[0];
22
23 if (!status) return { landed: false, reason: "unknown, likely lost the auction" };
24 if (status.confirmation_status) return { landed: true, slot: status.slot };
25 return { landed: false, reason: status.err ?? "not included" };
26}
27
28// Budget for this. A meaningful share of bundles do not land, and the ones
29// that do not are invisible unless you check.

What a staked connection gives you#

A staked connection addresses an earlier question. Before ordering matters, before block construction matters, the leader has to accept the connection carrying your transaction and read the stream.

Capacity for that is allocated in proportion to stake. Unstaked senders contend for a small shared remainder, which during congestion is where transactions quietly evaporate. The mechanism is covered in stake-weighted QoS explained.

What it does not give you:

  • No atomicity. Each transaction stands alone.
  • No ordering guarantee against anyone else.
  • No guarantee of inclusion. Delivery is not the same as landing.

It is a narrower promise, and being honest about how narrow is the whole point of this page.

Tips are not priority fees#

Three payment mechanisms get conflated constantly. They are genuinely different.

Base feePriority feeJito tip
Paid toBurned and validatorValidatorTip account, shared with validators
Denominated inLamports per signatureMicro-lamports per CULamports, flat
BuysNothing, mandatoryScheduling positionBundle auction position
Paid when you loseYes, if it landsYes, if it landsNo
Set byThe protocolComputeBudget instructionA transfer instruction

The fourth row is the economically interesting one. A priority fee is spent whether or not you win the race you were bidding for. A tip is only paid if the bundle lands. That changes optimal bidding behaviour: you can bid more aggressively on a tip because losing costs nothing, which is also why tip auctions clear high.

Do not put a tip instruction in a transaction you are not sending as a bundle. It becomes an unconditional transfer to a tip account with no auction attached, and you have simply given the money away. This mistake is more common than it should be.

Choosing between them#

You need a bundle when:

  • A partial execution of your sequence is unsafe. Liquidations, flash loans, atomic arbitrage.
  • You need to be adjacent to a specific transaction, before or after it.
  • You need ordering across several transactions that you control.
  • Paying only on success materially changes your economics.

You need staked delivery when:

  • Your transactions are individually valid and simply are not arriving.
  • Your losses do not correlate with fee, blockhash freshness or compute.
  • You are sending continuously and need consistency rather than a shot at a specific block.
  • You need to reach every leader, including those not running Jito.

Neither is your problem when:

  • Your blockhash handling is loose. Fix that first; it is free.
  • Your fee is priced off a constant rather than live per-account data.
  • You are requesting 1.4 million compute units by default.
  • You are polling an RPC to detect the events you react to.

That third list is not a rhetorical flourish. It is the most common actual answer, and both of the products on this page are more expensive than fixing it. Work through the diagnostic first.

Using both#

They compose, because they act at different layers. A realistic setup for a trading operation:

  • Bundles for anything requiring atomicity or adjacency, where losing the auction is an acceptable outcome because you pay nothing for it.
  • Staked delivery for the continuous flow of ordinary transactions, where you want consistent admission across every leader.

A common pattern is to attempt a bundle and fall back to a direct send when the auction is lost, accepting that the fallback has no atomicity. Whether that fallback is safe is a property of your strategy, not of the infrastructure, and it is worth thinking through carefully rather than assuming.

The cost comparison nobody does#

Comparing a per-send fee against a tip is comparing different things, and doing it properly needs expected values rather than sticker prices.

BundleStaked delivery
ChargedOnly on successPer accepted submission
Cost of losingZeroThe per-send price
Cost scales withCompetition for that blockVolume
PredictabilityLow, auctions are volatileHigh, a flat price

Which gives a rough rule:

  • High value, low frequency, atomicity required. Bundles. Paying only on success is worth a great deal when each attempt is individually valuable.
  • Lower value, high frequency, no atomicity required. Staked delivery. Predictable per-send cost, and you are not repeatedly bidding into an auction you will usually lose.

For a bot sending thousands of ordinary transactions a day, tip auctions become an expensive and unpredictable way to buy something you did not need. For a liquidator taking a handful of high-value shots, a flat per-send price is noise and atomicity is everything.

Where we stand#

We run a relay with staked connections. That is one of the two things on this page, so weigh the following accordingly.

Three things I would say if I had no stake in it:

  1. If you need atomicity, only a bundle will do. There is no substitute, and nothing we sell gets close. Do not let anyone talk you out of it on latency grounds.
  2. Most people asking this question have neither problem. They have a stale blockhash, a constant fee, or a polling loop. Both products are more expensive than fixing those, and neither will help until they are fixed.
  3. They are not substitutes. Anyone telling you that one replaces the other is selling something, including us if we ever say it.
The clean division: a bundle asks the block builder to include a set of transactions together. A staked connection asks the leader to read yours at all. Those are different questions, they are asked at different moments, and the right answer is frequently both.
Stop guessing at delivery.

swqos.com forwards your signed transactions to the leader over staked connections held open and kept warm. One prepaid balance, a flat price per send.

Get an API key
keep reading