Slots, Blocks & Epochs
Solana organizes time into slots (production windows), blocks (confirmed transaction batches), and epochs (stake schedule periods). These units drive leader rotation, staking rewards, and client confirmation timing.
Recipe
Quick-reference recipe card - copy-paste ready.
solana slot
solana epoch
solana epoch-info
solana block-time $(solana slot)import { createSolanaRpc } from "@solana/kit";
const rpc = createSolanaRpc("https://api.devnet.solana.com");
const slot = await rpc.getSlot().send();
const epochInfo = await rpc.getEpochInfo().send();
console.log({ slot, epoch: epochInfo.epoch, slotIndex: epochInfo.slotIndex });When to reach for this:
- Estimating when staking rewards activate (epoch boundaries)
- Correlating on-chain events with wall-clock time
- Understanding why transactions confirm in ~400 ms vs ~12 seconds
- Debugging leader skips during network degradation
- Scheduling maintenance around epoch transitions
Working Example
import { createSolanaRpc } from "@solana/kit";
const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");
const epochInfo = await rpc.getEpochInfo().send();
const epochSchedule = await rpc.getEpochSchedule().send();
const slotsPerEpoch = epochSchedule.slotsPerEpoch;
const slotsRemaining = slotsPerEpoch - epochInfo.slotIndex;
const msPerSlot = 400; // target, not guaranteed
const estimatedMsRemaining = slotsRemaining * msPerSlot;
console.log({
currentEpoch: epochInfo.epoch,
slotInEpoch: epochInfo.slotIndex,
slotsPerEpoch,
slotsRemaining,
estimatedMinutesToNextEpoch: Math.round(estimatedMsRemaining / 60_000),
});What this demonstrates:
getEpochInforeturns the current epoch and position within itgetEpochScheduleprovidesslotsPerEpoch(typically 432,000)- Slot time is a target, not a guarantee - skipped slots extend wall-clock duration
- Epoch boundaries affect staking warmup/cooldown and leader schedule rotation
Deep Dive
How It Works
- Validators rotate as leaders - one leader per slot produces a block
- Proof of History ticks within each slot provide a verifiable ordering clock
- A block contains transactions processed during a slot (or spans multiple slots if the leader is slow)
- At epoch end, a new leader schedule is computed from the current stake distribution
Timing Reference
| Concept | Typical Value | Notes |
|---|---|---|
| Slot time | ~400 ms | Target; actual varies with skips |
| Slots per epoch | 432,000 | ~2 days at 400 ms/slot |
| Block time | 400 ms - 1 s+ | Depends on congestion and leader |
| Finality (TowerBFT) | ~12-13 s | ~32 confirmed slots |
Leader Schedule
- Stake-weighted random selection determines which validator leads each slot
- The schedule for an epoch is fixed at the epoch boundary
- If the assigned leader is offline, the slot is skipped (no block)
Rust Notes
// Programs generally do not read slot/epoch directly unless using sysvars
use anchor_lang::prelude::*;
pub fn log_clock(ctx: Context<LogClock>) -> Result<()> {
let clock = Clock::get()?;
msg!("slot: {}, epoch: {}", clock.slot, clock.epoch);
Ok(())
}Clocksysvar providesslot,epoch,unix_timestamp- Do not assume fixed slot duration in program logic - use timestamps for deadlines
Gotchas
- Assuming exactly 400 ms per slot - skipped slots and slow leaders add latency. Fix: use confirmation levels, not slot math, for UX timers.
- Confusing slot with block height - block height increments only when a block is produced; slots always increment. Fix: use
getBlockHeightvsgetSlotappropriately. - Epoch boundary staking surprises - delegation changes have warmup/cooldown epochs. Fix: plan stake operations around epoch transitions.
- Using wall-clock for on-chain deadlines - clock drift and variable slot times exist. Fix: use
Clock::unix_timestampsysvar in programs. - Polling slot for confirmation - wasteful and imprecise. Fix: use
confirmTransactionwith a commitment level. - Leader skip during outages - transaction inclusion delays, not failures. Fix: retry with fresh blockhash and priority fees.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
getSlot polling | Debugging timing issues | User-facing confirmation UX |
Commitment levels (confirmed, finalized) | Application confirmation | Measuring block production health |
getBlockTime | Correlating slot to UTC | Real-time countdown timers |
| Clock sysvar in programs | On-chain time locks | Sub-second precision requirements |
FAQs
What is a slot in Solana?
A slot is a time window (~400 ms target) during which one validator is designated leader and may produce a block.
How long is an epoch?
Approximately 2 days. An epoch contains ~432,000 slots at the target 400 ms slot time.
What happens when a leader skips a slot?
No block is produced for that slot. The slot number still advances. Transactions wait for the next available leader.
Is slot number the same as block height?
No. Slot increments every ~400 ms regardless of blocks. Block height increments only when a block is actually produced.
How do I get the current epoch from RPC?
const info = await rpc.getEpochInfo().send();
console.log(info.epoch);Why does finality take ~12 seconds if slots are 400 ms?
TowerBFT requires a supermajority of stake to vote on a fork. This typically takes ~32 slots of voting.
Can programs access the current slot?
Yes, via the Clock sysvar: Clock::get()?.slot.
When does the leader schedule change?
At each epoch boundary. The new schedule is computed from the stake distribution at that point.
Does devnet have the same slot timing as mainnet?
Same target (400 ms), but devnet has fewer validators and more skips. Do not use devnet for timing benchmarks.
How do staking rewards relate to epochs?
Rewards are credited per epoch based on stake weight and inflation rate. New delegations have a warmup period measured in epochs.
What is slotIndex in getEpochInfo?
The number of slots elapsed since the current epoch started. Range: 0 to slotsPerEpoch - 1.
Should I build a countdown timer based on slots?
Only for rough estimates. Use confirmed/finalized commitment for user-facing "transaction complete" states.
Related
- How a Transaction Flows - slot-level confirmation path
- Clusters & Networks - per-cluster timing
- Solana Basics -
solana slotCLI usage
Stack versions: This page was written for Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, anchor-lang 0.32.1, Rust 1.91.1, @solana/kit 7.0.0, Surfpool 0.12.0, and LiteSVM 0.6.x.