solana-test-validator
Run solana-test-validator to get a single-node Solana cluster with JSON-RPC, faucet, and BPF program execution on localhost.
Recipe
Quick-reference recipe card - copy-paste ready.
solana-test-validator
solana-test-validator --reset
solana-test-validator --bpf-program <PROGRAM_ID> target/deploy/my_program.soWhen to reach for this:
- Default backend for
anchor test. - Manual client testing against fresh state.
- Loading custom programs without public devnet deploy.
- Cloning select mainnet accounts for realistic CPI tests.
Working Example
# Terminal 1: validator with your program preloaded
solana-test-validator --reset \
--bpf-program "$(solana-keygen pubkey target/deploy/my_program-keypair.json)" \
target/deploy/my_program.so
# Terminal 2: CLI + tests
solana config set --url http://127.0.0.1:8899
solana airdrop 5
anchor test --skip-local-validator # if validator already runningWhat this demonstrates:
--resetwipes ledger for deterministic runs.--bpf-programregisters bytecode at a fixed program ID at genesis.- Port 8899 serves RPC; 8900 is common for gossip/WebSocket.
Deep Dive
How It Works
- Embeds Agave validator logic tuned for developer speed (shorter epochs, relaxed limits).
- Mines blocks locally with your transactions immediately included.
- Faucet mints SOL without rate limits.
- Ledger stored under
test-ledger/by default unless--ledgeroverrides.
Useful Flags
| Flag | Effect |
|---|---|
--reset | Delete existing ledger |
--ledger <PATH> | Persistent state directory |
--clone <PUBKEY> | Copy account from --url at start |
--bpf-program <ID> <SO> | Preload program binary |
--url <CLUSTER> | Source for clones |
bash Notes
# Quiet logs for CI
solana-test-validator --quiet --reset
# Bind custom RPC port
solana-test-validator --rpc-port 18899Gotchas
- Forgotten --reset - stale state causes flaky tests. Fix: reset in CI always; document ledger path for persistent experiments.
- Port already in use - prior validator still running. Fix:
pkill solana-test-validatoror change--rpc-port. - Clone without mainnet URL - empty account at startup. Fix: pass
--url mainnet-betawith--clone. - Program ID mismatch -
--bpf-programID must match clientdeclare_id!. Fix: use keypair pubkey fromtarget/deploy. - Assuming WebSocket on same port - some setups need explicit WS URL. Fix: check
solana logsconnection errors.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
| Surfpool 0.12.0 | Mainnet-fork simulation | Minimal zero-dependency local tests |
| LiteSVM 0.6.x | Sub-second unit tests | Full RPC client integration |
| devnet | Shared staging environment | Fast inner dev loop |
anchor test embedded validator | One-command tests | Long-running manual session |
FAQs
What ports does test-validator use?
Default RPC 8899, gossip 8900, faucet 9900 - configurable via flags.
Can I persist ledger between restarts?
Yes - omit --reset and reuse --ledger path; beware state drift in tests.
How do I preload SPL programs?
Clone Token program IDs or use --bpf-program with known program pubkeys.
Does it support versioned transactions?
Yes - matches Agave 4.1.1 features including v0 transactions and ALTs when enabled in cluster features.
How many clones are practical?
Start with tens, not thousands - each clone adds startup RPC fetch time.
Can Docker run test-validator?
Yes for CI - expose port 8899 to test containers.
Why is slot time different from mainnet?
Test validator tunes slot timing for developer throughput, not production consensus timing.
How do I stop gracefully?
Ctrl+C in terminal; ensure no orphaned processes hold port 8899.
Does anchor test start its own validator?
By default yes - use --skip-local-validator when you manage validator manually.
Can I run multiple validators?
Yes on different --rpc-port values for parallel CI shards.
Related
- Local Dev Basics - dev loop overview
- Cloning Mainnet Accounts - realistic state
- Loading Programs & Fixtures - preload patterns
- Surfpool - fork-based alternative
Stack versions: This page was written for Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, anchor-lang 0.32.1, Rust 1.91.1, @solana/kit 7.0.0, Surfpool 0.12.0, and LiteSVM 0.6.x.