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

# How real-time data is served

> How chain-tip blocks enter HotblocksDB and how Portal routes recent-data requests.

In this architecture, **real-time data** means the recent, fork-sensitive part of
a chain. It may include unfinalized blocks. It is served from HotblocksDB, a
separate stateful service, instead of from archival chunks on worker nodes.

The Portal API remains request and response based. Real-time does not mean that
Portal opens a block subscription or waits indefinitely for a new head.

```mermaid theme={"system"}
flowchart LR
  chain["Chain node or data provider"] --> service["Chain-specific data service"]
  service -->|"blocks, fork signals, finality signals"| hotblocks["HotblocksDB<br/>bounded fork-aware window"]
  scheduler["Scheduler status"] -->|"last indexed archival block"| retain["Hotblocks-retain"]
  retain -->|"retention lower bound"| hotblocks

  client["Client"] -->|"stream request"| portal["Portal"]
  portal -->|"first block at or below archival head"| workers["Assigned workers<br/>archival chunks"]
  portal -->|"first block above archival head"| hotblocks
  workers -->|"JSON Lines"| portal
  hotblocks -->|"JSON Lines"| portal
  portal --> client
```

## 1. Ingest the chain tip

A chain-specific data service reads a configured upstream source. For EVM data,
the current service reads an RPC endpoint. It exposes blocks, fork signals, and
finality signals to HotblocksDB. A HotblocksDB dataset can use more than one data
service as a redundant source.

HotblocksDB checks structural consistency such as block ordering, parent-hash
linkage, finality monotonicity, and agreement between configured sources. It does
not validate chain consensus rules or independently decide which fork is
canonical. Block contents, canonical-fork selection, and finality ultimately come
from the configured sources.

## 2. Maintain one recent chain window

For each dataset, HotblocksDB stores a bounded and contiguous window near the
chain head. A normal update extends the window. When a source reports a fork,
HotblocksDB replaces the affected suffix as one committed transition. It exposes
one canonical chain at a time, not several competing forks.

Finality and retention are separate. Finality prevents later fork processing from
altering the finalized prefix that remains in the window. Retention can still
remove old finalized blocks because HotblocksDB is not the archive.

## 3. Choose one source for a request

Portal uses the request's first block and the archival head from its current
Network view:

* if the first block is at or below the archival head, Portal sends the request
  through the archival worker path;
* if the first block is above the archival head and the dataset has a real-time
  attachment, Portal forwards the request to HotblocksDB;
* if neither source can cover the requested start, Portal returns no data or the
  relevant source error.

One response comes entirely from one source. Portal does not splice archival
worker results and HotblocksDB results together. A client reaches the other source
with a follow-up request after advancing its block cursor.

The same routing rule applies to the standard stream and finalized stream. On the
finalized stream, HotblocksDB restricts its result to the finalized head it has
received.

## 4. Continue across forks

The client resumes from the block after the last block it accepted and can include
that block's hash as `parentBlockHash`. HotblocksDB checks the anchor against its
current chain. If a reorganization changed the parent, the request returns a
conflict with recent canonical-chain information so the client can find a shared
ancestor and resume.

The server does not keep a cursor between requests. The block number and parent
hash supplied by the client are the continuation state.

## 5. Advance retention from scheduler status

With API-controlled retention, Hotblocks-retain reads each dataset's last indexed
block from Network scheduler status. After the assignment's effective time plus a
configured delay, it sends that height to HotblocksDB as the new retention lower
bound. This moves the HotblocksDB window forward after the archival path reports
the data in its indexed chunks.

The scheduler height shows that the chunk has been indexed for assignment. It is
not proof that every assigned worker has finished downloading that chunk.

The two paths can still have a temporary gap. If the requested block is above the
archival head but below HotblocksDB's first retained block, Portal treats it as no
data rather than skipping ahead.

## 6. Stream failures without changing sources

Portal forwards a successful HotblocksDB response as a stream instead of buffering
the complete response. It can replay the upstream request once when a connection
fails before any response headers arrive. It does not replay after response data
has started because that could duplicate a prefix. A later failure therefore ends
the response, and the client resumes from its last accepted block.

A HotblocksDB failure affects requests routed to the real-time path. It does not
move those requests to archival workers when their first block is above the
archival head.

## Implementation sources

* [Portal source-selection and forwarding code](https://github.com/subsquid/sqd-portal/blob/db9430aa6ff6543854b7efbc3149baa7bf667be6/src/endpoints/stream.rs)
* [Portal Hotblocks client and replay behavior](https://github.com/subsquid/sqd-portal/blob/db9430aa6ff6543854b7efbc3149baa7bf667be6/src/hotblocks.rs)
* [HotblocksDB ingestion and dataset configuration](https://github.com/subsquid/data/blob/0182f4d86aaeb62d9d038007d71b44e4e21bd8df/crates/hotblocks/src/data_service.rs)
* [HotblocksDB query implementation](https://github.com/subsquid/data/blob/0182f4d86aaeb62d9d038007d71b44e4e21bd8df/crates/hotblocks/src/query/service.rs)
* [Hotblocks-retain implementation](https://github.com/subsquid/data/blob/0182f4d86aaeb62d9d038007d71b44e4e21bd8df/crates/hotblocks-retain/src/main.rs)
* [Scheduler dataset-height calculation](https://github.com/subsquid/network-scheduler/blob/f9430b1aec0fb7f33567e2d665f8db56f56588ba/src/controller.rs)

Continue with [How an archival query is
served](/en/network/introduction/how-a-query-is-served) or review [Finalized and
recent data](/en/portal/introduction/finalized-and-recent-data) for the client API
behavior.


## Related topics

- [FAQ](/en/sdk/squid-sdk/fuel/faq.md)
- [How an archival query is served](/en/network/introduction/how-a-query-is-served.md)
- [How it works](/en/sdk/squid-sdk/starknet/how-it-works.md)
