Alternatives to getProgramAccounts
TL;DR
- - getProgramAccounts scans the entire account set — it's inherently expensive
- - Use Geyser gRPC streams to maintain your own index of accounts
- - Use memcmp filters and dataSlice to reduce payload when GPA is unavoidable
getProgramAccounts (GPA) scans every account owned by a given program. For popular programs like the SPL Token Program (millions of accounts), this scan is extremely expensive. Many RPC providers disable it on free tiers, time it out on paid tiers, or charge extra compute units for it.
Why GPA is expensive
When you call getProgramAccounts:
- The RPC node iterates over all accounts in its database.
- It filters by program owner (and any
memcmp/dataSizefilters you provide). - It serializes matching accounts into the response.
- It sends the entire result set back to you.
For a program with millions of accounts, this can take 10–60+ seconds and produce responses of hundreds of megabytes. During this time, the RPC node is under heavy load.
Alternatives
1. Geyser gRPC (Yellowstone)
Geyser plugins stream account updates in real time. Instead of scanning all accounts periodically, subscribe to updates for a specific program and maintain your own local index:
// Subscribe to all accounts owned by a program
const stream = client.subscribe({
accounts: {
myFilter: {
owner: ["TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"],
},
},
});
for await (const update of stream) {
// Update your local database
await db.upsert(update.account.pubkey, update.account.data);
}
Advantages:
- Real-time updates (milliseconds, not seconds).
- No scanning — only changed accounts are sent.
- Build your own indexes for custom queries.
2. getMultipleAccounts with known addresses
If you already know which accounts you need (from a PDA derivation or a stored list), fetch them directly:
const accounts = await connection.getMultipleAccountsInfo(
knownAddresses // up to 100 per call
);
This is orders of magnitude faster than GPA because the RPC node looks up specific addresses instead of scanning.
3. Use memcmp and dataSlice filters
When GPA is unavoidable, minimize the cost:
const accounts = await connection.getProgramAccounts(programId, {
filters: [
{ dataSize: 165 }, // Only accounts of exactly this size
{
memcmp: {
offset: 32, // Byte offset of the field to match
bytes: ownerPublicKey.toBase58(),
},
},
],
dataSlice: {
offset: 0,
length: 64, // Only fetch the first 64 bytes
},
});
dataSizeeliminates accounts of the wrong type before reading data.memcmpfilters by field values server-side.dataSlicereduces the payload by fetching only the bytes you need.
4. On-chain indexing programs
Some protocols maintain index accounts that store lists of related accounts. Instead of scanning all accounts, read the index account to get the addresses, then fetch them with getMultipleAccounts.
5. Off-chain indexing services
Several services maintain indexed databases of Solana account data:
- DAS API (available from multiple providers) for token and NFT accounts.
- Custom indexers built on Geyser plugins that write to PostgreSQL, ClickHouse, or similar databases.
- Warehouse services that maintain historical snapshots of program accounts.
These provide SQL-like query capabilities that are impossible with raw RPC calls.
Decision matrix
| Approach | Real-time | Historical | Setup effort | Cost |
|---|---|---|---|---|
| GPA with filters | No (polling) | Current only | None | High per call |
| Geyser gRPC | Yes | No | Medium | Subscription |
| getMultipleAccounts | No | Current only | Need address list | Low |
| Custom indexer | Yes | Yes | High | Infrastructure |
| Off-chain service | Near real-time | Often yes | None | Subscription |
Migrating from GPA polling
If your application currently polls GPA every N seconds:
- Start a Geyser subscription for the program.
- Do one initial GPA to get the current state.
- Apply streaming updates on top of the initial snapshot.
- Remove the GPA polling loop.
This pattern gives you real-time data with lower infrastructure cost than repeated GPA calls.
FAQ
Why do some providers disable GPA? A single GPA call can consume more resources than thousands of regular RPC calls. Providers disable or restrict it to protect their infrastructure from overload.
Can I use GPA on a dedicated node? Yes. On a dedicated node you control the rate limits. GPA is still slow, but you will not be rate-limited or timed out by the provider.
Is there a way to get notified when a new account is created for a program? Yes. Geyser gRPC subscriptions include account creation events. When a new account is created and assigned to a program, the subscription fires with the new account data.
How much does a Geyser subscription cost? Pricing varies by provider. Geyser gRPC is typically available on dedicated node plans or as an add-on to higher-tier RPC plans. Check individual provider pricing.
Updated: