getBlockProduction — Solana RPC Method
getBlockProduction returns block production statistics, showing how many leader slots each validator was assigned and how many blocks they actually produced. This data is essential for evaluating validator performance and the network skip rate.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
commitment | string | No | processed, confirmed, or finalized. Default: finalized. |
identity | string | No | Filter results to a single validator identity (base-58 public key). |
range | object | No | {firstSlot: u64, lastSlot?: u64}. If omitted, covers the current epoch. lastSlot defaults to the highest available slot. |
Request
curl -X POST https://api.mainnet-beta.solana.com \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getBlockProduction",
"params": []
}'
TypeScript (@solana/kit)
import { createSolanaRpc } from "@solana/kit";
const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");
const production = await rpc.getBlockProduction().send();
for (const [identity, [leaderSlots, blocksProduced]] of Object.entries(
production.value.byIdentity
)) {
const skipRate = ((leaderSlots - blocksProduced) / leaderSlots) * 100;
console.log(`${identity}: ${blocksProduced}/${leaderSlots} (${skipRate.toFixed(1)}% skip)`);
}
Response
{
"jsonrpc": "2.0",
"result": {
"context": { "slot": 341200000, "apiVersion": "2.2.4" },
"value": {
"byIdentity": {
"85iYT5RuzRTDgjyRa3cP8SYhM2j21fj7NhfJ3peu1DPr": [48, 47],
"dv4ACNkpYPcE3aKmYDqZm9G5EB3J4MRoeE7WNDRBVJB": [36, 36]
},
"range": {
"firstSlot": 341100000,
"lastSlot": 341200000
}
}
},
"id": 1
}
| Field | Type | Description |
|---|---|---|
byIdentity | object | Map of validator identity → [leaderSlots, blocksProduced]. Each value is a two-element array. |
range.firstSlot | u64 | First slot of the range (inclusive). |
range.lastSlot | u64 | Last slot of the range (inclusive). |
Understanding the data
For each validator, the two-element array [leaderSlots, blocksProduced] tells you:
- leaderSlots: how many slots the validator was scheduled to lead.
- blocksProduced: how many blocks the validator actually produced.
The difference leaderSlots - blocksProduced is the number of skipped slots. A validator’s skip rate is (leaderSlots - blocksProduced) / leaderSlots.
Common errors
- Invalid range —
firstSlotmust be less than or equal tolastSlot. Setting a range outside the node’s available ledger data returns empty results. - Invalid identity — a malformed public key returns a parse error.
Performance
Without the identity filter, the response includes every validator in the cluster (1,500+ on mainnet). This can produce a large response. Use the identity filter when you only need data for a specific validator. The range parameter limits the slot window and reduces computation.
FAQ
How do I calculate the network skip rate?
Sum all leaderSlots and all blocksProduced across all validators, then compute (totalLeaderSlots - totalBlocksProduced) / totalLeaderSlots. Mainnet typically has a skip rate between 3-8%.
How often should I call this method? Block production stats change slowly. Polling once per minute is sufficient for monitoring dashboards. For per-epoch summaries, call once at the end of each epoch.
Can I query historical epochs?
Yes, by setting the range parameter. However, the node must still have ledger data for those slots. Most non-archival nodes only keep the last 2 epochs.
What is a good skip rate for a validator? A healthy validator typically has a skip rate under 5%. Skip rates above 10% may indicate performance issues, poor network connectivity, or insufficient hardware.
Parameters
| Parameter | Type | Required | Description | Default |
|---|---|---|---|---|
commitment | string | No | Commitment level: processed, confirmed, or finalized. | finalized |
identity | string | No | Only return results for this validator identity (base-58 public key). | — |
range | object | No | Slot range: {firstSlot: u64, lastSlot?: u64}. Defaults to the current epoch. | — |
Updated: