Skip to main content
DB
Why NYXDB

One engine instead of a data pipeline

Serve transactions, run analytics and follow live changes from one self-hosted SQL database. Your tables stay exact as writes land, the derived tables you define maintain themselves, and your queries stay open, with no cache, queue or stream processor to keep in sync.

The problem

Four systems to keep one answer fresh

A cache for reads, a queue to move changes, a stream processor to derive, a warehouse to keep history. Each one is sound on its own. Together they are a pipeline you run instead of a product you ship.

Cache · Queue · Stream processor · Warehouse

01The read you serve is one hop behind
A cached value lags its source by one refresh. For a risk check or a balance, that gap is a wrong decision, not a rounding error.
02Every hop is a place to disagree
A queue, a stream processor and a warehouse each keep a copy of the same state. Each copy is serialized, shipped and reconciled, and each is a new way for one system to disagree with another.
03Two pipelines, one entity, last writer wins
When several pipelines update parts of the same record, the last write wins and the others are lost. You add a merge step, and the merge step becomes a service of its own.

The trade, line by line

The usual stack vs NYXDB

Seven things a product needs from its data, and what each one costs when it is spread across four systems.

Fresh reads

A cache holds a copy that lags its source by one hop and is refreshed on a schedule.

Every read comes from the table itself. There is no copy to refresh.

Derived state

A stream processor computes aggregates into a second store, and the two are reconciled after the fact.

A transformation keeps the derived table exact from every committed write, inside the engine.

Schemas

The same entity is modelled again in the cache, the topic and the warehouse, and each copy drifts.

One table definition, read by every query, derived table and live stream.

History

A past state is rebuilt by replaying logs or restoring a snapshot into a scratch database.

A versioned table keeps every accepted version, and one clause reads it as it stood at a past commit.

Operations

Several systems to deploy, upgrade, secure and keep in step with each other.

One self-hosted process, started with a configuration file and a data directory.

Interfaces

A query language for the warehouse, a client API for the cache, producer and consumer APIs for the queue.

One SQL dialect for writes, reads, derived tables and live queries, over HTTP and WebSocket.

After a write

A write becomes visible downstream eventually, once it has crossed each hop.

When a write returns its receipt, the next read sees it, with no retry.

Every row restates what the docs describe.

Read the concepts

Store it, derive it, follow it live. One engine.

Every derived table, materialized view, index and live query is fed by the same stream of committed writes, so nothing drifts out of sync.

Tables that remember exactly what you need

Keep every event, only the latest state per key, or the complete history of every change. Read a table as it was at a past commit, and let the engine settle which version wins when writes arrive out of order.

Tables · Versioned history

Derived tables that maintain themselves

Describe the aggregate, the enriched view or the balance you need as a query. NYXDB keeps it current from every committed write, inside the database, so there is no stream processor to run and no results to reconcile.

Transformations · Materialized views

Queries that stay open

Put STREAM in front of a query and get the answer now, then every exact change as new writes land. Dashboards and services follow live state over one WebSocket session instead of polling.

Streaming queries · WebSocket

How it works

From your first table to a live view in three statements

Plain SQL, start to finish. The same two tables run through every example on this site and in the docs.

01

Create a table

Decide what each table remembers: every event, the latest state per key, or the full history of every change. Shard it by a key and pick the storage layout that fits how you read it.

an append table of transfers
CREATE TABLE transfers (
chain_id UINT16 NOT NULL,
token STRING NOT NULL,
sender STRING NOT NULL,
recipient STRING NOT NULL,
amount UINT256 NOT NULL,
transferred_at DATETIME64(3, 'UTC') NOT NULL,
_index UINT128 NOT NULL
)
MODE APPEND
SHARD BY (token) SHARDS AUTO;
02

Follow it live

Put STREAM in front of any query and it stays open: you get the answer now, then every change to it as new writes land. No polling, no second system.

a continuous grouped query
STREAM SELECT chain_id, token, SUM(amount) AS volume, COUNT(*) AS transfers
FROM transfers
GROUP BY chain_id, token;
03

Keep a derived table current

Describe the table you wish you had as a query. A transformation keeps it up to date from every committed write, so the aggregate, the enriched view or the balance is always ready to read.

a fold into one attribute group
CREATE TRANSFORMATION balance_activity INTO balances ATTRIBUTE GROUP activity AS
SELECT
chain_id,
recipient AS address,
token,
COUNT(*) AS transfer_count,
MAX(transferred_at) AS last_transfer_at,
MAX(_index) AS activity_index
FROM transfers
GROUP BY chain_id, recipient, token;

Built for

The workloads that cannot tolerate stale or wrong data

Each one keeps its events, its current state per key and its live views in the same engine, so the number a service reads is the number the writes produced.

Frequently asked questions

The questions a technical buyer asks first, including the awkward ones. Anything else is answered in the docs, or in the open on GitHub.

A SQL database. Your tables hold exact current and versioned state, and the derived tables, materialized views and streaming queries you define are kept current from every committed write, inside the engine. There is no separate stream processor to run.

Fewer systems, one exact answer

Start a node, create a table, and read it fresh, versioned and live from the same engine. The docs take you from install to your first self-maintaining derived table.