Quick start
Build the CLI and the Python package from the repository, create a table, load data and query it.
Install
The CLI needs Rust 1.94 (pinned in rust-toolchain.toml):
cargo build --release -p timelake-cli # → target/release/timelake
The Python package needs Python 3.10+ and builds with maturin:
cd crates/timelake-py maturin develop --release # or: pip install .
Choose a warehouse
A warehouse is a root location; tables live under it as namespace/table. Use a local path to try things out, or an object store URL:
export TIMELAKE_WAREHOUSE=./warehouse # local directory export TIMELAKE_WAREHOUSE=s3://my-bucket/lake # S3 (credentials from AWS_* env vars)
For S3-compatible stores and other options, see Storage & configuration.
Load data with the CLI
import creates the table from the first file’s schema if it doesn’t exist, then appends the files. Parquet and CSV (.csv, .csv.gz, .tsv) are supported.
timelake import iot.readings readings.parquet --time-column time --series-key device_id timelake import iot.devices devices.csv # a plain table: no time column timelake info iot.readings # contract, files, partitions, snapshots
Query
timelake sql "SELECT device_id, time_bucket(INTERVAL '1 hour', time) AS hour, avg(temp)
FROM iot.readings
WHERE time >= TIMESTAMP '2026-01-01 00:00:00'
GROUP BY 1, 2 ORDER BY 1, 2"
timelake latest iot.readings # newest row per deviceThe same from Python
import pyarrow as pa
import timelake
lake = timelake.Lake("./warehouse")
t = lake.create_table("iot.readings", batch.schema,
time_column="time", series_key=["device_id"])
t.append(batch) # pyarrow Table/RecordBatch/reader, polars DataFrame, ...
lake.sql("SELECT count(*) FROM iot.readings") # -> pyarrow.Table
lake.latest("iot.readings") # -> pyarrow.Table, one row per deviceRead it from plain DuckDB
INSTALL iceberg; LOAD iceberg;
SELECT * FROM iceberg_scan('./warehouse/iot/readings') LIMIT 10;timelake duckdb iot.readings prints this SQL for a table, including the location of its last-value index.
Keep it healthy
Appends compact small files and expire snapshots inline, so a single writer needs nothing else. To rewrite each partition into one sorted file, apply retention and clean up, run:
timelake maintain # all tables timelake maintain iot.readings # one table
Browse it in the Explorer
This website includes an Explorer: tables and freshness, partitions and snapshots, the newest value per series, a chart for one series, and a read-only SQL console. It reads the lake through the timelake CLI, so it runs where the binary and the warehouse are:
cargo build --release -p timelake-cli # from the repo root cd dashboard && bun install TIMELAKE_WAREHOUSE=./warehouse bun run dev # http://127.0.0.1:3000/explore
TIMELAKE_WAREHOUSE also takes s3://… locations (with TIMELAKE_OPTIONS for storage options). Hosted deployments don't include the CLI; reading from the browser and serverless functions through a WASM build of the reader is in progress.