kdb+ vs QuestDB
The open-source alternative for capital markets. One SQL engine for live and historical data, on open formats, with published benchmarks.
kdb+ has been the fastest thing on a trading floor since 2003, and for most of that time nothing came close. Its architecture was the right answer for the data of the 2010s: one writer, one language, one format. QuestDB is what you'd build today: one SQL engine over hot and cold data, tiering that runs itself, and streaming compute at low latency.
Adoption in capital markets has been fast: 7 of the 20 largest investment banks use QuestDB, alongside hedge funds, market makers, proprietary trading firms, crypto venues and exchanges.
Run QuestDB beside kdb+
Start with one workload on open source, talk to us about a side-by-side on your own data, or reproduce the benchmark first.
Two decades of kdb+: what it was built for, and what changed
kdb+ earned its reputation. Arthur Whitney wrote k in 1993, kdb followed in 1998 and kdb+ in 2003. The goal was simple: hold a day of ticks in memory on one machine and run vector math over it faster than anything else. One expert could ask any question in a few characters of q. Back in the 2000s, nothing came close.
That architecture is the one you still run today: a tickerplant feeds an RDB that holds the day in RAM, a script flushes it to the HDB at end of day, and only one process writes to a table. Query routing, entitlements, replication and failover aren't part of the database either; they're q scripts your team wrote and still maintains, and every byte on disk is in a format only kdb+ reads.
Three things changed since.
The data outgrew RAM. A day of ticks fit in memory. Years of full-depth order book don't fit on any one machine, and rebuilding the book at a given microsecond on a day last March means going to object storage. kdb+ can read its own HDB format from a bucket, but anything else that wants that data still needs an export.
The team outgrew the specialist. The people who need the data now are quants, compliance, risk, data platform teams and, more and more, coding agents. They know Python, dataframes and SQL, not q. The q developers who do are scarce and expensive, and they take the knowledge of the scripts with them when they leave.
The tools on the desk changed. Polars, DuckDB and their kind are on every quant's machine now: very fast, liked, and all reading one format, Parquet. KX's answer has been wrappers and exports, and its own versions of those tools like PyKX. A proprietary rebuild can't keep pace with open source.
KX's answer is KDB-X, generally available since November 2025: native Parquet, object storage, SQL and the PostgreSQL wire protocol, the direction QuestDB has been on since it went open source. In KX's own words, KDB-X is "built on the trusted kdb+ core" and its SQL works by "translating statements to q at runtime". Open formats and SQL are a layer over the old engine, not a database designed around them, and the license stops anyone outside KX from measuring the difference.
Capture, compute, query, retain: kdb+ versus QuestDB
Capture. In kdb+: a tickerplant process, log replay on crash, one writer per table. In QuestDB: millions of ordered and out-of-order events per second, multi-writer, acknowledged once durable, and QWP clients hold unacknowledged rows through a node loss and resend on reconnect.
Compute. In kdb+: customer-written q update loops maintaining RDB state, and markouts as batch jobs. In QuestDB: live views (beta in 10.0) keep VWAP, rolling windows and order-book aggregates current as rows land, and HORIZON JOIN turns markouts into one SQL statement.
Query. In kdb+: RDB for today, HDB for history, a gateway script to stitch them. In QuestDB: one SQL surface across the hot and cold tiers; a query doesn't know or care which tier the data sits on.
Retain. In kdb+: an end-of-day flush to the HDB, and the archive is a project. In QuestDB: partitions tier to S3, GCS or Azure on a schedule you set and stay part of the same table, and what lands is plain Parquet.
Pre- and post-trade analysis in SQL
Most post-trade analysis is some combination of a few primitives: slippage is an ASOF JOIN, a markout curve is a HORIZON JOIN, and an ECN scorecard is the same HORIZON JOIN grouped by venue and pivoted into a dashboard. The post-trade cookbook walks through each of them. On the pre-trade side, a one-second OHLCV bar that maintains itself as trades arrive:
CREATE MATERIALIZED VIEW trades_ohlcv_1s ASSELECTtimestamp, symbol,first(price) AS open,max(price) AS high,min(price) AS low,last(price) AS close,sum(amount) AS volumeFROM tradesSAMPLE BY 1s;
In kdb+, the equivalent is a hand-coded RDB update loop and an end-of-day HDB flush.
Case in point: real-time markouts
Markout analysis is arguably the hardest post-trade problem. In kdb+, markouts are typically batch jobs backed by streaming pipelines that maintain state across multiple time offsets. QuestDB built HORIZON JOIN to solve this as a single SQL primitive: each trade is matched to market data at multiple horizons in one pass, turning a batch process into a real-time query. In kdb+, these analyses are customer-maintained q scripts. In QuestDB, they are declarative SQL, with query planning, parallel execution and SIMD acceleration handled by the database.
Open formats versus kdb+'s proprietary format
With kdb+, the database is the ceiling. Data lives in a format only kdb+ reads, on local disk or in a bucket, behind a protocol only kdb+ clients speak. Anything else that wants the data, a lake, a notebook, an ML pipeline, an agent, needs a wrapper or an export, and every export is another copy to keep in sync. The more the estate grows, the more of that architecture there is to maintain.
With QuestDB, two things are different. You don't depend on our format: older partitions are plain Hive-partitioned Parquet in your own bucket with nothing proprietary on top. Register them in a catalog like Iceberg or DuckLake, or point a lakehouse like Databricks or Snowflake at the bucket, and they read the same files QuestDB is still querying. The data stays yours. And there's nothing to stitch together: one SQL engine queries the hot tier and the cold tier, and data moves from one to the other on its own, on the retention policy you set.
What kdb+ costs to run, and what QuestDB costs instead
Start with RAM. A kdb+ RDB holds the day in memory, so the boxes are sized for RAM, and RAM prices have gone up a lot recently. QuestDB doesn't need the day in memory.
Then the history. QuestDB partitions by the hour, so data that is an hour old can already move to object storage, where it costs a fraction of local disk: 100 TB of history is roughly $2.3k a month on S3 Standard against roughly $8k on gp3 volumes.
Once it's there, storage and compute are decoupled. The history sits in one place, as Parquet, and every replica reads it natively from the same bucket, so you size compute for the queries, not for the data. In an RDB/HDB estate, compute is tied to storage: every HDB carries its own copy of the history on its own disk, and adding capacity means adding another box with both.
Hardware and people
The most demanding QuestDB deployments run on 32 to 64 cores per box, occasionally 96. About 4 GB of RAM per core is what we recommend for the heaviest queries; plenty of deployments run on less. Running it takes the skills a platform team already has, SQL and standard ops, so the people who know the data best, the q engineers included, spend their time on the data rather than on gateways and replication scripts. Fewer, smaller boxes, one copy of the data and no specialist plumbing to maintain is where the materially lower total cost of ownership comes from.
Replication, failover and security: built into QuestDB, DIY in kdb+
- Crash recovery in seconds. After a crash, QuestDB replays the last seconds of its write-ahead log. A kdb+ RDB replays the tickerplant log to rebuild the day, which is minutes on a busy desk.
- Role-based access control and TLS on by default. kdb+ ships TLS and a password file; entitlements are a gateway your team writes.
- Replication on shared object storage. Replicas in other regions read the same bucket, and a new one bootstraps without touching the primary. In kdb+, replication is q scripts and a project.
- Failover without a restart. A replica is promoted to primary in place and clients reconnect to it on their own. Promotion is manual today; automatic failover is in development.
- Clients ride through a node change in both directions: store-and-forward on the write path, resumable query streams on the read path. In kdb+, that's a queue in front of the database.
- Rolling upgrades with no maintenance window, using the same promotion mechanism.
- Concurrency. Multi-threaded reads and writes, readers never block, and analytical queries run alongside ingestion. A kdb+ process is single-threaded with one writer per table; parallel reads come from secondary threads or extra processes.
SQL instead of q, for your team and for AI agents
kdb+ gives you q, a terse and powerful array language descended from APL, and in expert hands a few lines of q do remarkable things. Some large firms have gone a long way with it and built whole applications in q, which is unusual for a database language. The catch is that everything is q: routing, entitlements, materialized views, replication, all scripts your team builds and maintains in a language with a small and expensive talent pool.
QuestDB is SQL, with primitives built for capital markets: an extensive suite of time-series joins (ASOF JOIN alone picks between seven algorithms depending on the shape of the data), SAMPLE BY, LATEST ON, materialized views and live views.
The same goes for AI agents. QuestDB speaks standard SQL over the protocols agents already use, a REST API and the PostgreSQL wire protocol, so an agent connects with nothing extra to install and can write the markout or best-execution query itself. With the Web Console notebooks and the QuestDB MCP server, it works in the same session as the person checking its output, with the same permissions.
Here, a single prompt has Codex calculate markouts for the previous day along with key indicators, then display the results in an interactive notebook:
Learn more about AI integrations →
kdb+ exposes a proprietary protocol and q. LLMs fail 57% of q coding tasks on the first attempt and 26% even after ten retries: right-to-left evaluation, heavy operator overloading and very little public training data.
kdb+ vs QuestDB benchmarks: what we can publish
We publish reproducible benchmarks using TSBS, which was created by Timescale and has seen no real development upstream since 2023, so we maintain our own fork. See our comparisons with InfluxDB, TimescaleDB and ClickHouse; the QuestDB figures below are the same ones those pages use.
kdb+'s license carries a DeWitt clause, which forbids publishing benchmark results, so we cannot show a head-to-head. KX is under no such restriction and has published its own TSBS comparison of KDB-X against QuestDB 9.0.0, a July 2025 release that is now more than a year and several releases behind, on hardware and configuration of its choosing. Until the license changes, that is the only side of this comparison anyone will be allowed to publish.
These numbers predate QWP, the binary protocol we shipped in QuestDB 10.0 in August 2026. It replaces text-based InfluxDB Line Protocol on the way in, up to 3.6x faster over a network, and streams results back as Arrow on the way out.
QuestDB TSBS results
Environment: AWS r8a.8xlarge (32 vCPU, 256 GiB RAM), EBS GP3 (20k IOPS,
1,000 MB/s throughput), QuestDB 9.3.3 with the out-of-the-box configuration.
Measured: QuestDB 9.3.3, queries in August 2026 and ingestion in March 2026. The TSBS client and the database run on the same instance with no CPU pinning. New benchmarks on QuestDB 10.0 are coming.
Ingestion
Workload: cpu-only use case, 10-second reporting interval, 32 load
workers, across four cardinality levels. These are single-server figures, one
r8a.8xlarge with 32 vCPUs; ingestion is parallel across cores, so a larger
instance goes higher.
| Hosts | QuestDB |
|---|---|
| 1,000 | 7.77M rows/sec |
| 4,000 | 7.96M rows/sec |
| 100,000 | 8.59M rows/sec |
| 1,000,000 | 7.14M rows/sec |
Throughput holds between 7 and 8.6 million rows per second from a thousand hosts up to a million, because QuestDB stores every host in one columnar table rather than creating a structure per series.
Query latency
Query names encode metrics, hosts and hours: 5-8-1 is five metrics, eight hosts, one hour. Every query on this page is described in the appendix.
Workload: cpu-only use case, 4,000 simulated hosts, 10-second reporting
interval, two-day window (69.1 M rows). 1,000 queries per type, single client
worker (QuestDB parallelizes queries internally). Each figure is the median
latency within a run, averaged over 3 runs, with a warm query cache.
| Query Type | Median |
|---|---|
| single-groupby-1-1-1 | 0.41 ms |
| single-groupby-5-1-1 | 0.60 ms |
| single-groupby-1-8-1 | 0.91 ms |
| single-groupby-5-8-1 | 1.17 ms |
| single-groupby-1-1-12 | 1.43 ms |
| cpu-max-all-1 | 1.48 ms |
| lastpoint | 1.70 ms |
| single-groupby-5-1-12 | 1.94 ms |
| high-cpu-1 | 3.31 ms |
| cpu-max-all-8 | 5.40 ms |
| cpu-max-all-32-24 | 5.37 ms |
| groupby-orderby-limit | 16.76 ms |
| double-groupby-1 | 32.20 ms |
| double-groupby-5 | 41.20 ms |
| double-groupby-all | 56.10 ms |
| high-cpu-all | 1,027.50 ms |
Narrow single-groupby queries return in sub-millisecond median latency, and every query except the full scan of all ten metrics across all 4,000 hosts completes in under 60 ms.
Reproduce it yourself
TSBS is fully open source. Clone, build, and run the exact same benchmark on your own hardware:
git clone https://github.com/questdb/tsbs.gitcd tsbsmake tsbs_generate_data tsbs_generate_queries \tsbs_load_questdb tsbs_run_queries_questdb
We also provide ready-to-run automation for Claude Code and OpenAI Codex that handles prerequisites, data generation, loading, and the full query benchmark end-to-end.
Ecosystem & Openness
Infrastructure & Operations
Development & Language
AI & LLM Readiness
Is QuestDB a kdb+ replacement?
kdb+ has been the fastest thing on a trading floor for most of the years since 2003, and it's still a capable engine with a large installed base. Where a firm has built whole applications in q, that's not what QuestDB replaces; it replaces the database underneath them, the tick store, the market data history and the analytics on top. That architecture was the right answer for the data of the 2010s: one writer, one language, one format. The data of 2026 still needs a low-latency engine that ingests and analyzes live market data in milliseconds; the history now belongs on object storage, in open formats, with storage and compute decoupled and the popular tools reading it directly.
QuestDB is built for that data: one SQL engine from the tick that just landed to the partition archived five years ago, on open formats every major platform reads. Security, replication, failover and live compute come in the box.
The rate of progress at QuestDB is worth weighing too: 16 releases in 2025 alone, with nanosecond timestamps, N-dimensional arrays, HORIZON JOIN, materialized views and symbol auto-scaling, then QuestDB 10.0 in 2026 with a brand new ingress and egress binary protocol and live views, and Enterprise 4.0 with cold storage and restart-free promotion.
So, is it a replacement? For the tick store, the market data history and the analytics on them, yes. And the stakes are bigger than a database swap: capital markets firms are choosing the data infrastructure they'll run for the next decade, between a proprietary stack and open formats. You don't have to choose up front: the easiest start is one workload beside kdb+.
Ready to evaluate?
QuestDB is built for capital markets. The post-trade analysis cookbook runs on the live demo with real FX market data, with no license required and no restrictions on what you can publish about the results.
Appendix: what each TSBS query does
Query names encode their parameters: single-groupby-5-8-1 is five metrics, eight hosts, one hour.
| Query | What it measures |
|---|---|
| single-groupby-M-H-T | Maximum of M CPU metrics for H random hosts, in 5-minute buckets over T hours. 1-1-1 is one metric, one host, one hour; the -12 variants cover twelve hours |
| double-groupby-M | Average of M CPU metrics for every host, grouped by host and by hour, over 24 hours. all is all ten metrics |
| cpu-max-all-H | Maximum of all ten CPU metrics for H random hosts, per hour. -1 and -8 cover one hour; -32-24 covers 32 hosts over 24 hours |
| high-cpu-1 | Every reading where one metric is above a threshold, for one random host |
| high-cpu-all | The same threshold scan across every host, which is a full-table scan |
| lastpoint | The most recent reading for every host |
| groupby-orderby-limit | The last five per-minute aggregates before a random point in time, ordered by time, a top-N query |
Definitions follow the TSBS README. Every query is generated with seed 123 against the 4,000-host dataset, so each engine answers the same random hosts and time ranges.