Timelaketimelake
DocsBenchmarksRoadmapSpecContribute
Apache 2.0 ·
TimelaketimelakeThe open time-series lakehouse.
v0 · Apache 2.0 · Contribute · GitHubBuilt on Apache Arrow, Apache DataFusion, Apache Parquet, and Apache Iceberg.
Benchmarks

Industrial IoT

Plant data as it really arrives, 30 days of it, queried like plant dashboards and reports, against databases and lakes.

Our own benchmark: the data generator, the queries, and the method are all timebench's.

Methodology
After maintenanceRight after ingestAfter 1 dayAfter 7 daysIngest and maintenanceWhile ingestingConcurrent dashboardsCostFailed or timed outWhat each entry meansOver time

Answers are checked against a copy of the data with each row once. Each section shows the newest run on the storage you pick.

After maintenance

After each system's maintenance, first run of each query in a fresh process. Systems maintain at different times: Timelake while it ingests, most others in a separate step after it, some not at all; the panel below says which, and how long the step after ingest took.

Tuned·Run of 2026-10-20

Maintenance before these queries

When each system maintains its tables, and how long its step after the last commit took.

  • TimelakeWhile it ingests: each append compacts what it can. The step after ingest only finishes what's left.1.8 s
  • Iceberg (PyIceberg)A separate job after ingest; until it runs, readers see every small file.175 s
  • LanceA separate job after ingest.27.8 s
  • Parquet filesA separate job after ingest.276 s
Rank by
QueryTimelakevs fastest

All queries

The geometric mean over the 10 of 11 queries every reader answered. First run of every reader; lower is better.

  1. 209 ms
  2. 527 ms2.5×
  3. 622 ms3.0×
  4. 732 ms3.5×
  5. 890 ms4.3×
  6. 4.75 s23×
  7. 5.12 s25×

Time over runs

First-run time in each of the 1 run on this storage; dashed: a system read by another engine.

One run so far: the history starts with the next.

Right after ingest

Right after the last commit, before any maintenance: the state readers see while data streams in.

Tuned·Run of 2026-10-20

Rank by
QueryTimelakevs fastest

All queries

The geometric mean over the 10 of 11 queries every reader answered. First run of every reader; lower is better.

  1. 281 ms
  2. 659 ms2.3×
  3. 1.67 s5.9×
  4. 4.27 s15×
  5. 6.24 s22×
  6. 9.06 s32×
  7. 10.6 s38×

Time over runs

First-run time in each of the 1 run on this storage; dashed: a system read by another engine.

One run so far: the history starts with the next.

After 1 day

After a day of data has arrived.

Tuned·Run of 2026-10-20

Rank by
QueryTimelakevs fastest

All queries

The geometric mean over the 11 queries. First run of every reader; lower is better.

  1. 203 ms
  2. 232 ms1.1×
  3. 493 ms2.4×
  4. 543 ms2.7×
  5. 564 ms2.8×
  6. 1.31 s6.5×
  7. 2.27 s11×

Time over runs

First-run time in each of the 1 run on this storage; dashed: a system read by another engine.

One run so far: the history starts with the next.

After 7 days

After seven days of data have arrived.

Tuned·Run of 2026-10-20

Rank by
QueryTimelakevs fastest

All queries

The geometric mean over the 11 queries. First run of every reader; lower is better.

  1. 255 ms
  2. 351 ms1.4×
  3. 495 ms1.9×
  4. 759 ms3.0×
  5. 1.76 s6.9×
  6. 3.36 s13×
  7. 3.46 s14×

Time over runs

First-run time in each of the 1 run on this storage; dashed: a system read by another engine.

One run so far: the history starts with the next.

Ingest and maintenance

How each system took the data in and kept it in shape: load rate, commit times, maintenance, and what it stored.

Tuned·Run of 2026-10-20

Load

rows per second, history in commits of an hour of data; higher is better

  1. 1.8M/s
  2. 1.6M/s1.2×
  3. 1M/s1.8×
  4. 508.5K/s3.6×

Commit

median time per commit of the live day; lower is better

  1. 95 ms
  2. 179 ms1.9×
  3. 443 ms4.7×
  4. 1.15 s12×

Per system

Committing is the time spent in all commits together; commit times are the live day's, a 5-minute window per commit. Storage is all files after maintenance, counting replaced files still waiting for cleanup.

SystemCommittingCommit p50MaintenanceFilesStorage
Timelake404 s95 ms1.8 s149757 MB
Iceberg (PyIceberg)17 min1151 ms175 s1,0692.2 GB
Lance348 s443 ms27.8 s2613.5 GB
Parquet files232 s179 ms276 s311.7 GB

Scroll the table sideways for every column.

While ingesting

Fresh readers during ingest: whether they saw every finished commit, and how fast dashboard queries ran under writes.

Tuned·Run of 2026-10-20

Per system

Every 15 s during ingest, a fresh reader ran the dashboard queries and checked the newest row it could see. Behind: probes that missed a commit that had already finished.

SystemProbes behindMost behindDashboard query, median
Timelake0 of 17—226 ms
Iceberg (PyIceberg)0 of 5—1.07 s
Lance0 of 8—5.26 s
Parquet files0 of 6—5.63 s

Scroll the table sideways for every column.

Concurrent dashboards

Several clients at once after maintenance, each with its own reader, running the dashboard queries in turn.

Tuned·Run of 2026-10-20

Per system

After maintenance, 1, 4, 16 clients at once, each with its own reader open, running the dashboard queries in turn for 30 s. Queries per second over all clients, and the 95th percentile latency.

System1 client4 clients16 clients
Timelake41.4 q/sp95 40 ms67.6 q/sp95 116 ms68.5 q/sp95 451 ms
Iceberg (PyIceberg)2.5 q/sp95 816 ms3.5 q/sp95 2.87 s0.7 q/sp95 353 s9 errors
Lance0.3 q/sp95 5.64 s0.4 q/sp95 15.5 s0.3 q/sp95 1491 s8 errors
Parquet files10.6 q/sp95 139 ms24.0 q/sp95 262 ms24.9 q/sp95 1.08 s

Scroll the table sideways for every column.

Cost

Requests and storage at the store's list prices; machines are not included.

AWS S3·Tuned·Run of 2026-10-20

On AWS S3

Ingest is scaled to a month of data arriving at this rate.

SystemIngest, per monthStorage, per monthPer query
Timelake$0.049$0.016$0.000023
Iceberg (PyIceberg)$0.098$0.048$0.000097
Lance$0.26$0.076$0.0014
Parquet files$0.058$0.036$0.000038

Scroll the table sideways for every column.

Failed or timed out

Left out of the rankings above; each query's list says which readers it lost.

Tuned·Run of 2026-10-20

Per reader

  • Lance + DuckDB2uptime (right after ingest), uptime (after maintenance)

What each entry means

Each system is written, maintained, and read the way its own docs suggest, on the same data. An entry in a ranking is a system, or a system and the reader that queried it, such as Lance + DuckDB.

Every system runs in two tunings. Tuned: each system as its docs recommend, precomputation included. Default: each system as installed. Results are tuned unless a section's switch says otherwise.

Timelake

Timelake's own writer: Iceberg tables of sorted Parquet, compacted as it appends.

Written
Table.append per commit, with inline maintenance (compaction, dedup, retention).
Maintenance
timelake maintain: each partition rewritten into one sorted file, rollups refreshed.
When
While it ingests: each append compacts what it can. The step after ingest only finishes what's left.
Tuned
The workload's rollups, and its queries in Timelake's own functions where the docs write them that way.
Read by
Timelake: Timelake's own reader (the CLI, on DataFusion), with dedup on read, its indexes and its cache.DuckDB: Timelake's tables read by plain DuckDB, with no Timelake software: it sees rows that arrived twice until compaction removes them.

Iceberg (PyIceberg)

Plain Iceberg tables written by PyIceberg appends: what a Firehose stream into S3 Tables writes.

Written
PyIceberg append per commit, tables partitioned by day.
Maintenance
A bin-pack rewrite of small files, S3 Tables' default compaction.
When
A separate job after ingest; until it runs, readers see every small file.
Tuned
A sort order on the series key and time, and compaction that sorts each day by it.
Read by
DuckDB: DuckDB reading the files directly with its Iceberg, Lance or Parquet support: no Timelake software.

Lance

Lance datasets, appended commit by commit.

Written
write_dataset in append mode per commit.
Maintenance
compact_files, then cleanup_old_versions.
When
A separate job after ingest.
Tuned
Its maintenance, then a B-tree index on the series key and a zone map on time. Default: no maintenance.
Read by
DuckDB: DuckDB reading the files directly with its Iceberg, Lance or Parquet support: no Timelake software.DataFusion: Apache DataFusion reading the files directly, from Python.

Parquet files

Parquet files without a table format: a new file per commit, as an S3 sink writes them.

Written
A Parquet file per commit in a folder per day.
Maintenance
Each day rewritten into one sorted file.
When
A separate job after ingest.
Tuned
Its maintenance. Default: the files as written, no maintenance.
Read by
DuckDB: DuckDB reading the files directly with its Iceberg, Lance or Parquet support: no Timelake software.DataFusion: Apache DataFusion reading the files directly, from Python.

TimescaleDB

TimescaleDB, a PostgreSQL database for time series, on its server's own disk.

Written
COPY per commit into hypertables; rows that arrive twice are skipped.
Maintenance
Every chunk converted to its columnstore.
When
A separate step after ingest (in production, a background policy on older chunks).
Tuned
An index on (series, time), the columnstore, and continuous aggregates its tuned queries read. Default: the hypertable as created, row store.
Read by
PostgreSQL: SQL over PostgreSQL's protocol.

ClickHouse

ClickHouse MergeTree tables on its server's disk, ordered by series key and time.

Written
Arrow inserts per commit; tables where rows can repeat use ReplacingMergeTree.
Maintenance
OPTIMIZE TABLE … FINAL merges every partition; repeated rows are read with FINAL until then.
When
Merges run in the background while it ingests; the step after ingest forces the final merge.
Tuned
Ordered by (series, time), partitioned by month, merged after ingest, and materialized views where rows don't repeat. Default: ordered by time.
Read by
ClickHouse: ClickHouse's own SQL over HTTP.

QuestDB

QuestDB WAL tables partitioned by day, on its server's disk.

Written
Its wire protocol from Python, per commit; repeated rows are removed on write (DEDUP UPSERT KEYS).
Maintenance
None; a checkpoint waits until every commit is applied.
When
None: commits are applied in the background, and the step after ingest waits for them.
Tuned
The series symbol indexed, materialized views, and LATEST ON for the latest rows. Default: the tables as created.
Read by
QuestDB: QuestDB's SQL over the PostgreSQL protocol.

InfluxDB 3 Core

InfluxDB 3 Core with its query file limit raised, as its docs allow, so long time ranges can be queried.

Written
Line protocol over HTTP, four requests at a time.
Maintenance
None: Core has no compaction.
When
None.
Tuned
The query file limit raised and a last value cache. Default: as shipped, a query reads at most 432 files.
Read by
InfluxDB: InfluxDB's SQL over HTTP.

InfluxDB 3 Core, as shipped

InfluxDB 3 Core as shipped: a query reads at most 432 Parquet files, about 3 days of data, so longer ones fail.

Written
Line protocol over HTTP, four requests at a time.
Maintenance
None: Core has no compaction.
When
None.
Read by
InfluxDB: InfluxDB's SQL over HTTP.

Over time

Each system's own reader after maintenance: the geometric mean of first runs over the queries it completed in each run. The weekly run adds a point each week.

AWS S3

1 run

Local disk

7 runs

All runs

Hover or tap ⓘ for the machine, the commit and every version.

  • 2026-10-20AWS S3Timelake, Iceberg (PyIceberg), Lance, Parquet filesjsonl
  • 2026-10-20Local diskTimelake, TimescaleDB, ClickHouse, QuestDB, InfluxDB 3 Core, InfluxDB 3 Core, as shipped, Iceberg (PyIceberg), Lance, Parquet filesjsonl
  • 2026-10-19Local diskTimelake, TimescaleDB, ClickHouse, QuestDB, InfluxDB 3 Core, InfluxDB 3 Core, as shipped, Iceberg (PyIceberg), Lance, Parquet filesjsonl
  • 2026-10-18Local diskTimelakejsonl
  • 2026-10-18Local diskTimelakejsonl
  • 2026-10-18Local diskTimelakejsonl
  • 2026-10-17Local diskTimelake, TimescaleDB, ClickHouse, QuestDB, InfluxDB 3 Core, InfluxDB 3 Core, as shipped, Iceberg (PyIceberg), Lance, Parquet filesjsonl
  • 2026-10-16Local diskTimelake, TimescaleDB, ClickHouse, QuestDB, InfluxDB 3 Core, InfluxDB 3 Core, as shipped, Iceberg (PyIceberg), Lance, Parquet filesweekly