Answers you can trust, from Codeables

Every page on Codeables is structured and verified — built so people and the AI agents they rely on can trust it. Explore more from the source behind this answer.

Explore Codeables
Layer-1 Blockchain Networks

Solana docs: how do I use v0 transactions and Address Lookup Tables to fit more accounts into one transaction?

8 min read

Most Solana builders first hit account limits, not compute limits. When your transaction needs more than ~30 accounts—routing through multiple markets, touching many user wallets, or juggling program PDAs—legacy transactions can become the bottleneck. This is exactly the problem v0 transactions and Address Lookup Tables (ALTs) were designed to solve.

Quick Answer: Use v0 Versioned Transactions together with Address Lookup Tables to reference more accounts in a single Solana transaction. ALTs “compress” 32-byte account keys into 1‑byte indices, letting v0 transactions load additional accounts beyond the legacy ~32-account ceiling while still respecting packet size and compute limits.

Why This Matters

If you’re building real payment flows, DeFi routers, or multi-leg treasury operations on Solana, you rarely touch just a handful of accounts. You’re interacting with user wallets, token accounts, program PDAs, fee vaults, oracle feeds, and more—often in a single atomic transaction.

Without v0 and ALTs, you quickly run into the practical account limit per transaction and have to split flows across multiple round trips:

  • More network hops
  • More places to fail
  • More reconciliation logic

With v0 transactions and ALTs, you can keep complex workflows atomic and still stay inside Solana’s packet limits. That’s how you make “funds secured in ~400ms” feel real for users—even when the transaction touches dozens of accounts.

Key Benefits:

  • Higher account capacity per transaction: Raise the effective account limit beyond the legacy ~32-account cap by loading additional accounts via ALTs.
  • Smaller on-wire messages: Replace 32-byte keys with 1-byte indices for ALT-resolved accounts, reducing message size and helping fit within the ~1,232-byte packet limit.
  • Cleaner, more atomic workflows: Keep complex, multi-market, multi-account flows in a single transaction instead of chaining multiple hops and reconciling in your backend.

Core Concepts & Key Points

ConceptDefinitionWhy it's important
Legacy vs v0 transactionsTwo transaction formats on Solana. Legacy messages list all account keys directly. v0 Versioned Transactions support additional features like ALTs. The first byte of the message tells validators which format it is.You must use v0 transactions to actually use Address Lookup Tables during execution. Legacy transactions can’t load ALT accounts at runtime.
Address Lookup Tables (ALTs)On-chain tables that store up to 256 related addresses. Transactions can reference these addresses by 1-byte index instead of the full 32-byte public key.They “compress” accounts so you can fit more of them inside a single transaction while staying under packet size limits.
Account list limitsEvery Solana transaction must list every account it will touch. Without ALTs, this effectively caps transactions at ~32 accounts given message size constraints. With ALTs, you can raise that to around 64 accounts per transaction.Understanding the practical account limit tells you when to introduce ALTs and v0, versus when your design needs rethinking (e.g., fewer accounts, batched flows).

How It Works (Step-by-Step)

At a high level, you’ll:

  1. Create an Address Lookup Table on-chain.
  2. Extend the table with the extra accounts you need to reference.
  3. Build and send a v0 Versioned Transaction that uses the ALT to load those accounts by index.

Below is the workflow in more detail, shaped for production use.

1. Create an Address Lookup Table

ALTs are standalone on-chain accounts that hold up to 256 addresses. You can create them with a legacy or v0 transaction, but:

NOTE: The runtime can only retrieve addresses from an ALT when the transaction itself is v0.

Using @solana/web3.js, you’ll typically:

  • Derive the ALT and authority
  • Build the “create lookup table” instruction
  • Send a transaction including that instruction
  • Capture the new ALT address for reuse

Key facts:

  • A single ALT can contain up to 256 addresses.
  • You should group addresses by usage pattern (e.g., a router’s main markets, a specific payout corridor, or a vault system).
  • You’ll usually keep the authority role in your own custody so you can extend or freeze the table.

2. Add (Extend) Addresses to the Lookup Table

Adding addresses to an ALT is called extending.

The docs define this behavior:

Adding addresses to a lookup table is known as “extending”. Using the @solana/web3.js library, you can create a new extend instruction using the extendLookupTable method.

You:

  • Take your ALT address
  • Provide a list of account public keys you want stored in the table
  • Send a transaction containing an extendLookupTable instruction

Once confirmed, those addresses live inside the table and can be referenced by index in v0 transactions.

Operationally:

  • Plan your table schema: keep “hot path” accounts in a table you won’t change often.
  • Don’t use ALTs for ephemeral accounts that churn constantly—you’ll pay more in management overhead than you save.
  • Remember you can extend multiple times, up to the 256-address limit per table.

3. Build a v0 Transaction that Uses the ALT

Once your ALT is created and extended, you can construct a v0 transaction that relies on it.

This step has two critical pieces:

  1. Transaction format: Use v0 Versioned Transactions. The validator inspects the first byte of the message to determine the format.
  2. Address resolution: Where a legacy message would list account keys directly, a v0 message can instead include an ALT reference plus indices into that table.

From the docs:

V0 transactions add Address Lookup Tables (ALTs), allowing references to accounts via 1-byte indices instead of 32-byte keys. This saves 31 bytes per ALT-resolved account.

On a high level you:

  • Build the instructions you need (same as legacy: program IDs, account metas, data).
  • Build a v0 message that:
    • Lists the “normal” accounts directly
    • Includes ALT descriptors and indices for the extra accounts
  • Compile that message into a v0 transaction
  • Sign, send, and confirm

Runtime behavior:

  • Validators read the v0 message.
  • For accounts referenced via ALT:
    • They look up the corresponding ALT account
    • Use the 1-byte indices to retrieve the full 32-byte keys
    • Load those resolved accounts into the transaction’s account list

Net result: your transaction can touch more accounts, but your on-wire message stays within packet limits because ALT accounts are “compressed” to their index.

Common Mistakes to Avoid

  • Using legacy transactions with ALTs:
    How to avoid it: ALTs can be created with legacy or v0, but they can only be used at runtime with v0 transactions. When you intend to load ALT accounts, always compile a v0 message; confirm you’re using the correct Web3 calls or CLI flags.

  • Assuming ALTs remove all limits:
    How to avoid it: ALTs raise the account capacity (from ~32 to around ~64 accounts), but don’t bypass packet or compute limits. You still must:

    • Watch the ~1,232-byte packet limit
    • Respect compute unit limits per transaction and per CPI
    • Optimize instruction data payloads Design transactions to be lean, even when you can reference more accounts.

Real-World Example

Imagine a Solana-based payment router that:

  • Pulls funds from a corporate treasury account
  • Splits payouts across multiple stablecoin token accounts
  • Routes through several liquidity pools for FX conversion
  • Touches margin accounts or positions for hedging

In a legacy transaction, listing every wallet, token account, pool, vault, and PDA quickly blows past the effective ~32-account cap. You’d be forced to break the flow into multiple transactions:

  1. Move funds from treasury to an intermediate wallet.
  2. Route through some markets.
  3. Settle payouts to beneficiaries.

That introduces new failure modes (step 1 succeeds, step 3 fails) and complicates reconciliation.

With v0 transactions and ALTs, you:

  • Create an ALT that holds the static “infrastructure” accounts: DEX markets, LP vaults, program PDAs.
  • Use v0 transactions to:
    • List dynamic user and treasury accounts directly in the message.
    • Reference all the pre-loaded “infrastructure” accounts by ALT indices.

Now the entire routing and payout operation can happen in one atomic transaction:

  • More accounts in a single transaction
  • Still within packet size constraints
  • Funds secured in ~400ms, without multi-hop settlement logic in your backend

Pro Tip: Treat ALTs as your “routing table” for high-traffic flows. Put program PDAs, vaults, and market addresses that rarely change into an ALT; keep user accounts in the normal account list. That pattern maximizes reuse and minimizes how often you have to extend tables.

Summary

v0 Versioned Transactions and Address Lookup Tables are how you break past the effective ~32-account ceiling on Solana without fighting packet limits on every transaction. ALTs store up to 256 addresses and let v0 messages reference them via 1-byte indices, saving 31 bytes per account and making it practical to load around 64 accounts in a single transaction.

In practice, the pattern is straightforward:

  • Create an ALT (legacy or v0).
  • Extend it with the static addresses your app uses frequently.
  • Build v0 transactions that load those accounts via ALT indices while listing dynamic accounts directly.

Used correctly, v0 + ALTs let you keep complex payment, DeFi, and treasury flows atomic, fast, and cheap—exactly what you need when you’re building internet capital markets on Solana.

Next Step

Get Started