Solana 的读取层,重建:Quicknode 的内存缓存内部
核心要点
- Solana's Read Layer, Rebuilt: Inside Quicknode's In-Memory Cache Quicknode rebuilt Solana's read layer in memory.

Solana's Read Layer, Rebuilt: Inside Quicknode's In-Memory Cache Quicknode rebuilt Solana's read layer in memory. getProgramAccounts, getLargestAccounts, and more run 10x to 1000x faster than stock Agave.
Quicknode May 5, 2026 — 13 min read
Solana developers hit roadblocks when using methods that return large amounts of data or require scanning the full account set. getProgramAccounts gets throttled or disabled. getLargestAccounts never returns. The root cause is structural. Agave RPC nodes are write-optimized systems, and throttling expensive read methods is a necessity, not a policy choice. Applications end up compensating with retry logic, caching layers, and polling intervals that exist purely to work around their blockchain provider’s infrastructure limitations.
While the broader ecosystem is now beginning to tackle this problem, Quicknode already built the read layer that Solana's ecosystem actually needs. Two years of iterative work, purpose-built in-memory architecture, and results that are 10x to over 1000x faster than Agave's defaults.
If you're a Quicknode customer, you don’t need to opt in to these benefits. Your endpoint delivers them already.
The Structural Problem with Solana's Read Layer
Agave RPC nodes are built to process transactions, reach consensus, and advance the ledger. The account state they maintain is a byproduct of that process, not a read-optimized store. There is no query planner, no native secondary indexes, and no separation between read and write I/O.
Hardware scaling does not resolve this. Read queries and consensus work compete for the same CPU on the same machine, so more hardware means paying validator-class costs (768 GB RAM, fast NVMe, high-bandwidth networking) without eliminating the contention.
Adding more RPC nodes compounds the problem: additional nodes add load to Solana's gossip and turbine networks, slowing state propagation for the validators that actually need it. Scaling the read layer through the validator architecture actively degrades the write layer.
Data pagination introduces a consistency risk. When new blocks land between pages, the account state underlying the response changes mid-read. Applications iterating through large result sets receive data that shifted before they finished reading it.
How Quicknode Built a Better Read Layer
Quicknode recognized this problem early, separating read workloads from the validator and serving them from purpose-built infrastructure. The architecture serving traffic today is the third iteration of those efforts. Each one moved closer to the data, stripping away abstraction layers that added latency without adding value, and the work is ongoing.
Iteration 1: Relational Databases
The first iteration followed the conventional approach: pipe account state and ledger data into a relational database, build indexes, and query against it. This immediately solved the resource contention problem. Validators could focus on consensus while a separate system handled reads. But relational databases carry overhead that matters at Solana's scale: query planning, row locking, managing Write-Ahead Logging, autovacuum, and the inherent latency of disk-backed storage. For a blockchain producing blocks every 400 milliseconds, every microsecond of read latency compounds across millions of daily requests. As Solana traffic scaled, disk I/O became the next limit to clear.
Iteration 2: Specialized High-Performance Databases
The next iteration started with the schema itself. The team simplified and denormalized the data model to match Solana's actual access patterns, dropping the relational shape that no longer paid for itself. That reshape unlocked a move to a high-performance NoSQL database built for write-heavy ingestion and low-latency point reads, without the query planning, row locking, and write-ahead overhead that came with the relational approach.
Both throughput and latency improved noticeably, and the operational headaches that came with running a relational system at scale (autovacuum stalls, lock contention spikes, WAL bloat) disappeared.
Iteration 3: Fully In-Memory Architecture
The motivation for the next move was different. Disk-backed systems, no matter how well-tuned, share a hard ceiling: every read eventually touches a storage medium that is orders of magnitude slower than RAM. To push past it, the read path itself had to leave the disk behind.
The current architecture eliminates disk from the read path entirely. AccountsDB state lives in memory, indexed by hand-crafted data structures purpose-built for Solana's specific query patterns. There is no query planner, no B-tree traversal, no page cache miss: just direct memory access to pre-indexed data.
The shift to a fully in-memory architecture was a deliberate decision to optimize for a single objective: raw read performance.
The LedgerDB (stores the historical record of every slot's blocks, transactions, and metadata) cache follows the same design philosophy with a different storage strategy. Solana's ledger is too large to fit entirely in memory, so it uses a tiered design: tip-of-chain data stays hot in memory, and historical data is served from a high-performance distributed database tuned for that workload.
How It Works: Quicknode's In-Memory Cache
Quicknode's Solana Cache is a single self-contained binary that serves every tip-of-chain method with no external dependencies. Only historical ledger queries reach into an external database.
The AccountsDB (stores the current state of every account) cache is fully in-memory, and the design choices that make it fast are not incidental. Four mechanisms work together to eliminate every avoidable source of latency on the read and write paths.
Ahead of the Chain
Data freshness is a performance property, and it begins before any read request arrives. The cache ingests directly from a shred-stream data source, receiving account updates 200-400 ms earlier than they would surface on a typical Agave RPC node that waits for fully formed blocks. Those updates land through a low-latency write path (in-memory writes with a near lock-free design) so the head start is preserved end-to-end rather than absorbed by ingestion overhead.
The combined effect is measurable at tip: under production traffic, the cache's latest observable slot runs consistently 1-2 slots ahead of a comparably configured Agave RPC node. For workloads where the question is 'what is the state right now' for trading systems, MEV, liquidation engines, and real-time dashboards, this is the difference between acting on live state and acting on data that is already stale.
Custom Data Structures
The indexes that power account lookups, token queries, and program account filtering are built from low-level data structures chosen by benchmark, not the most general choice, but the one that measured fastest for the access patterns the system actually sees. Shared state uses minimal locking wherever possible, keeping concurrent readers out of each other’s way.
Tuned for the Hardware
The system goes deep on hardware utilization by pinning ingestion, indexing, and query serving to dedicated CPU cores to minimize context-switch overhead, and selecting memory allocators per-component based on their specific allocation profiles to reduce fragmentation under load.
Pre-Computation
Where possible, the system pre-computes and maintains derived views as account state is ingested: supply aggregates, sorted account lists, filtered program caches. This shifts CPU cost from the latency-sensitive read path to the throughput-oriented write path. Queries never trigger computation. They read results that are already there. The 17ms getSupply response in the benchmarks is this mechanism in practice: the aggregate already exists when the query arrives.
getProgramAccounts: The Hardest Problem
getProgramAccounts does a simple-sounding task: return all accounts owned by this program that match these filters. The challenge is that indexing it well is hard. The program could be any of thousands of deployed programs, each with its own account schema.
The filters are typically memcmp operations at specific byte offsets, offsets that only make sense if the program's internal data layout is known. A memcmp at offset 32 means one thing in SPL Token and something entirely different in a DEX program.
There is no universal indexing strategy that works for all of them. Indexing getProgramAccounts efficiently requires understanding what each program's accounts look like. Quicknode's indexer addresses this with two strategies working together:
Natively Indexed Programs
For a small set of high-traffic, well-understood programs, Quicknode builds and maintains dedicated native indexes continuously as accounts update. These are the programs that dominate Solana traffic: SPL Token (legacy), SPL Token-2022, and the Stake program.
