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 10 · Tables and storage

Supplemental timestamps

PlannedUpdated 2026-10-16View on GitHub
Versions
Not released yet
Roadmap
Data lifecycle, Technical preview
Related
4. Time-series table contract, 12. Late data and dedup on read

Summary

Declare the other times a sample carries (server, gateway, sent, corrected) in the contract, choose which time decides the latest copy of a row (latest-by), record per commit the ranges and delays of each time, and query a table as of an insertion time. Proposed, waiting for review.

Design

The need. A sample often carries more than one time. In industrial data the source (a PLC or sensor) stamps when it measured; a server or gateway stamps when it received the value (OPC UA sends both: SourceTimestamp and ServerTimestamp); a device stamps when it sent a store-and-forward batch; a correction carries when it was made. Timelake adds its own insertion time (_ingest_ts, spec 12). Users want to keep these times, query them, measure delays between them, and sometimes decide by one of them which copy of a reading is current.

Today they can already be ordinary timestamp columns: stored, queried, and pruned on (every column has Iceberg min/max bounds). What Timelake doesn't know is what they mean.

Proposal: declare them in the contract.

  • Declaring: timelake.supplemental-time-columns = server_ts, sent_ts at creation (supplemental_time_columns=[…] in Python, --time-columns server_ts,sent_ts on the CLI). Each must be a timestamp; it is stored as µs UTC like the time column. Adding one later waits for schema evolution.
  • Which copy wins (setting latest-by, spec 9): by default the latest _ingest_ts, then the later commit. A table can instead name a column, for example latest-by = server_ts, so a resent old reading never overrides a newer correction however late it arrives; _ingest_ts and commit order still break ties. Dedup on read, compaction, the last-value index and in-append dedup all use the same order. A numeric version column would work the same way; whether to allow non-timestamp columns is a question below.
  • What arrived when, from metadata: each commit records the min and max of every supplemental time and of _ingest_ts in its snapshot summary, next to the time ranges it touched (spec 12). "Which partitions got data the server stamped after 10:00" and freshness dashboards then need no scan.
  • Delays: per commit, the largest gap between the time column and _ingest_ts (and each supplemental time) goes in the snapshot summary, so store-and-forward lateness is visible per gateway or table without a query; SQL can compute it per row (_ingest_ts - time).
  • As of an insertion time: SET timelake.as_of_inserted = '2026-01-05 10:00' answers "what did we know at 10:00": rows inserted later are left out before dedup, so a reading corrected at 10:30 shows its 10:00 value. It reads only _ingest_ts, or the column latest-by names.

Questions for review:

  • Names: supplemental-time-columns and latest-by, or role names (server-time-column, sent-time-column) that tools could rely on, OPC UA style?
  • Non-timestamp latest-by: allow a version number or sequence column, or timestamps only?
  • As-of: a session setting (switchable, works in any SQL), or also a table function (as_of_inserted('iot.readings', TIMESTAMP …)) for one table in a join?
  • Writers that don't fill them: a supplemental column may be null (the source didn't send it); latest-by then falls back to _ingest_ts for those rows. Or require it?

Open questions and issues

  • #118 Review: supplemental timestamps (names, latest-by, as-of)

History

  • 2026-10-16: proposed (SPEC.md §7.4)
  • 2026-10-19: moved from SPEC.md into its own spec.
  • 2026-10-19: was spec 7; specs regrouped one per feature, with milestones on the roadmap.