MCAP to queryable
158×
faster than Foxglove’s open-source MCAP toolchain
211 MB/s vs 1.3 MB/s · 86× rosbags · 89% of the speed of a raw read that decodes nothing
Benchmarks
Four standard benchmarks on one 4-vCPU machine, one system at a time, every competitor at its vendor defaults. The scripts and raw results are public, so you can rerun every number on this page.
MCAP to queryable
158×
211 MB/s vs 1.3 MB/s · 86× rosbags · 89% of the speed of a raw read that decodes nothing
TSBS ingest
1.7×
622K vs 373K rows/s · 17.3M rows, official TSBS loaders
TSBS queries
1.8×
16.1 ms vs 29.7 ms geometric-mean p50 · fastest on 7 of 10
Write to queryable
2.6×
14.7 ms vs 38.4 ms from write to visible in SQL
01 · MCAP to queryable
24 rosbag2-style ROS 2 recordings from a 24-robot fleet simulator, 465 MB and 3.28M messages: joint states, IMU, odometry, laser scans, battery, camera frames, logs and diagnostics in zstd-compressed MCAP. Queryable means every message is decoded into typed columns. The Python tools build one DataFrame per topic; Brewric builds its indexed tables and a camera-frame index. The official mcap Rust crate iterating messages without decoding them is the ceiling: Brewric reaches 89% of it while decoding everything.
The Python libraries are single-threaded, so they are compared with Brewric on one thread. With 4 threads Brewric reaches 481 MB/s.
| Tool | Threads | MB/s | Messages/s |
|---|---|---|---|
| mcap Rust crate, raw read without decoding | 4 | 905.3 | 6,389,177 |
| Brewric indexer, in-process | 4 | 480.9 | 3,394,001 |
| mcap Rust crate, raw read without decoding | 1 | 236.5 | 1,669,223 |
| Brewric indexer, in-process | 1 | 210.7 | 1,487,041 |
Brewric over HTTP (PUT /v1/recordings) | – | 67.7 | 478,045 |
| Python mcap 1.6.0, raw read without decoding | 1 | 11.2 | 78,771 |
| rosbags 0.11.9, Python | 1 | 2.4 | 17,282 |
| Foxglove mcap 1.6.0 + mcap-ros2-support 0.6.0, Python | 1 | 1.3 | 9,426 |
02 · TSBS ingest
TSBS DevOps cpu-only: 1,000 hosts over 2 days at 10-second intervals, 17.3M rows. Each database’s official TSBS loader runs with 4 workers and batches of 10,000. Brewric is loaded twice: with the InfluxDB loader over HTTP, as InfluxDB 3 is, and with the QuestDB loader over ILP/TCP, as QuestDB is. Until queryable also counts the time until count(*) returns every row.
InfluxDB 3 acknowledges a write after its WAL flush (1 s by default), so with 4 workers its ingest is bound by client concurrency.
| System | Rows/s (TSBS loader) | Rows/s until queryable |
|---|---|---|
| Brewric 0.1.0, ILP over TCP | 622,217 | 622,209 |
| Brewric 0.1.0 | 565,398 | 565,390 |
| QuestDB 10.1.0 | 373,140 | 365,850 |
| ClickHouse 26.10.3.7 | 146,434 | 146,434 |
| TimescaleDB 2.31.0 | 136,012 | 136,012 |
| InfluxDB 3 Core 3.12.2 | 40,003 | 40,003 |
03 · TSBS queries
The 10 TSBS DevOps queries run with the same seeded parameters for every system: 2 warm-up sets, then 10 sets × 2 repetitions, timed client-side over one persistent connection with no result caches. Every system’s results are cross-checked against the others. TimescaleDB is faster on two single-host queries and on groupby-orderby-limit.
The InfluxDB bar is cut at 70 ms.
| p50, ms | Brewric | QuestDB | TimescaleDB | ClickHouse | InfluxDB 3 |
|---|---|---|---|---|---|
single-groupby-1-1-1 | 3.44 | 5.01 | 2.70 | 15.0 | 30.7 |
single-groupby-1-1-12 | 4.54 | 10.4 | 13.9 | 15.7 | 470 |
single-groupby-5-1-1 | 5.37 | 6.32 | 1.85 | 15.2 | 31.2 |
cpu-max-all-1 | 6.23 | 6.96 | 6.93 | 20.7 | 316 |
double-groupby-1 | 76.5 | 203 | 680 | 105 | 1,926 |
double-groupby-all | 161 | 370 | 1,255 | 564 | 2,236 |
high-cpu-1 | 3.82 | 24.4 | 9.55 | 16.1 | 663 |
high-cpu-all | 353 | 682 | 968 | 660 | 2,674 |
groupby-orderby-limit | 47.8 | 59.9 | 7.56 | 86.4 | 15,517 |
lastpoint | 2.91 | 3.14 | 87.8 | 129 | 189 |
| geometric mean | 16.1 | 29.7 | 34.7 | 59.0 | 562 |
04 · Write to queryable
While a background TSBS load writes 100,000 rows a second, a marker row is written every 100 ms, 300 per write path, and timed from sending the write until a SQL query returns it. The chart shows each database’s fastest write path; the table has all of them.
The InfluxDB bar is cut at 200 ms.
| System and write path | p50 ms | p99 ms | Write ack p50 ms |
|---|---|---|---|
| Brewric 0.1.0: /write line protocol | 3.51 | 14.7 | 0.95 |
| QuestDB 10.1.0: ILP over HTTP (/write) | 8.80 | 38.4 | 1.47 |
| ClickHouse 26.10.3.7: INSERT (async_insert=0) | 15.3 | 45.0 | 7.96 |
| ClickHouse 26.10.3.7: INSERT (async_insert=1, wait_for_async_insert=1) | 75.2 | 125 | 67.3 |
| TimescaleDB 2.31.0: INSERT (autocommit) | 8.78 | 191 | 7.65 |
| InfluxDB 3 Core 3.12.2: /api/v3/write_lp?no_sync=true | 730 | 1,230 | 0.80 |
| InfluxDB 3 Core 3.12.2: /api/v3/write_lp (default: ack after WAL flush) | 756 | 1,250 | 838 |
Reproduce
You need Linux x86-64 with Docker and Python 3, 4 vCPU and 16 GB of RAM. The MCAP run takes about 10 minutes. The TSBS suite starts QuestDB, ClickHouse, InfluxDB 3 and TimescaleDB one at a time and takes about 2 hours. Each run prints your numbers next to the ones on this page.
Brewric runs from a prebuilt image, ghcr.io/arnavborkar/brewricd:0.1.0, and the other systems from their official images, pinned by digest. QUICK=1 checks the setup in a few minutes.
$ git clone https://github.com/Brewric/benchmarks$ cd benchmarks$ ./reproduce.sh mcap # ~10 min: MCAP to queryable$ ./reproduce.sh tsbs # ~2 h: ingest, queries, freshness$ ./reproduce.sh report # your numbers next to these
Methodology
timescaledb-tune.mcap, mcap-ros2-support), not its hosted platform. In the published run Brewric ran natively under the same limits; the scripts run it in Docker.Measured October 2026 on a 4 vCPU Intel Xeon (2.8 GHz) VM with 15.7 GiB of RAM, Linux 6.18. Versions: Brewric 0.1.0, QuestDB 10.1.0, ClickHouse 26.10.3.7, InfluxDB 3 Core 3.12.2, TimescaleDB 2.31.0 (PostgreSQL 17.11), mcap 1.6.0 with mcap-ros2-support 0.6.0, rosbags 0.11.9, TSBS at commit 8323e59c7402.