# QuestDB: a time-series database that keeps ingestion and SQL on one engine

> QuestDB is an Apache-2.0 time-series database written mostly in Java, with a Docker image, a Homebrew formula for Apple Silicon, and a columnar wire protocol that writes rows in and streams Arrow columns back. This review covers what it solves, how the storage and ingestion path work, and where it stops being the right tool.

**questdb/questdb** — QuestDB is a high performance, open-source, time-series database

- Repository: https://github.com/questdb/questdb
- Website: https://questdb.com
- Stars: 17,379 · Forks: 1,654
- Language: Java
- License: Apache-2.0
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/questdb-questdb

## The problem QuestDB targets: time-series data that arrives before you can model it

A general-purpose relational database assumes you know the shape of the data and that writes are modest. Time-series workloads break both assumptions. Events arrive out of order, the same event can be delivered twice, a burst can be ten times the baseline, and the schema may gain a column while ingestion is running. QuestDB is built for that set of conditions, and the README is explicit about which ones it handles in the engine rather than leaving to the application: "out-of-order data, deduplication and exactly-once semantics, continuous ingest under concurrent queries, bursty load, and schema changes while streaming."

The intended audience is named in the repository topics and the README's "Where it runs" list: capital markets (tick data, order books, trades, pre-trade and post-trade analytics), aerospace and robotics (flight-test telemetry, fleet data, mission replay), and energy and infrastructure (reactor, turbine and grid telemetry at full resolution). These are teams that already have a stream of timestamped rows and want to query it with SQL rather than build a pipeline into a warehouse first. If your data is small, transactional and updated in place, this is not the tool, and the rest of this review is not for you.

## How the engine works: memory-mapped partitions, a parallel WAL, and Parquet as a tier

The README describes a storage layout rather than a query planner. Data lives in memory-mapped, time-partitioned columns, which is why the engine can read a time range without a separate index structure. Queries run across all cores with SIMD and JIT-compiled filters. The implementation is zero-GC Java with C++ and Rust on the hot paths, and the README states there are no third-party dependencies on the data path.

Storage is tiered in three layers: a parallel write-ahead log, native columnar partitions, and Apache Parquet. In the open source edition you convert partitions to Parquet yourself with `ALTER TABLE`, or create a table in Parquet directly. The README attributes automatic conversion of cold partitions and tiering to object storage to QuestDB Enterprise, which is the clearest functional line between the two editions. Parquet, Apache Iceberg and Apache Arrow are the interchange formats, so the data stays readable by other tools.

On the wire, version 10.0 introduced the QuestDB Wire Protocol (QWP), described as one binary columnar protocol over WebSocket for both directions: the same connection writes rows in and streams query results back out as columns. The Python client returns those columns as Apache Arrow by default; Rust and C/C++ enable it with a flag. The README cites its own benchmarks for 10.0 over QWP (19M rows/sec peak ingestion, 220M rows/sec streamed to Arrow with eight readers, first Arrow batch after 32 ms), and those numbers come from QuestDB's blog posts, not from an independent run.

On the SQL side, the extensions are the interesting part. `SAMPLE BY` produces time buckets, `LATEST ON` picks the most recent row per key, `ASOF JOIN` matches a row to the most recent preceding row, and `WINDOW JOIN` and `HORIZON JOIN` cover the remaining join shapes. Materialized views aggregate many rows into one per time slice; live views run window functions such as indicators one row in and one row out on an in-memory tier.

## Installing QuestDB with Docker and running a first SAMPLE BY query

The README's fastest path is the Docker image, which publishes the Web Console on port 9000 and the PostgreSQL wire protocol on port 8812:

```bash
docker run -p 9000:9000 -p 8812:8812 questdb/questdb
```

After the container starts, open `http://localhost:9000` for the Web Console. That is where you run SQL and inspect the schema; the README also points to a public demo at demo.questdb.io if you want to look before installing.

On Apple Silicon macOS there is a Homebrew formula instead:

```bash
brew install questdb
brew services start questdb
```

The README also lists the `questdb start` and `questdb stop` commands for managing the service. One constraint is stated plainly: QuestDB bundles native libraries for Apple Silicon only, and on an Intel Mac you should use the Docker image instead. For Windows and Ubuntu the README does not give install steps here; it defers to the quick start guide at questdb.com/docs/getting-started/quick-start/.

Once the console is up, the README's own example is a 15-minute OHLCV bar over a trades table, and it is a good first query because it exercises the time-series syntax rather than plain SQL:

```sql
SELECT timestamp, symbol,
  first(price) AS open,
  max(price) AS high,
  min(price) AS low,
  last(price) AS close,
  sum(quantity) AS total_volume
FROM fx_trades
WHERE symbol = 'EURUSD'
  AND timestamp IN '$today'
SAMPLE BY 15m;
```

The `SAMPLE BY 15m` clause collapses each 15-minute window into one row, and `timestamp IN '$today'` is QuestDB's interval syntax rather than a function call. The companion example in the README matches each trade to the most recent quote with `ASOF JOIN core_price q ON (symbol)`. Both queries assume tables named `fx_trades` and `core_price` exist; the README does not include the DDL for them, so you will create your own tables before either query returns anything.

## Where QuestDB stops being the right tool

The README is a product description, so it does not spend space on failure modes. Reading it as a specification, several boundaries are visible.

First, this is a time-series engine, not a general OLTP database. There is no mention of multi-statement transactions, foreign keys or row-level updates in the README, and the feature list is built around append, aggregate and retain. If your application needs mutable relational state with referential integrity, QuestDB is the wrong store and you will end up running a second database beside it.

Second, the tiering story splits across editions. The README says that in open source you convert partitions to Parquet with `ALTER TABLE` or create a Parquet table directly, while automatic conversion of cold partitions and tiering to object storage is an Enterprise capability. Teams that assume the open source build will age data out to S3 on its own will be writing that job themselves.

Third, the 10.0 features carry their own status. The README labels native arrays and live views as beta. Live views sit on an in-memory tier, which means the working set has to fit in the memory you give the process, and the README does not state what happens when it does not. QWP is new in 10.0 as well, so a client pinned to an older protocol version is a compatibility question worth checking against the release notes rather than assuming.

Fourth, the benchmark figures in the README are QuestDB's own, published on QuestDB's blog, measured over QWP on version 10.0. They are useful as an indication of the order of magnitude the project is aiming at, and useless as a prediction of your throughput, which will depend on your schema, your partitioning and your hardware.

## QuestDB compared with InfluxDB, TimescaleDB and ClickHouse

The searches people run around this project are mostly comparisons, so it is worth being precise about the differences in approach rather than in marketing.

InfluxDB is a purpose-built time-series store with its own query languages and line protocol. QuestDB's position is different in two ways: it speaks SQL with time-series extensions rather than a bespoke query language, and its storage is columnar partitions plus Parquet rather than a custom time-series file format. If your team already writes SQL and wants the data readable by Parquet consumers, that is the practical difference.

TimescaleDB is an extension on top of PostgreSQL. That means you inherit the PostgreSQL ecosystem, extensions and transactional semantics, and you inherit PostgreSQL's write path as well. QuestDB replaces the storage engine instead, which is the trade: you give up the PostgreSQL surface area and gain a write path designed around time partitioning and a WAL rather than around general-purpose MVCC.

ClickHouse is the closest comparison in spirit, since both are columnar and both are fast at aggregation. ClickHouse is a general analytical database that handles time-series data well; QuestDB is narrower and puts time-series semantics into the SQL itself, with `SAMPLE BY`, `LATEST ON`, `ASOF JOIN` and `WINDOW JOIN` as first-class clauses rather than patterns you assemble. If your workload is mostly wide analytical scans over many dimensions, ClickHouse's broader model is a better fit. If it is mostly timestamped events queried in time order with as-of joins, QuestDB's clauses do work you would otherwise write by hand.

A fourth comparison, kdb+, appears in the repository topics. The relevant difference is licensing and language: kdb+ is a commercial system with its own array language, while QuestDB is Apache-2.0 and SQL. That is a different kind of decision, about who on the team can read the queries, not about throughput.

## Licence, maintenance and what an upgrade costs you

QuestDB is licensed under Apache-2.0, per the repository's LICENSE.txt and the badge at the top of the README. The practical implication is that you can run, modify and redistribute it, including inside a commercial product, subject to the terms of that licence; the repository also carries a THIRD_PARTY_LICENSES.txt for the bundled components. This is a description of the licence file, not legal advice, and if the distinction between the open source edition and QuestDB Enterprise matters to your deployment, that is a question for your own counsel.

On maintenance, the last push to the default branch was on 2026-09-21, and the repository is not archived. Recent releases are 10.0.1 on 2026-08-24, 10.0.0 on 2026-08-06 and 9.4.3 on 2026-06-15, so the 10.0 line is roughly a month old and has already had one patch release.

The upgrade cost is concentrated in 10.0. That release introduced QWP as a new binary protocol alongside the existing ingestion path, and the README's benchmark post is framed as "QWP vs ILP", which tells you the older line protocol is still in the picture rather than replaced outright. If you have clients pinned to an older protocol or an older client library, the 10.0 upgrade is a client-side exercise as much as a server-side one. The beta label on native arrays and live views is the other thing to weigh: features marked beta in a release note can change shape in a patch release, so pinning a version and reading the release notes before each bump is cheaper than discovering a semantic change in production.

## Conclusion

Adopt QuestDB when your workload is append-heavy time-series data that you want to query with SQL soon after it lands: tick data, telemetry, SCADA, flight-test or fleet data. Do not adopt it as a general-purpose transactional database, and do not expect the open source edition to tier cold partitions to object storage on its own, since the README attributes automatic conversion and tiering to QuestDB Enterprise. Before committing, verify what your own queries do against the Parquet workflow you intend to run, and check the release notes for the 10.0 line, because QWP, native arrays and live views are new and live views are marked beta.

## FAQ

### What is QuestDB used for?

The README lists capital markets (tick data, order books, trades, pre-trade and post-trade analytics), aerospace and robotics (flight-test telemetry, fleet data, mission replay), and energy and infrastructure (reactor, turbine and grid telemetry at full resolution). It is a time-series database, so the common thread is timestamped events that need to stay queryable rather than be aggregated away on arrival.

### How much does QuestDB cost?

The repository is licensed under Apache-2.0, so the open source edition carries no licence fee. The README distinguishes an Enterprise edition that adds automatic conversion of cold partitions and tiering to object storage; it does not state pricing for that edition, and the repository does not contain it.

### Is QuestDB open source?

Yes. The repository is licensed under Apache-2.0, and the README describes QuestDB as "the open-source, low-latency time-series database on open formats." QuestDB Enterprise is a separate edition that adds capabilities the open source build does not include, such as automatic Parquet conversion and object storage tiering.

### How do I install QuestDB?

The README gives a Docker command that publishes ports 9000 and 8812, and a Homebrew formula for macOS on Apple Silicon followed by brew services start questdb. It notes that native libraries are bundled for Apple Silicon only and that Intel Mac users should use the Docker image. For Windows and Ubuntu the README defers to the quick start guide on questdb.com.

### What is WAL in QuestDB?

The README describes storage as tiered, with "a parallel write-ahead log" as the first layer, ahead of native columnar partitions and Parquet. It does not document WAL configuration keys or replay behaviour in the README, so the operational details are not something this review can state.

### What language is QuestDB written in?

The README describes the engine as "zero-GC Java with C++ and Rust on the hot paths." The repository's primary language is listed as Java, which matches the Maven build file at the top level.

## Sources

- [License: Apache-2.0](https://github.com/questdb/questdb/blob/master/LICENSE)
- [Project website](https://questdb.com)
- [questdb/questdb on GitHub](https://github.com/questdb/questdb)
- [README](https://github.com/questdb/questdb/blob/master/README.md)
- [Releases](https://github.com/questdb/questdb/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/questdb-questdb
