Block tables
BlockDB abstracts on-chain data into two core logical models: the Block State Table and the Block Event Table. Both use the block as their unit of data and understand on-chain semantics, so you do not manage block heights, data overwrites, or reorg rollbacks yourself.1. Model definitions
Block State Table: single-row state model
Definition: stores the latest state of on-chain entities plus their state at every historical height. Whenever data for a new height arrives, BlockDB stores a snapshot at that height and asynchronously updates the latest-state table.- Design philosophy: keyed by a unique entity (an address, a contract). Every write overwrites the previous state, while the storage layer retains historical snapshots.
- Typical scenarios: token balances of user addresses, current contract state variables, current NFT owner.
- System-managed columns:
block_id,block_height, andblock_timestampare maintained automatically to support historical version lookups.
Block Event Table: fact record model
Definition: stores every event that happened on chain.- Design philosophy: data is read-only and append-only. Each row represents a fact that definitively happened on chain and cannot be modified.
- Typical scenarios: token transfer logs (token_transfer), contract events, individual matched trades on an exchange.
- System-managed columns:
block_id,block_height, andblock_timestampare maintained automatically.
_archive table. Once an on-chain event happens at a given height it is unique and immutable — there is no notion of “update”, only “append”.
The derived tables underneath a business abstraction table (
_archive, _height, and so on) can be read directly with GetRow / BatchGetRows / FilterRows just like regular tables, which helps with troubleshooting. However, modifying derived tables with regular-table write APIs such as UpsertRows is forbidden — all writes must go through the Block table’s own block write interface.2. Logical types
When you create a table, every business column besides theid primary key can be declared with any logical type. For the complete list, see the reference. This section covers the types that are closely tied to blockchain data and follow EVM length conventions:
Fixed-length hexadecimal types such as
ADDRESS, TXID, BLOCKID, and TOKENID are represented as 0x-prefixed hexadecimal strings at the BlockDB API boundary and stored as fixed-length bytes underneath. Their lengths follow the EVM conventions and BlockDB’s own definitions; treat the reference and the implementation as authoritative.- ID (primary key): must be named
id. - Business columns: add as many as you need, with any logical type.
- CHAINID: identifies which chain the data belongs to.
3. Start height and consensus height
Start height
The start height is the first block height of on-chain data that the table manages, and you set it yourself.- Your table often does not need to maintain data from height 0. For example, if a contract only appeared at a certain height, set that height as the start height and only maintain data from there on.
- If you do not set it, the start height defaults to
0.
Consensus height
The consensus height is the right boundary of the contiguous height range covered from the start height onward.- As long as data is written contiguously from the start height with no gaps, the consensus height keeps advancing.
- It is the highest height that
GetState,GetEvent, and similar interfaces can safely query — querying within it guarantees you will not get an incorrect result caused by missing data.
The
current_block.height you pass when reading must be ≤ the table’s consensus height (the highest height contiguously covered in the _height table from the start height) for the result to be correct.4. Core features
ACID guarantees for block-granular writes
BlockDB writes use the block as the smallest atomic unit:- Atomicity (A): all data in one block is either fully written or fully rejected. There is never “half a block” of dirty data.
- Consistency (C): a write always replaces the data at that height completely, at block granularity — the data at that height is one complete, deterministic snapshot, and readers never see an intermediate or partially written state.
- Isolation / durability: concurrent writes are coordinated at block granularity, and committed data is durably readable.
Time-travel queries
The read APIs natively supportAS OF BLOCK <height> semantics. Even though a State table stores the latest balance, you can query its value at any historical block height in a single call.
Real-time event subscription
Every successful block-granular write makes BlockDB publish a block write event, so downstream tasks can process the data produced at each block height incrementally and in real time, building multi-stage cascaded event-driven pipelines.Transparent automatic reorg handling
When the underlying chain reorgs and N blocks must be rolled back, BlockDB uses the implicitly maintained block columns to automatically undo writes for the forked blocks, delete the corresponding events from Block Event tables, and keep Block State tables eventually consistent. Reorgs require no maintenance on your side.Summary
For on-chain data production, prefer Block tables to manage on-chain data.