A slot can pass without a block
A slot identifies a scheduled opportunity for block production. Block height counts produced blocks. Skipped slots mean the two counters do not advance together. Do not subtract a slot from a block height or use the difference as a latency measurement.
Read both counters explicitly
[{"jsonrpc":"2.0","id":"slot","method":"getSlot","params":[{"commitment":"confirmed"}]},{"jsonrpc":"2.0","id":"height","method":"getBlockHeight","params":[{"commitment":"confirmed"}]}]Even this batch is not a promise of one atomic snapshot. For diagnostics, retain the commitment and response time. Use slot-based positions for block lookups and stream checkpoints, and block-height-based checks when the API returns lastValidBlockHeight.
Apply the distinction to expiry
- Request getLatestBlockhash at your chosen commitment. Save its blockhash and lastValidBlockHeight together.
- Sign the transaction with that blockhash.
- Track getBlockHeight using a consistent commitment.
- When the valid height is exceeded, reconcile signature status before deciding whether to rebuild and sign again.
Avoid time conversion shortcuts
A fixed multiplication such as slots times 400 milliseconds is an estimate, not a wall-clock guarantee. Network behavior and skipped slots change the relationship. For actual elapsed time, record a local monotonic timestamp; for ledger placement, keep slots; for human reporting, use observed block times with their possible missing values. Clear field names prevent a subtle counter mix-up from becoming a transaction retry bug.