Embedded analytics (DuckDB-style)
Embedded analytics (DuckDB-style)
LessDB embeds into Python and Node processes the way DuckDB does — one library call, zero servers, Arrow everywhere.
Python
import lessdb
import pandas as pd
db = lessdb.open("analytics.less") # in-process engine
db.sql("""
CREATE TABLE orders (id Int64, sku Utf8, qty Int32, ts Timestamp)
ENGINE=MergeTree ORDER BY (sku, ts)
""")
df = pd.read_parquet("orders.parquet") # any Arrow-native source
db.insert("orders", df) # pyarrow interop, zero copies
print(db.sql("SELECT sku, sum(qty) FROM orders GROUP BY sku").to_pandas())
Node
import { open } from "lessdb";
const db = open("analytics.less");
await db.sql(`CREATE TABLE t (x Int64, y Float64) ENGINE=MergeTree ORDER BY x`);
await db.insert("t", arrowTableFromAnywhere); // Arrow IPC buffers
const batches = await db.sql("SELECT x, sum(y) FROM t GROUP BY x");
Why it feels native
- Arrow IPC is the wire format —
pyarrow/pandas/JS Arrow objects
go in and come out without conversions.
- Parquet is the storage format — existing files load straight in;
LessDB's own parts open in DuckDB/pandas/Spark unchanged.
- Same engine as the server — the code you embed is the code that
runs the 100M-row ClickBench table: merge trees, pruning, bounded merges, GPU kernels, MCP tools.
The ladder
Start embedded (one process, one file), then serve it (less server), then share it (point the same schema at s3:///R2 and add compute nodes) — the query layer and file format never change along the way.
See Getting started for the 11-step quickstart and the CLI/TUI tour.