← All writing

September 2, 2026

What “Confirmed” Means Across Chains

A deposit system eventually needs a single answer to the question "can I credit this?". Chains don't agree on what that answer looks like, so a single global "N confirmations" setting is usually wrong for most of them.

Probabilistic versus deterministic finality

There are two broad families.

Probabilistic finality. A block can in principle be replaced by a longer competing chain, but the probability falls quickly as blocks pile on top. Bitcoin is the classic case. The common convention of six confirmations is a risk heuristic, not a protocol guarantee, and the right depth depends on how much value is at stake.

Deterministic (economic) finality. The protocol itself declares a block final, and reverting it would require provably burning a large amount of stake or breaking the consensus assumptions. Stellar's consensus closes a ledger roughly every five seconds, and a closed ledger doesn't get reorganized.

Ethereum has three answers

After the Merge, Ethereum clients expose several block tags, and they mean different things:

  • latest is the head of the chain, and may be reorganized.
  • safe is a block unlikely to be reorganized under normal conditions.
  • finalized has been finalized by the Casper FFG gadget, which takes about two epochs, roughly 13 minutes.

For a small deposit, waiting for safe, or a fixed number of blocks, may be reasonable. For a large one, waiting for finalized is cheap insurance. Other EVM chains and rollups each have their own finality story, including how and when batches settle to their base layer.

Solana's commitment levels

Solana exposes the idea directly as commitment levels: processed (seen by a node), confirmed (voted on by a supermajority of stake) and finalized (rooted, with maximum lockout). What you read from an RPC node depends on the level you ask for, so it matters to pass it explicitly rather than rely on a default.

Design implications

A few things I'd build in from the start:

  • Make the policy per chain, and ideally per amount. A table of (network, amount band) → required depth or finality tag is more honest than one constant.
  • Track block hashes, not only heights. A reorg replaces blocks at the same height. If you only remember "block 1,000,000 is processed", you can't tell that its contents changed.
  • Keep deposits in an explicit pending state. An observed deposit that isn't yet credited should be a first-class record that can move forward, or back to dropped if its block is orphaned.
  • Handle reorgs by reversal, not deletion. If a credited event disappears, you need an audit trail and a way to claw back or flag the credit, not a silent row removal.
  • Credit and unlock separately when it makes sense. Showing a deposit as incoming right away while only letting it be spent after finality gives users feedback without taking on the risk.
  • Watch the node, too. A lagging or forked RPC node reports confirmations that are true for its own view only. Reading from more than one provider, or sanity-checking head height, catches a lot.

A small summary

Chain familyFinality modelTypical stance
BitcoinProbabilisticDepth scaled to value
EthereumProbabilistic, then finalizedsafe for small, finalized for large
SolanaCommitment levelsRequire finalized for credits
StellarDeterministic per ledgerClosed ledger is final

The numbers will vary with each team's risk appetite. The point is that the pipeline should expose confirmation as configuration, because the right answer differs by chain, by amount, and sometimes by customer.