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 device

The 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 device

Read 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.