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

# State sync

> How a node that has never seen the chain reaches the current version, and how it stays there.

A node joining the network has to answer two questions: how do I get to where the chain is now, and how do I stay there. State sync answers both, and the trade-off between them is explicit rather than hidden.

## Two modes of catching up

Bootstrapping — reaching the current version from nothing — can be done in one of two fundamentally different ways.

**Replay the history.** Start at genesis and work forward, either by executing every transaction again or by applying the outputs that execution already produced. The result is a node holding the entire history: every version, every proof, every transaction. It is also slow, and gets slower every day the chain runs.

**Download the current state.** Skip the history and fetch the state keys and values as they stand at the latest version, verified against the committed root. The node is current in a fraction of the time, and knows nothing about how the chain got there.

<div className="dg" data-dg="state-sync">
  <div className="dg-c" style={{aspectRatio:"720 / 322"}}>
    <svg className="dg-w" viewBox="0 0 720 322" aria-hidden="true">
      <path className="dg-wire dg--blue" d="M 134.00 126.00 L 159.60 126.00" />

      <path className="dg-head dg--blue" d="M 166.00 126.00 L 159.60 130.40 L 159.60 121.60 Z" />

      <path className="dg-wire dg--sky" d="M 324.00 126.00 L 356.54 75.38" />

      <path className="dg-head dg--sky" d="M 360.00 70.00 L 360.24 77.76 L 352.84 73.00 Z" />

      <path className="dg-wire dg--yellow" d="M 324.00 126.00 L 356.54 176.62" />

      <path className="dg-head dg--yellow" d="M 360.00 182.00 L 352.84 179.00 L 360.24 174.24 Z" />

      <path className="dg-wire dg--green" d="M 568.00 70.00 L 578.66 119.74" />

      <path className="dg-head dg--green" d="M 580.00 126.00 L 574.36 120.66 L 582.96 118.82 Z" />

      <path className="dg-wire dg--green" d="M 568.00 182.00 L 578.66 132.26" />

      <path className="dg-head dg--green" d="M 580.00 126.00 L 582.96 133.18 L 574.36 131.34 Z" />
    </svg>

    <div className="dg-b dg--blue" style={{left:"0.0000%",top:"30.4348%",width:"18.0556%",height:"17.3913%"}}><span className="dg-t">A new node</span></div>
    <div className="dg-b dg--yellow dg-round" style={{left:"23.6111%",top:"29.1925%",width:"20.8333%",height:"19.8758%"}}><span className="dg-t">Bootstrapping mode</span></div>
    <div className="dg-b dg--sky" style={{left:"50.5556%",top:"6.2112%",width:"27.7778%",height:"31.0559%"}}><span className="dg-t">Replay the history</span><span className="dg-s">re-execute, or apply stored outputs, from genesis</span><span className="dg-n">slow, and slower every day the chain runs</span></div>
    <div className="dg-b dg--yellow" style={{left:"50.5556%",top:"40.9938%",width:"27.7778%",height:"31.0559%"}}><span className="dg-t">Download current state</span><span className="dg-s">keys and values at the latest version, verified against the committed root</span><span className="dg-n">current in a fraction of the time</span></div>
    <div className="dg-b dg--green" style={{left:"81.1111%",top:"25.4658%",width:"18.8889%",height:"27.3292%"}}><span className="dg-t">Current version</span><span className="dg-s">then continuous sync</span></div>
    <div className="dg-b dg--orange dg-left" style={{left:"0.0000%",top:"78.2609%",width:"100.0000%",height:"18.0124%"}}><span className="dg-t">The two paths are not equivalent</span><span className="dg-s">A node that downloaded current state cannot serve historical queries or say how a position got where it is. A node feeding an indexer or an audit needs the history it skipped.</span></div>
  </div>
</div>

Within the replay path there is a further choice — re-execute transactions, apply the stored outputs, or let the node pick whichever is faster at each point. Re-executing is the stronger check, since it reproduces the result rather than trusting a recorded one; applying outputs is faster. The mixed mode exists because the right answer changes with how far behind the node is.

<Note>
  This is an operational decision, not a default to accept without thinking. A node that downloaded current state cannot serve historical queries or answer questions about how a position got where it is — it has no history to read. A node serving an [indexer](/protocol/architecture/indexer) or an audit process needs the history it skipped.
</Note>

## Staying current

Once at the current version, a node keeps up by consuming committed blocks as they arrive — again either by executing the transactions or by applying the outputs, with the same trade between verification strength and speed.

The difference from bootstrapping is that the gap is small and constant rather than large and shrinking. A node that falls behind enough re-enters the bootstrapping path rather than trying to close an arbitrary gap incrementally.

## How data moves

Sync is not one node asking another for a range of blocks. It separates into layers so that no single peer is a dependency and no single failure stalls progress.

| Layer                 | Role                                                                                              |
| --------------------- | ------------------------------------------------------------------------------------------------- |
| **Storage service**   | Serves data to other nodes: transactions, outputs, state values, and the proofs that go with them |
| **Data client**       | Chooses peers, tracks who has what, sends requests, and handles the ones that fail                |
| **Streaming service** | Turns "get me from here to there" into an ordered stream of verified chunks                       |
| **Driver**            | Decides what the node needs next and applies what arrives                                         |

The consequence worth understanding: a syncing node is not trusting a peer. Every chunk arrives with a proof against a root the network committed, and a peer that serves something inconsistent is rejected rather than believed. Peer selection is a performance decision, not a trust decision.

## Verification

Nothing in state sync is accepted on the strength of who sent it.

State values are verified against the committed state root. Transactions and outputs are verified against the accumulators. A node that finishes bootstrapping has a state whose root matches what a quorum of validators signed — which is what makes the fast path safe: downloading current state skips the history, but it does not skip verification.

## Where to go next

<CardGroup cols={2}>
  <Card title="Storage and proofs" href="/protocol/architecture/state/storage">
    The structures that make sync verifiable.
  </Card>

  <Card title="Run a node" href="/developers/run-a-node">
    Node roles, and how to ask about operating one.
  </Card>

  <Card title="Network topology" href="/protocol/architecture/intention-bft">
    Which tier of node a syncing peer is talking to.
  </Card>

  <Card title="Indexer" href="/protocol/architecture/indexer">
    What history answers that current state cannot.
  </Card>
</CardGroup>
