Timelaketimelake
DocsBenchmarksRoadmapSpecContribute
Apache 2.0 ·
Roadmap

DoneIn progressPlanned

Tables and storage

Done:1. Iceberg tablesDone:2. CommitsDone:3. Object-store catalogIn progress:4. Time-series table contractIn progress:5. File layout and encodingsIn progress:6. Last-value indexDone:7. One-request table state and version checksDone:8. Table format versions and upgradesDone:9. SettingsPlanned:10. Supplemental timestamps

Writing

Done:11. AppendsDone:12. Late data and dedup on readDone:13. Writes from WebAssemblyPlanned:14. Hot tier and seconds-fresh readsPlanned:15. BackfillIn progress:16. Import and migrationPlanned:17. DeletesPlanned:18. GDPR erasure

Maintenance

Done:19. CompactionIn progress:20. Maintenance runs, retention and expiry

Reading

In progress:21. Timelake readerDone:22. Block cacheDone:23. Filter pushdownDone:24. Pruning with long IN listsDone:25. Newest-first scansDone:26. Scans in series orderDone:27. Materialized rollups

SQL functions

In progress:28. Function libraryDone:29. Time buckets and gap fillingDone:30. Signal aggregatesDone:31. Downsampling with m4

Integrations

Planned:32. REST catalogPlanned:33. DuckDB extensionPlanned:34. Snowflake connectionPlanned:35. Multitenancy

Services

Planned:36. Ingestion and rulesPlanned:37. Data to eventsPlanned:38. Static read modelsPlanned:39. Computed metricsPlanned:40. Agent access with permission setsPlanned:41. Device syncPlanned:42. Edge gatewayPlanned:43. Server mode

Benchmarks

In progress:44. Benchmark harness: timebenchIn progress:45. Industrial IoT benchmarkPlanned:46. Agent benchmark

Background

ArchitectureDeployment and cost modelEmbedded engine: DataFusionLandscape and positioningLicense and open corePurpose and requirementsReleases
TimelaketimelakeThe open time-series lakehouse.
v0 · Apache 2.0 · Contribute · GitHubBuilt on Apache Arrow, Apache DataFusion, Apache Parquet, and Apache Iceberg.
DocsBenchmarksRoadmapSpecContribute

Spec 9 · Tables and storage

Settings

DoneUpdated 2026-10-20View on GitHub
Versions
0.5.0, unreleased
Roadmap
Installable, upgradable, switchable
Related
4. Time-series table contract, 21. Timelake reader

Summary

Every engine feature has a setting that turns it on or off or picks its behaviour, at the table, session or call level, declared once in a registry that drives validation, SHOW, the CLI and the docs.

Design

Principle. Every engine feature has a setting that turns it on or off or picks its behaviour, a bit like Postgres's configuration variables. During fast development this keeps trade-offs explicit, lets benchmarks measure each feature on and off, and records how behaviour changed.

One registry. Every setting is declared once (in timelake-format): name, type, default, the levels it may be set at, a description, and the version that added it. From it come the docs page, SHOW timelake.* in SQL, timelake settings on the CLI, and validation: an unknown name or a bad value is an error, not ignored.

Levels, the more specific winning:

LevelHow it's setLifetime
Built-in defaultthe registry—
Tabletable property timelake.<name>, at creation or later (timelake alter, Table.set_properties)stored in the table, applies to every reader and writer
SessionSQL SET timelake.<name> = …; Session / Lake options in Rust and Python; --set <name>=<value> on the CLIone connection or process
CallAppendOptions, MaintainOptions, …one call

A setting declares which levels it allows: the time column and series key only at creation; read settings at every level; write settings at table and call level.

First settings:

SettingValues (default)LevelsMeaning
read-dedupon, off (on when dedup is on)table, sessionRemove copies when the Timelake reader reads (spec 12)
read-dedup-strategymerge, keys-first (decided by benchmark)table, sessionHow copies are removed on read (spec 12)
append-dedupon, off (on when dedup is on)table, callKeep only the last of equal keys within one append (not built, see below)
ingest-time-columna column name, or none (_ingest_ts)creationInsertion time per row (spec 12), built
latest-bya column (_ingest_ts)tableWhich copy of a row is the latest write (spec 10, proposed)
as_of_inserteda timestamp, or nonesessionLeave out rows inserted after it, before dedup (spec 10, proposed)
compact-cold-aftera duration, or off (1h)table, callFull compaction of partitions whose time range has ended (spec 12)
version-check-intervala duration (1s)table, sessionHow long the reader uses a table version without checking for a newer one (spec 7), built
data-page-rowsa count (20,000; 8,192 when written from WebAssembly)tableRows per Parquet data page (spec 13), built

The existing timelake.* properties become registry entries unchanged. Hard-coded behaviour moves into settings as it's touched: compaction tiers, the small-file ratio, scan parallelism. The planning cache's lifetime became version-check-interval.

Decided 2026-10-16:

  • Names in SQL use underscores (SET timelake.read_dedup = off); every spelling (dashes, underscores, with or without timelake.) names the same setting.
  • No locked settings: a session override is the reader's choice.
  • No environment variables until something needs them.

Built 2026-10-16:

  • The registry is timelake_format::settings: name, kind, default, levels, the version that added it, description, and a value check. A test keeps it in step with the contract's properties and defaults.
  • Table level: properties are checked at creation and by Table::set_properties (CLI timelake alter --set/--unset, Python Table.set_properties). Unknown timelake.* names, bad values and settings not allowed at the table level are errors; properties a newer Timelake wrote are ignored when reading.
  • Session level: every setting the registry allows there can be SET, shown with SHOW, passed with --set, or given to Python's Lake(settings=…). The CLI's --set no longer panics on a bad key.
  • timelake settings [table] [--json] lists them; the docs page "Settings" renders the same list (dashboard/lib/settings.json, checked by a test).
  • Unreleased: a setting's kind is a type (settings::Kind) that names its values for the docs and checks them; a setting with a fixed set of values is an enum (timelake_format::value) that the contract, the registry and the reader share. A table property outside its set is an error when the table is opened, naming the property, as a bad boolean or duration was: series-order used to fall back to auto and float-encoding to dictionary. Iceberg's compression codec and level are checked together at creation and by set_properties; set by another engine, a bad one fails writes, never reads.
  • Changes from the proposal: dedup is fixed at creation (files written with it off may hold copies, which dedup on read assumes they don't). append-dedup isn't built for the same reason: an append that keeps copies would need its files marked for the reader. format-version is managed by Timelake (create, upgrade) and can't be set by hand. latest-by and as_of_inserted wait for spec 10. Storage options (timelake_freshness_check, …) stay lake options, documented on the Storage page.

Open questions and issues

None open.

History

  • 2026-10-16: built (SPEC.md §21.9)
  • 2026-10-19: 35 settings
  • 2026-10-19: moved from SPEC.md into its own spec.
  • 2026-10-19: was spec 25; specs regrouped one per feature, with milestones on the roadmap.
  • 2026-10-20: typed kinds and values; values outside a setting's set are errors when a table is opened