ScramDB against everything you are running today
One live copy of your data serving transactions, analytics and AI at once, on a single binary that speaks PostgreSQL. Here is what that replaces, and what it beats.
Pick your incumbent
Same data, same machine, same queries. Pick the database you are trying to get away from.
Transactional databases
Same wire protocol, same drivers, same SQL. A columnar engine and native-code execution underneath.
No columnar storage, no vectorized execution, no parallel query in the community server. Every analytical scan is a row walk.
Documents are read whole, there is no columnar scan engine, and a transaction comes with a documented time limit and a document count guideline.
ColumnStore has shipped at beta integration for years, and the new DuckDB engine is labelled alpha and not for production.
Columnstore memory and batch-mode parallelism are capped outside Enterprise, and Enterprise is licensed per core.
Database In-Memory is an Enterprise-only paid option, licensed per processor across every core on the server. ScramDB is columnar by default.
SQLite allows one writer at a time and its own documentation says it competes with fopen(), not with client-server databases.
openGauss makes you choose row store or column store per table, and serializable is implemented as repeatable read.
Analytics engines
ClickHouse cannot hold your transactions, so it lives next to a real database with a pipeline between them. ScramDB is both.
A good Postgres extension with a hybrid row and columnstore, still bound by the Postgres executor underneath.
DuckDB is embedded in a single process and allows one writer process at a time. There is nothing for a second service, a second developer or a BI tool to connect to.
StarRocks needs frontend and backend nodes before it serves a query. ScramDB is one binary, and it answered the same workload faster.
Doris is positioned to receive upserts from your operational database. ScramDB is the operational database, and it answered the same workload faster.
Druid does not support single-record updates by primary key, and a production cluster is five service types plus ZooKeeper, a metadata database and deep storage.
Pinot needs controller, broker, server and ZooKeeper before it answers, and joins only exist in its multi-stage engine.
No cross-document transactions, updates are reindex operations, and joins are either denormalisation or a single-field lookup.
Greenplum stopped being developed in the open in 2024 and its engine tracks PostgreSQL 12. ScramDB answered the same workload 24x faster.
Trino queries other people’s files through connectors. It owns no storage, holds no transactions and needs a coordinator plus workers.
Spark is a driver, executors and a cluster manager, over storage it does not own and transactions it does not provide.
QuestDB has no row-level DELETE statement, no foreign keys, triggers or procedures, and replication and RBAC are Enterprise features.
Databend needs a Raft meta service, query nodes and an object store before it answers, and it is a warehouse rather than your database.
Distributed SQL
Raft-replicated ranges over an LSM row store. Vectorized execution on top of a layout that was never columnar.
TiKV holds the rows, TiFlash holds a second columnar copy, and Raft Learner replication runs between them.
DocDB is an LSM row store with no columnar engine. Heavy analytics is documented as a job for an external system.
The other engine that really does serve both workloads. Proprietary, capped at 8 vCPU in the free tier, and slower here.
Citus spreads Postgres across a coordinator and workers. Every shard is still a row heap read by the Postgres executor.
CrateDB speaks the PostgreSQL protocol but does not support multi-statement transactions: it accepts the statement and ignores it.
OceanBase needs at least three servers for production and fixes a tenant’s compatibility mode at creation. ScramDB is one binary.
Cloud warehouses
Firebolt is an analytics engine with per-second compute billing and keys that are not enforced. ScramDB is a database that also answers the analytics.
Snowflake supports one isolation level, does not enforce primary or foreign keys on standard tables, and cannot run on your own hardware at all.
Redshift documents primary and foreign keys as informational only and never enforces them. It is also AWS-only and billed by the node hour or the processing unit.
Primary and foreign keys are informational only, the platform is not built for row-level operational work, and every second of compute is a DBU.
BigQuery charges for the bytes each query scans, does not enforce primary or foreign keys, and limits what a mutating transaction may touch.
The rest of the database
Speed is the part that fits in a table. This is the part that changes how you work.
Your dashboard reads the row your transaction wrote a millisecond ago, because there is only one copy of it. Nothing to load into a warehouse, nothing to keep in sync, no staleness window to explain to anyone.
A full analytical workload over 100 million rows in 31.6 seconds, on a 16 vCPU machine, while transactions run against the same data. That is 377 times faster than PostgreSQL answered the same queries.
The dataset that occupies 99 GiB on PostgreSQL occupies 16 GiB here. Less storage to pay for, less to back up, less to move, and less to read every time you ask a question.
CREATE DATABASE staging CLONE production returns immediately and costs nothing until you write to it. Give every developer, every test run and every AI agent its own copy of production, then throw it away.
Point at any past timestamp and query it with ordinary SQL: what did this customer see on Tuesday, when did this value change, what did the table look like before the migration. Restore targets a timestamp too, to and from S3, Google Cloud Storage or Azure.
A semantic layer ships inside the engine and speaks MCP, so an agent can ask what the data means, ask whether a question is even answerable, get the answer, and see the exact SQL that produced it. Nothing to deploy beside the database.
Every agent call runs as a real database role, so table grants, column privileges and row-level security apply to it exactly as they apply to a person. Filters are structured values rather than strings, so there is nothing to inject.
Results start flowing as soon as the first rows are ready, and keep flowing at the speed you can take them. A big join or aggregation does not have to finish before you see anything, and one slow reader never stalls the rest of the database.
Ejder is the self-driving layer. It fits itself to the machine it lands on, learns the shape of your data as it changes, picks the fastest way to answer each query, and makes hot queries faster while they run. The database tunes itself as the workload moves, so most deployments never touch a config key.
Transactions up to serializable isolation, so the concurrency anomalies you would otherwise design around simply cannot happen. Distributed transactions commit or roll back as one, and survive a client disconnecting mid-commit.
The same binary runs standalone and joins a cluster. No minimum node count to reach before production, and no separate edition to migrate to when the second machine arrives.
One database across several continents. Regions stay in agreement with full transactional guarantees between them, reads are served close to the people asking, and queries move only the data they have to move across the ocean.
Analytical execution can run on the GPU as well as the CPU, on the same data, through the same SQL. No separate engine, no export, no rewrite of the query.
A transaction that spans three machines commits everywhere or nowhere, and finishes even if the client drops halfway through. Distributed does not mean weaker guarantees here.
Bring a node in and it takes its share of the data. Drain one with a single statement and it hands its work over before it leaves. No downtime window, no rebalancing weekend, no separate operator to install.
Rewind to any moment, not to last night’s dump: name a timestamp and get the database as it was. Backups and restores talk to S3, Google Cloud Storage and Azure directly, with nothing else to install.
Roles and grants down to individual columns, and policies that decide which rows each person may see and change. The same rules bind people, applications and AI agents, because they are all just roles.
A package registry of ready-made extensions installs into the database with one command: text and embedding helpers, format codecs, domain functions. Publish your own the same way, and they run in the same sandbox with the same limits.
Prometheus metrics and a health endpoint on port 9090 from the moment it starts, plus query plans on demand. Nothing to bolt on, nothing to configure before you can see what the database is doing.
No per-query bill, no bytes-scanned charge, no compute credits ticking while a warehouse stays warm, no per-core licence to count. The cost is the machine, whether it answers one query today or a million.
Connect with psql, psycopg, SQLAlchemy, Django, JDBC, .NET, Go, Rust, Node and every BI tool that speaks PostgreSQL. Joins, window functions, CTEs, foreign keys, triggers, stored procedures, roles and row-level security all work the way you already wrote them.
Write functions in JavaScript, Python or Ruby with no toolchain, or ship compiled packages built from Rust, Go, C, C++ and TypeScript. They run sandboxed with only the permissions you grant and hard limits on what they can consume.
A single binary with no dependencies. Install it with one line, type scramdb, and it picks its own config, listens on the postgres port 5432, runs in the background and exposes metrics and health for your monitoring.
Why there are four other columns
Every other system here belongs to a category that was designed around half of the problem. The transactional databases cannot scan, the analytical engines cannot hold a transaction, the distributed SQL systems replaced the storage engine without replacing the executor, and the HTAP systems solved it by keeping your data twice.
| ScramDB UTAP | OLTP Postgres, MySQL | OLAP ClickHouse, DuckDB | Distributed SQL CockroachDB, Yugabyte | HTAP TiDB, SingleStore | |
|---|---|---|---|---|---|
| Transactions and analytics on one copy | yes | no | no | partly | partly |
| Columnar storage with native-code execution | yes | no | yes | no | partly |
| Serializable isolation | yes | yes | no | yes | no |
| PostgreSQL wire protocol | yes | yes | no | partly | no |
| Foreign keys, triggers, procedures, RLS | yes | yes | no | partly | partly |
| Instant branching and point-in-time forks | yes | no | no | no | no |
| GPU-accelerated execution | yes | no | no | no | no |
| Streaming results: answers start arriving before the query finishes | yes | no | partly | partly | partly |
| Ejder: a self-driving engine that tunes itself as the workload changes | yes | no | no | no | no |
| Programmability: sandboxed functions in your language | yes | partly | partly | partly | no |
| Clustering across regions, on the same binary | yes | no | no | yes | partly |
| Semantic AI: an agent interface inside the engine | yes | no | no | no | no |
| Production on a single node | yes | yes | yes | no | no |
Run it yourself in one line
One static binary, no dependencies. It picks its own config, listens on the postgres port 5432 and runs in the background.
$curl -fsSL https://scramdb.com/install | bash