getMultipleAccounts Solana Developer Guide
In this developer guide, we'll learn to batch up to 255 Solana account reads into a single request, handle missing accounts safely, and cut bandwidth usage with dataSlice — with measured before/after data to show how much you can save.
Reference documentation: getMultipleAccounts
Before We Begin
Once you have mastered getAccountInfo, the next step is to learn getMultipleAccounts. On FluxRPC, this RPC call allows you to fetch up to 255 accounts with one request. You will need a FluxRPC API key to complete all the steps in this guide — our free keys are sufficient.
There is no need to copy-paste it — just navigate back to this page while logged in, and we will automatically use the key you select.
In this guide, we will accomplish the following:
- Fetch the data for multiple accounts on the Solana blockchain
- Deal with missing data
- Optimize the request with dataSlice, and measure what we saved
We will provide examples in Python, TypeScript, Go, and cURL.
Why Read from Multiple Solana Accounts at Once?
Using getMultipleAccounts instead of many getAccountInfo requests is the first optimization a new Solana developer should consider. It is very straightforward.
Due to network latency, it takes time for your RPC request to reach our servers, and the response to return to you (this is called round-trip latency).
The processing time for us to actually serve your request is around 5 milliseconds for getAccountInfo, and 10-15 milliseconds for getMultipleAccounts. You can see those performance metrics live on the FluxRPC performance tracking page.
This means that a significant amount of the time you spend waiting for a response is due to round-trip network latency. The easiest optimization to apply here is to batch requests — instead of asking for accounts one at a time, you ask for many accounts at once, so the overhead per piece of information you receive is smaller.
Also, when you make a getAccountInfo request, the response is JSON, which has some bandwidth overhead. Using getMultipleAccounts will save bandwidth, because this overhead only has to be paid once for multiple pieces of information. Since FluxRPC charges based on the bandwidth you use, this is not just about making your application faster — it means lower fees for you.
How to Use getMultipleAccounts
A getMultipleAccounts RPC call is structured very similarly to getAccountInfo. The only difference worth noting is that you request an array of public keys, instead of a single public key.
The response is also similar, although again, you will receive an array instead of a single item.
curl "https://eu.fluxrpc.com?key=<Your-API-Key>" -s -X POST \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getMultipleAccounts",
"params": [
[
"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"Czfq3xZZDmsdGdUyrNLtRhGc47cXcZtLG4crryfu44zE",
"HZ1JovNiVvGrGNiiYvEozEVgZ58xaU3RKwX8eACQBCt3",
"65ZHSArs5XxPseKQbB1B4r16vDxMWnCxHMzogDAqiDUc",
"51FQwjrvo8J8zXUaKyAznJ5NYpoiTCuqAqCu3HAMB9NZ"
],
{
"encoding": "base64"
}
]
}'
Encoding
Similar to getAccountInfo, in production you should use base64 encoding to save bandwidth. Setting base58 or jsonParsed is mostly useful during development.
Further Optimizations
When discussing getAccountInfo, we mentioned that many RPC calls are really just convenience functions built on top of getAccountInfo, getMultipleAccounts, and sometimes getProgramAccounts.
Specifically, we gave an example of how we could implement getTokenAccountBalance using getAccountInfo and some parsing. However, there is no "getMultipleTokenAccountBalances" RPC call — but we could build one that's more efficient than making multiple getTokenAccountBalance calls.
To do that, we'll introduce a new parameter, dataSlice. This returns only a byte slice of an account's data. The savings for using this with getAccountInfo are generally minimal, but when fetching many accounts at once, they begin to matter.
Let's say for example, I want to return the balance of 11 USDC accounts. I already know the mint decimals for USDC is 6, and I know that in the ATA account model, the token amount is stored at byte positions 64-72 (a uint64). We can do something like this:
Why is there a bad public key in the array?
I've sneakily added an invalid public key to the array so we get to handle the missing-account case for real, instead of pretending it never happens. Nye he he.
import requests
import json
import base64
APIKey = "<Your-API-Key>"
RPCRegion = "eu"
AccountPubKeys = [
"3emsAVdmGKERbHjmGfQ6oZ1e35dkf5iYcS6U4CPKFVaa",
"7KJjY7rArbydeLBF7gQ5LdqXRKRYyPArT99NEctsHsgU",
"DT78gNBH7enTRrAFcag4PAuQbSeemstmtj888w8pkvdf",
"9piy5wGy8v1gpnGXigfmbssBgCuv2X6VKrACT5owmFVo",
"Cp8wjBC7MVWeMeawTdyPzPdH7ThpBq1vRdBKtVRVTW2B",
"FSxJ85FXVsXSr51SeWf9ciJWTcRnqKFSmBgRDeL3KyWw",
"BmkUoKMFYBxNSzWXyrjyMJjMAaVz4d8ZnxwwmhDCdXFB",
"WzWUoCmtVv7eqAbU3BfKPU3fhLP6CXR8NCJH78UK9VS",
"4XgV4PgJsLEL1TrbTvKDxg1njoZuKouFHur4WAcWTt3o",
"6xTBTqJMBr5m7BKqVxmW2x11DfqUwtD3TJsqpxELx72L",
"BmkUoKMFYBxNSzWXyUjyMJjMAaVz4d8ZnxwwmhDCUXFB",
]
def fetchAccounts(pubKeys):
headers = {'content-type': 'application/json'}
url = "https://" + RPCRegion + ".fluxrpc.com?key=" + APIKey
data = {
"jsonrpc": "2.0",
"id": 1,
"method": "getMultipleAccounts",
"params": [
pubKeys,
{
"encoding": "base64",
# Only return the 8 bytes that hold the token amount
"dataSlice": {"offset": 64, "length": 8}
}
]
}
response = requests.post(url, data=json.dumps(data), headers=headers)
return response
response = fetchAccounts(AccountPubKeys)
if response.status_code != 200:
# Handle HTTP errors from the RPC.
raise Exception("RPC returned HTTP error code " + str(response.status_code))
responseJSON = json.loads(response.text)
# The value field contains our array of account data, so we can iterate through it.
# Enumeration lets us match any errors back to the public key in our request.
for count, account in enumerate(responseJSON["result"]["value"]):
if account is None:
print("Account " + str(AccountPubKeys[count]) + " doesn't exist on-chain!")
continue # You could raise an error and halt, but here we just keep going.
# The byte slice happened server-side, so there is no slicing to do here.
amountBytes = base64.b64decode(account["data"][0])
amount = int.from_bytes(amountBytes, byteorder='little') # Byte format is little-endian
# We happen to know these are USDC accounts, and USDC has 6 decimals.
UI_balance = amount / 1000000
print("Account " + str(AccountPubKeys[count]) + " has a USDC balance of: " + str(UI_balance))
You'll notice that we catch the one public key that doesn't exist. In the result for getMultipleAccounts, accounts that don't exist return a null entry in the array.
The index of results is ordered the same as the array of public keys in your request, so you know which public key was invalid. In the code example, we catch and print out this case.
We've successfully retrieved the token balance of multiple USDC accounts, with the latency of a single RPC call instead of multiple calls, and a total bandwidth cost lower than making multiple getTokenAccountBalance calls.
What the Optimization Actually Saved
At the time of writing (and dropping the invalid public key from the benchmark), here is what each approach costs in response bandwidth for 10 USDC token accounts:
| Approach | Bandwidth | Requests |
|---|---|---|
getMultipleAccounts with dataSlice | 1838 bytes | 1 |
getMultipleAccounts without dataSlice | 3918 bytes | 1 |
| 10 × getTokenAccountBalance | 2010 bytes | 10 |
So without the slicing optimization, getTokenAccountBalance is actually cheaper than getMultipleAccounts. With it, we save about 9% bandwidth on top of being several times faster.
This might not seem like much, but opportunities for this kind of optimization exist everywhere on Solana. As we charge per byte of bandwidth on FluxRPC, the sum of all these optimizations results in your application being cheaper, faster, and better in every way.
Optimizing Further with Lantern
Lantern can answer getMultipleAccounts calls locally. This is faster, there's no rate limit, and the bandwidth savings are typically much (much, much) higher than the example above. If you're making getMultipleAccounts calls to accounts owned by one or just a few programs, you can really speed up your application with Lantern, while saving costs.
Serving thousands of getMultipleAccounts requests locally per second is not too difficult to achieve. This would cost thousands of dollars per month at any competing RPC, but an affordable FluxRPC Developer plan is sufficient to get started with Lantern.
Next Steps
If you haven't yet, read the getAccountInfo guide — it covers the response fields, encoding trade-offs, and account data parsing that this guide builds on.