Reducing Latency for Solana Bots
TL;DR
- - Colocation in the same data center as validators saves 10–50ms per transaction
- - Pre-compute everything possible before the opportunity arrives
- - Leader-aware routing sends directly to the current and next leader
In competitive Solana trading, every millisecond matters. A bot that detects an opportunity 10ms earlier and lands a transaction 10ms faster wins the arbitrage, liquidation, or snipe. This guide covers practical techniques to minimize latency at every layer.
Latency breakdown
A transaction’s lifecycle from event detection to confirmation:
| Stage | Typical latency | Optimized latency |
|---|---|---|
| Event detection (Geyser gRPC) | 5–20ms | 1–5ms |
| Decision logic | 5–50ms | <1ms |
| Transaction construction | 2–10ms | <1ms |
| Signing (Ed25519) | <1ms | <1ms |
| Network to leader (unstaked) | 20–100ms | 5–15ms |
| Network to leader (staked, colocated) | 5–15ms | 1–5ms |
| Total | 37–191ms | 8–27ms |
Colocation
Why it matters
Network latency between your bot and the validator leader is irreducible physics. Light through fiber travels at roughly 200km/ms. Running in a data center that hosts many Solana validators reduces this to near-zero.
Key data center regions
Major Solana validator concentrations (as of 2026-10-21):
- North America: multiple US data centers (NY, Chicago, Dallas, LA).
- Europe: Frankfurt, Amsterdam.
- Asia: Tokyo.
Choose a location with the highest concentration of high-stake validators, as these produce the most leader slots.
Bare metal vs. cloud
For lowest latency, bare metal servers outperform cloud VMs:
- No hypervisor overhead.
- Dedicated NIC (no shared networking).
- Consistent performance (no noisy neighbors).
Cloud VMs add 0.5–5ms of variable latency from virtualization and shared networking.
Connection optimization
Keep connections warm
Establishing a new TCP/TLS/QUIC connection adds 1–3 round trips (5–15ms). Reuse connections:
// Keep a persistent HTTP/2 connection
const agent = new https.Agent({
keepAlive: true,
maxSockets: 10,
});
// Reuse for all RPC calls
const response = await fetch(rpcUrl, {
agent,
method: "POST",
body: JSON.stringify(rpcRequest),
});
Pre-connect to upcoming leaders
Monitor the leader schedule and establish connections to the next 2–4 leaders before their slots begin:
const leaderSchedule = await connection.getSlotLeaders(currentSlot, 8);
for (const leader of leaderSchedule) {
preConnect(getTPUAddress(leader));
}
Pre-computation
Pre-build transaction templates
Construct transaction skeletons with all fixed fields. At execution time, fill only the variable data:
// Pre-built at startup
const template = buildSwapTransaction({
pool: poolAddress,
userAccounts: myAccounts,
program: dexProgram,
});
// At execution time (~0.1ms instead of ~5ms)
template.setAmount(computedAmount);
template.setBlockhash(latestBlockhash);
signer.sign(template);
Cache account data locally
Maintain an in-memory cache of frequently accessed accounts, updated via Geyser or WebSocket subscriptions:
const accountCache = new Map<string, AccountInfo>();
// Updated in real-time via Geyser
geyserStream.on("accountUpdate", (pubkey, info) => {
accountCache.set(pubkey, info);
});
// Decision logic reads from cache (0ms) instead of RPC (20ms+)
const poolState = accountCache.get(poolAddress);
Pre-compute blockhash
Keep a fresh blockhash ready:
let latestBlockhash = await connection.getLatestBlockhash();
// Refresh every 20 seconds (blockhash is valid for ~60–90 seconds)
setInterval(async () => {
latestBlockhash = await connection.getLatestBlockhash();
}, 20000);
Leader-aware routing
Direct TPU connection
Instead of sending through the RPC node (which adds a hop), connect directly to the leader’s TPU:
Standard: Bot → RPC → Leader TPU (2 hops, 20–40ms)
Direct: Bot → Leader TPU (1 hop, 5–15ms)
Multi-leader sending
Send to both the current and next leader for redundancy:
const leaders = await connection.getSlotLeaders(currentSlot, 2);
await Promise.all([
sendToTPU(leaders[0], signedTx),
sendToTPU(leaders[1], signedTx),
]);
Language and runtime
Rust vs. TypeScript
For latency-critical paths:
| Aspect | Rust | TypeScript |
|---|---|---|
| Decision logic | <0.1ms | 1–5ms |
| JSON parsing | <0.1ms | 0.5–2ms |
| Transaction construction | <0.1ms | 1–3ms |
| Ed25519 signing | ~0.05ms | ~0.1ms |
| GC pauses | None | 0–50ms |
Rust eliminates garbage collection pauses and provides predictable, low-latency execution. Many competitive bots use Rust for the hot path and TypeScript for management and monitoring.
Zero-allocation patterns
In Rust, avoid heap allocations in the hot path:
- Pre-allocate buffers for serialization.
- Use stack-allocated arrays for account lists.
- Reuse transaction buffers between iterations.
Measuring latency
Timestamps at every stage
const t0 = performance.now(); // Event received
// ... decision logic
const t1 = performance.now(); // Decision made
// ... transaction built
const t2 = performance.now(); // Transaction sent
// ... confirmation received
const t3 = performance.now(); // Confirmed
metrics.record({
decisionMs: t1 - t0,
buildMs: t2 - t1,
landingMs: t3 - t2,
totalMs: t3 - t0,
});
Track p50, p95, and p99 latencies. Optimize for p95 — consistent performance matters more than best-case speed.
FAQ
How much does colocation improve latency? Typically 10–50ms reduction, depending on your current distance from validators. From a residential connection, the improvement can be 50–100ms.
Is it worth using Rust instead of TypeScript? For competitive strategies (arbitrage, sniping), yes. Rust reduces decision and construction latency from 5–10ms to <1ms and eliminates GC pauses. For lower-frequency strategies, TypeScript is usually sufficient.
Can I reduce latency by running my own validator? Running a staked validator gives you direct SWQoS access and eliminates the RPC hop. However, it requires significant capital (staked SOL) and operational effort. A managed staked RPC connection provides most of the benefit.
What is the theoretical minimum latency? Physics limits: light through fiber at ~200km/ms. If you are in the same data center as the leader, network latency is <1ms. The practical minimum is roughly 5–10ms including computation and signing.
Updated: