> ## Documentation Index
> Fetch the complete documentation index at: https://docs.allium.so/llms.txt
> Use this file to discover all available pages before exploring further.

# Reorgs

> Why blockchains discard blocks, what that does to data you have already read, and how Allium detects and corrects reorged records.

A **reorg** — short for chain reorganization — happens when a blockchain discards blocks it had already produced and replaces them with a different, competing sequence. Every transaction in the discarded blocks is un-included. Some of them get re-included in the new blocks, often at a different position; some never make it back at all.

Reorgs are normal. They are how a decentralized network resolves the case where two validators produce a block at nearly the same moment and part of the network sees each one first. The network converges on one branch, and the other is dropped.

## What a reorg looks like

Two validators propose a block at height 100. Half the network builds on block A, half on block B.

```
                  ┌── 100A ── 101A            (dropped)
   ... ── 99 ─────┤
                  └── 100B ── 101B ── 102B     (canonical)
```

When the network converges on the B branch, block 100A and everything in it never happened as far as the chain is concerned. If you read block 100A and stored its transactions, your copy of history is now wrong.

**Depth** is how many blocks got replaced. The overwhelming majority of reorgs are one or two blocks deep and resolve in seconds. Deeper reorgs are rare and usually indicate a real problem: a client bug, a network partition, or an attack.

**Frequency varies enormously by chain.** Chains with sub-second blocks and probabilistic finality reorg many times a day; BFT chains with deterministic finality never reorg at all, because a block is committed by a validator supermajority before the next one is built. See [Consensus mechanisms](/guides/consensus).

<Note>
  A reorg is not the same as a failed transaction. A failed transaction is permanently recorded onchain with a failure status and it consumed gas. A reorged transaction leaves no record on the canonical chain.
</Note>

## Why reorgs break naive pipelines

If you poll an RPC node for new blocks and append every result to a table, a reorg leaves you with:

* **Phantom records** — transactions, transfers, and trades that are not on the canonical chain
* **Duplicates** — the same transaction hash appearing twice, once from each branch, often with a different block number
* **Broken balances** — a transfer counted that never happened, so every balance derived from it is off
* **Silent drift** — no error is raised. Your pipeline looks healthy and your numbers are wrong

This is the single most common source of disagreement between a home-rolled indexer and a production dataset.

## How Allium handles reorgs

Allium treats reorg handling as a property of the platform, not something you configure.

<AccordionGroup>
  <Accordion title="Detection at ingestion" icon="magnifying-glass">
    Allium's scrapers track the parent hash of every block they ingest. When a newly fetched block does not descend from the block we already hold at the previous height, that is a reorg: we walk back to the common ancestor and re-fetch the replaced range from the canonical branch.
  </Accordion>

  <Accordion title="Confirmation depth" icon="lock">
    For the confirmed feeds, Allium waits a per-chain number of confirmations before publishing a block at all, so the vast majority of reorgs are resolved before the data is ever served. Depths are tuned per chain and listed in [Transaction finality](/guides/finality).
  </Accordion>

  <Accordion title="Realtime correction" icon="bolt">
    On the [Realtime APIs](/api/developer/overview), Allium captures reorgs as they happen and immediately corrects the affected entities — blocks, transactions, and everything derived from them. Records superseded by a reorg are removed or replaced rather than left in place.
  </Accordion>

  <Accordion title="Reconciliation for batch data" icon="microscope">
    Batch data in the [Data Catalog](/historical-data/overview) and [Datashares](/datashares/overview) is continuously re-verified against the chain by [existence and consistency checks](/historical-data/overview/data-quality-verification). Any range that disagrees with the canonical chain is re-ingested and republished, which is why batch freshness can degrade slightly on chains that reorg frequently.
  </Accordion>
</AccordionGroup>

### What this means for each product

| Product                                                                          | Reorg behaviour                                                                                    |
| :------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------- |
| [Realtime APIs](/api/developer/overview)                                         | Served from the tip, with reorgs detected and the affected entities corrected in realtime          |
| [Datastreams](/datastreams/overview) and [Beam](/beam/overview), default sources | Published after the chain's confirmation depth, so reorged blocks are filtered out before emission |
| [Datastreams](/datastreams/overview) and [Beam](/beam/overview), latest sources  | Streamed from the tip; **may include reorged data**, which is the price of the lower latency       |
| [Datashares](/datashares/overview) and [Data Catalog](/historical-data/overview) | Reconciled against the canonical chain and republished when a range changes                        |

<Warning>
  If you consume a latest stream, design for it. Key your storage on `(block_number, transaction_hash)` and make writes idempotent so a replaced block overwrites rather than duplicates, or treat latest as a low-latency signal and reconcile against a confirmed source before you act on money.
</Warning>

## Building your own reorg-safe pipeline

Whatever source you consume, these rules keep you correct:

<Steps>
  <Step title="Store the block hash, not just the number">
    A block number is not a unique identifier across branches. A block hash is.
  </Step>

  <Step title="Make writes idempotent">
    Upsert on a natural key so a re-delivered or corrected record replaces the old one instead of adding a row.
  </Step>

  <Step title="Recompute derived state rather than incrementing it">
    A balance derived by summing transfers self-corrects when a transfer is removed. A balance stored as a running counter does not.
  </Step>

  <Step title="Set your confirmation threshold by exposure, not by habit">
    Match the wait to what a reversal would cost you. See [Transaction finality](/guides/finality).
  </Step>
</Steps>

## Next steps

* [Transaction finality](/guides/finality) — per-chain confirmation depths
* [Data integration guide](/historical-data/overview/data-integration-guide) — building a reliable sync against Allium's delivery metadata
