Skip to main content
DB
ProductDisaggregated architecture

A disaggregated architecture, three layers on their own

Storage, memory and compute are separate layers of a node. It keeps your data in one layer, the state behind live queries and views in another, and the work that maintains them in a third. Each has its own clauses, keys and system relations, so you grow the one your workload leans on.

Three layers

Storage, memory and compute, each on its own terms

What each layer holds, the clause or key you turn, and the system relation that reports it.

Storage01

Where committed data lives

The write-ahead log, the segments and checkpoints behind it, the row or columnar layout of each table, its partitions, and the policies that retain its rows and tier its data between devices.

You turn
WAL · STORAGE PROFILE · PARTITION BY · POLICY
You read
system.storage · system.table_policy_bindings · system.tablets
Memory02

Where live state is kept ready

The state a shared arrangement or a materialized view holds between commits, charged to the stream’s share of the node’s continuous-state memory and visible in rows and bytes.

You turn
subscriber_idle_ttl · max_stream_duration · keep_alive · checkpoint_class
You read
system.psi_arrangements
Compute03

Where derived work runs

The transformations, arrangements and subscribers that apply every committed change once, each on its own durable cursor, with producers never waiting for readers.

You turn
node.storage.recovery_workers · node.lifecycle.stop_drain_seconds
You read
system.psi_streams · system.transformation_revisions

Storage

Durable first, laid out your way

Every commit lands in the write-ahead log before anything else sees it. From there each table declares how it is laid out, bucketed and encoded, and policies decide how long its rows stay and where its data lives over time.

WAL · group commit
Commits join a group behind one persistence barrier in a segmented, checksummed log, and a write is acknowledged only once its group is durable.
checkpoint · replay
Committed data is kept in immutable parts. A restart loads the last checkpoint, replays the log written after it and repairs a torn tail record.
STORAGE PROFILE · PARTITION BY
Row, columnar or both per table; rows bucketed by hour, day, month or hash so reads prune. Codecs are declared per column.
… POLICY <name>
Every table is bound to policies, one per role: placement, storage, retention, compaction, projection storage and residency, and index storage and residency. Retention policies expire rows by age, and storage policies tier data between local devices and object storage.
an append table with a layout, codecs, a partition and an index
CREATE TABLE transfers (
chain_id UINT16 NOT NULL CODEC(Delta(2), ZSTD(1)),
token STRING NOT NULL ENCODING LOW_CARDINALITY,
sender STRING NOT NULL CODEC(ZSTD(1)),
recipient STRING NOT NULL CODEC(ZSTD(1)),
amount UINT256 NOT NULL CODEC(ZSTD(1)),
transferred_at DATETIME64(3, 'UTC') NOT NULL CODEC(DoubleDelta, ZSTD(1)),
_index UINT128 NOT NULL CODEC(ZSTD(1)),
INDEX transfers_ts (transferred_at) USING MINMAX SCOPE HISTORY GRANULE 8192
)
MODE APPEND
SHARD BY (token) SHARDS AUTO
PARTITION BY MONTH(transferred_at)
ORDER BY (chain_id, token, _index)
STORAGE PROFILE COLUMNAR;
What you control · the node configuration
The write-ahead log keys of the node configuration and the policy clause of a table.
node.storage.wal.shard_countThe number of WAL shards per database runtime. Every tablet maps to one shard by a stable hash.
node.storage.wal.group_commit_delay_microsHow long the WAL waits to gather a commit group behind one persistence barrier.
node.storage.wal.seal_interval_millis · node.storage.wal.seal_bytesWhen an open WAL segment is sealed, by time and by size.
node.storage.wal.maximum_record_bytesThe largest WAL record one tablet batch may write.
… POLICY <name>Attaches a named policy to a table or an index, for any of the roles every table is bound to. system.table_policy_bindings lists the bindings.

Memory

Live state kept ready, visible in rows and bytes

A shared arrangement holds the state behind a streaming query or a view so its subscribers receive changes to a result that is already computed. Window and aggregate state is charged to the stream’s share of the node’s continuous-state memory, and the share is visible in the stream’s metrics.

system.psi_arrangements
One row per shared arrangement: its state rows and bytes, subscribers by consumer kind, input changes applied and output deltas emitted.
window state
A window that hops keeps one open window per step across its size, so size windows to the share. The share is visible in the stream’s metrics.
after the last subscriber
An arrangement stays ready for the idle time you set, so a returning subscriber joins without reseeding; set it per node, per definition or per statement.
an hour of volume, advancing every minute
STREAM SELECT window_start, window_end, SUM(amount) AS volume
FROM HOP(transfers, transferred_at, INTERVAL 1 MINUTE, INTERVAL 1 HOUR)
EMIT AFTER WINDOW CLOSE;
What you control · registered settings and node keys
The settings and node keys that bound what the engine keeps in memory, with the scope each applies at.
subscriber_idle_ttlnode · definition · statementHow long a shared continuous arrangement stays ready after its last subscriber leaves, so a returning subscriber joins without reseeding.
max_stream_durationnode · session · statementCaps the total lifetime of one WebSocket request, including a STREAM SELECT. A session or statement may only lower a configured cap.
keep_alivedefinitionKeeps a view’s arrangement running with no subscriber. Transformations and materialized views always run.
checkpoint_classdefinitionWhat a definition recovers after a restart: nothing, its durable progress, or its durable state.
result_batch_rowsnode · session · statementThe largest number of rows in one page of a finite result. Rows and their order do not change, only the framing.
gateway.observability.query_history_entriesnodeHow many recent queries the process keeps in memory for query history; it starts empty after a restart.
node.resources.execution.schema_maximum_rungsnodeSchema generations kept per table.

Compute

Derived work that never slows a write

Transformations, arrangements and subscribers run on the node and apply every committed change once. Each keeps its own durable cursor and acknowledges only what it applied, so a producer never waits for a reader.

  1. transformation01

    Checkpointed writers that resume

    A transformation records its progress durably. After a restart it continues from its cursors, rebuilds from current rows or reseeds from a snapshot, whichever is the cheapest exact way, and logs its choice.

    system.transformation_revisions · rows_written · lag_source_sequences

  2. derived_arrangement02

    One arrangement per shared query

    Shared continuous channels and materialized views run as arrangements that subscribers join. The engine sizes query and seed parallelism, chooses join strategies and prunes shards itself, so those choices need no setting.

    system.psi_arrangements · generation · checkpoint sequence

  3. public_session · index · projection03

    Subscribers on their own cursors

    Streams, indexes, projections, caches and the change feed each read the feed by relation, component and key. Delivery is admitted per owner against the feed’s retention capacity, so one consumer cannot grow the retained feed without bound.

    system.psi_streams · demand · queued frames · lag

node.storage.recovery_workers sets how many relations recover at once when the node opens · node.lifecycle.stop_drain_seconds bounds the drain in which every transformation catches up with its sources before the process exits

What that means for you

Grow the layer your workload leans on

Each layer has its own clauses, keys and system relations, so the knob you turn matches the pressure you see.

your history grows

Keep more, in the storage layer

Partition by time, choose a columnar layout and codecs per column, and let retention policies expire rows by age and storage policies tier data between local devices and object storage. Watch live WAL bytes and the reclamation blockers.

your live queries multiply

More subscribers, one arrangement

Every client on the same query joins one shared arrangement, so its state is held once. Read each arrangement’s rows and bytes, and set how long it stays ready after the last subscriber leaves.

your derived tables multiply

More transformations, no slower writes

Each transformation is its own subscriber with its own cursor, and a slow one never holds back a write. Follow each one’s lag and rows written per revision, and bound the drain on a graceful stop.

Tablets are replicated across nodes and move, split and merge as data grows; when a node is lost, a replica takes over with every acknowledged write.

Deployment topologies

Frequently asked questions

The questions an operator asks before a node carries production traffic. Anything else is in the operations docs.

No. Producers never wait on consumers. Each transformation, index and stream keeps its own durable cursor and acknowledges only what it applied; a slow one falls behind on its own cursor and catches up, and after a restart it resumes from where it left off.

See the three layers on your own node

Start a node, read its storage, arrangement and transformation relations, and set the keys that bound each layer.