MEV

How to Send Jito Bundles on Solana: Atomic Transactions Explained (2026 Guide)

July 4, 2026AllenHark Team

How to Send Jito Bundles on Solana: Atomic Transactions Explained

You buy on one DEX and sell on another. The buy lands. The sell doesn't. You're now holding a bag you never wanted, and the "arbitrage" just became a directional bet.

This is the problem Jito bundles exist to solve. A bundle is a group of up to five Solana transactions that execute atomically and in order — either all of them land in the same block, exactly in the sequence you submitted, or none of them touch the chain at all. No partial fills, no stranded legs, no cleanup transactions.

This guide covers what bundles actually are, how the Jito Block Engine and its tip auction work under the hood, and how to submit bundles in practice — including full request examples over HTTPS, QUIC, and WebSocket via AllenHark Relay.

What Is a Jito Bundle?

Roughly 80%+ of Solana stake runs Jito-Solana, a validator client fork that adds an out-of-protocol blockspace auction. Alongside normal transaction processing, a Jito validator accepts bundles from the Jito Block Engine and executes them with three guarantees regular transactions never get:

  1. Atomicity — all transactions in the bundle land, or none do. If any transaction in the bundle reverts, the whole bundle is discarded.
  2. Ordering — transactions execute in exactly the order you placed them in the bundle.
  3. Contiguity — nothing else executes in between your transactions.

That combination is impossible to replicate with individual transactions, no matter how fast you submit them. Five transactions sent back-to-back through the fastest pipe in the world can still be reordered, interleaved with other traffic, or partially dropped. A bundle cannot. (New to the concept? Our earlier primer, Understanding Jito Bundles & Block Building, covers the background.)

When you actually need bundles

  • Multi-leg arbitrage — buy leg and sell leg must both land or neither. The classic case.
  • Backrunning — your transaction must execute immediately after a target transaction, with nothing in between.
  • Atomic setup + action + cleanup — create an account, use it, close it, in one indivisible unit.
  • Launch sniping with guards — pair the buy with a check transaction that reverts (killing the whole bundle) if conditions moved against you.
  • Liquidations — seize collateral and hedge it in the same block.

If a lone transaction failing just costs you a fee retry, you don't need a bundle. If a partially executed sequence costs you real money, you do.

How the Block Engine and Tip Auction Work

Bundles don't go through Solana's normal gossip path. They go to the Jito Block Engine — a service that collects bundles from searchers, simulates them, runs a sealed-bid auction per block, and forwards winners to the current leader (when that leader runs Jito-Solana).

Your bid in that auction is the Jito tip: a plain SOL transfer to one of Jito's eight tip accounts, included in one of your bundle's transactions. The protocol minimum is 1,000 lamports, but the tip is a bid, not a fee — when several bundles touch the same accounts, the highest tipper wins the spot. In quiet markets a few thousand lamports lands fine; in a contested launch or a fat arbitrage window, winning bids run to hundreds of thousands of lamports or more, priced against the profit at stake.

Two mechanics worth internalizing:

  • Accepted ≠ landed. The Block Engine accepting your bundle means you're in the auction, not in the block. If the current leaders aren't Jito-enabled, or you're outbid, the bundle sits pending until its blockhash expires (~60 seconds), then dies silently.
  • Put the tip last. If your tip transfer is the first transaction, the rest of the bundle can revert after your tip already paid out its value to the auction — you paid to land a failure. Tip in the last transaction (or last instruction) means you only pay when the whole bundle succeeds.

Sending a Bundle: The Practical Part

You can talk to the Block Engine's JSON-RPC directly, but then region selection, endpoint health, rate limits (5 requests/second per IP without a key), and status polling are all your problem. AllenHark Relay wraps all of that: it validates your bundle before submission (so you find out about a missing tip in milliseconds, not via a silent 60-second death), picks the lowest-latency regional block engine automatically, submits, and returns Jito's own bundle id for tracking.

All examples below assume up-to-5 fully signed, base64-encoded transactions sharing a fresh recent blockhash.

Option 1: HTTPS — POST /v1/sendBundle

Simplest integration, works everywhere:

curl -X POST "https://relay.allenhark.com/v1/sendBundle?api-key=YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "txs": ["BASE64_TX_1", "BASE64_TX_2"],
    "id": "arb-1234"
  }'

Response:

{
  "status": "accepted",
  "bundle_id": "c9a8f2e1-7b3d-4e2a-9f1c-8d6e5a4b3c2d",
  "signatures": ["5wH...buyLeg", "3kP...sellLeg"],
  "id": "arb-1234"
}

That bundle_id is the Jito Block Engine's id — you can feed it straight into Jito's getBundleStatuses to watch for landing.

Option 2: QUIC — for latency-sensitive systems

Same persistent-connection protocol as single transactions (one bidirectional stream per request): write the api-key: YOUR_KEY\n header line, then the JSON frame — the only difference from a single transaction is txs instead of tx:

{"txs": ["BASE64_TX_1", "BASE64_TX_2"], "id": "arb-1234"}

Close the write side, read the identical JSON response, keep the connection for the next bundle. QUIC skips the per-request TLS handshake entirely — dispatch is sub-millisecond from co-located infrastructure.

Option 3: WebSocket — persistent and browser-friendly

Connect once to wss://fra.relay.allenhark.com/v1/stream/bundle (or ams/ny/tyo), then stream frames:

const ws = new WebSocket(
  "wss://fra.relay.allenhark.com/v1/stream/bundle?api-key=YOUR_KEY"
);

ws.onopen = () => {
  ws.send(JSON.stringify({
    id: "arb-1234",
    txs: [BASE64_TX_1, BASE64_TX_2],
  }));
};

ws.onmessage = (e) => {
  const r = JSON.parse(e.data);
  if (r.status === "accepted") {
    console.log("in the auction:", r.bundle_id);
  } else {
    console.error("rejected:", r.error);
  }
};

Replies can arrive out of order — correlate by id.

The Two-Tip Checklist

The most common reason a first bundle gets rejected: tips. Through AllenHark Relay a bundle needs two separate SOL transfers, in any of its transactions:

TipMinimumWho paysPurpose
Jito tip → one of Jito's 8 tip accounts1,000 lamports (realistically 10k+)Everyone, alwaysYour bid in the Block Engine auction
Relay tip → an AllenHark tip wallet0.001 SOLEveryone except dedicated subscribersRelay usage, one transfer covers the whole bundle

Both must be plain SystemProgram transfers with statically verifiable destinations — no hiding tips behind address lookup tables. The relay validates both before submission and rejects instantly with a readable error ("No transfer to a Jito tip account found in bundle") rather than letting a doomed bundle silently expire. Dedicated relay customers with whitelisted signers skip the relay tip but still need the Jito tip — the Block Engine, not the relay, enforces that one.

Tracking Outcomes (and Reading Failures Correctly)

After acceptance, a bundle resolves to one of four outcomes:

  • Landed — all transactions on-chain, atomically. Confirm any returned signature, or query getBundleStatuses with the bundle id for the landing slot.
  • Failed — a transaction in the bundle reverted during atomic execution, so the whole bundle was dropped. Fix the failing leg.
  • Invalid — the bundle never entered the auction (malformed, tip issue at the engine).
  • Expired — the blockhash aged out while pending. This is the one that confuses people: it usually means the slot leaders during your window weren't Jito-enabled, or you were outbid. Nothing is wrong with your code — re-sign with a fresh blockhash, consider a higher tip, and resubmit. Resubmission is safe: bundle ids derive from transaction signatures, and on-chain signature dedup makes execution at-most-once.

Best Practices

  1. Fresh blockhash, always — grab it immediately before signing. A bundle built on a stale blockhash burns most of its 60-second auction window before it starts.
  2. Tip last, not first — only pay Jito when the whole bundle succeeds.
  3. Rotate tip accounts — pick randomly among the 8; it avoids write-lock contention on a single hot account across the network.
  4. Size the Jito tip to the opportunity — 1,000 lamports is a floor, not a strategy. Bid a fraction of expected profit.
  5. Keep bundles small — 2–3 transactions beat 5 in the auction; simulation cost and revert probability grow with every leg.
  6. Handle expired as routine, not error — non-Jito leaders take ~1 in 5 slots. Build resubmission into the loop.
  7. Use QUIC or WebSocket for repeated submission — auction timing is a latency game; don't pay a TLS handshake per bundle.

Bundles vs. Single Fast Transactions

Bundles are not "better transactions" — they're a different tool. A single transaction through AllenHark Relay's 5-channel broadcast (stake-weighted QUIC, direct-to-leader TPU, UDP, RPC fan-out, block-engine forward) typically lands faster than a bundle, because it doesn't wait for an auction and lands on every leader, Jito or not. Reach for a bundle when you need atomicity or ordering; reach for a fast single transaction when you just need speed.

Single tx via relayJito bundle
Atomic multi-tx✓ (up to 5)
Guaranteed ordering
Lands on non-Jito leaders✓ (all leaders)✗ (~80% of slots)
Extra cost0.001 SOL relay tip+ Jito tip (auction bid)
Typical useSwaps, snipes, transfersArbitrage, backruns, atomic sequences

Start Sending Bundles

Bundle submission is live on all AllenHark Relay regions — Frankfurt, Amsterdam, New York, and Tokyo — over HTTPS, QUIC, and WebSocket, with no gRPC client or Jito authentication key required on your side.

Questions about bundle strategies or landing rates? Talk to us — we run this infrastructure all day, every day.