HTAP & operational analytics
Run transactional point access and analytical scans on the same data. The physical layout is a per-table choice — not a second system to ETL into.
The problem
Why this is hard today
The HTAP tax is two databases. A row store answers point reads and writes fast but scans slowly; a column store scans fast but is a poor fit for single-row access. So teams run both and ship rows between them with CDC and ETL — paying for the lag, the duplication, and the reconciliation jobs that keep them honest.
The copy is where correctness goes to die: the analytical side is always minutes behind the operational side, dashboards disagree with the application, and "how many active accounts right now" returns a different number depending on which store you ask.
What operational analytics actually needs is one engine where a row can be written and pointed-at transactionally and scanned analytically — where the storage layout is chosen per table to fit the access pattern, not bolted on as a separate system.
Architecture
How NYXDB does it
Every table picks its physical layout independently (ADR-001, “HTAP via per-table storage layout”): row layout for OLTP point access, columnar for OLAP scans — the same catalog, the same SQL, the same transactions, with nothing shuttling rows between them.
- 01
Choose layout
A keyed, row-layout table serves single-row reads and writes; an append, columnar table serves analytical scans — each set with one SETTINGS clause.
- 02
Commit under MVCC
Writes commit under MVCC (ADR-017) with the WAL sequence as the version clock — readers see a consistent snapshot, writers never block them.
- 03
Read your writes
The operational read reflects the write that just committed — there is no CDC lag to an analytical replica.
- 04
Scan analytically
Columnar, SIMD-vectorized expression execution scans the same data for aggregates and reports.
Real SQL
In practice
-- Operational: keyed, row layout, memory-resident — fast point accessCREATE TABLE accounts ( id UInt64 NOT NULL, balance Int64, status String, PRIMARY KEY (id)) SETTINGS mode='keyed', layout='row', storage_policy='memory_data';-- Analytical: append, columnar — fast scans over historyCREATE TABLE ledger ( account_id UInt64 NOT NULL, amount Int64, ts DateTime) SETTINGS mode='append', layout='columnar', index_granularity=2048;SELECT balance, status FROM accounts WHERE id = 42;SELECT account_id, count() AS txns, sum(amount) AS netFROM ledgerGROUP BY account_id;Every statement follows the engine’s own test SQL shapes. See the SQL reference for full syntax.
Capabilities
What you get
Per-table layout
Row layout for point access, columnar for scans — chosen per table (ADR-001).
MVCC snapshot isolation
Snapshot reads at a WAL sequence; writers never block readers (READ COMMITTED default, ADR-017).
Read-your-writes
The operational read sees the write that just committed — no replica lag.
Vectorized scans
Columnar, SIMD-vectorized expression execution for heavy analytics.
One catalog
Operational and analytical tables share one schema and one SQL surface.
No ETL
Retire the CDC pipeline and the second store.
Proof
Measured on the vetted benchmark lane
point consult on warm postings (OLTP)
row-layout point access
vetted table
View benchmark952M rows/ssingle-shard columnar scan (OLAP)
vectorized execution
vetted table
View benchmark230 nskeyed count(), flat 1k–16k keys
O(1) exact
vetted table
View benchmarkMeasured on Apple M4 Max (dev), macOS — server-class validation pending. Release build, median of 5, commit-pinned (d4a3885b, 2026-07-07). Ingest figures are engine-side. See the full benchmark suite.
One engine for writes and analytics
Model an operational table and an analytical table, and query both.