Autoscale DuckDB fleets
on demand.
From a single Docker container on one node to fleets of DuckDB Quack nodes on your own Kubernetes. Per-tenant isolation, fine-grained ACLs, federated queries. Query it from any ODBC/JDBC/ADBC client. Works with any ETL.
# One endpoint, JDBC / ADBC / ODBC / PyArrow
conn = flight_sql.connect(
"grpc+tls://gateway:31338",
db_kwargs={
"username": "alice", "password": "•••",
tenant: "acme", pool: "analytics"})
# routed to the least-loaded node for the tenant
cur = conn.cursor()
cur.execute("SELECT count(*) FROM orders")
cur.fetchone()
(1500000,)From a single database to a fleet
$ uvx qod start
control-plane Postgres: jdbc:postgresql://localhost:5432/qod (user postgres)
Quack on Demand 0.5.0 is up
control plane : jdbc:postgresql://localhost:5432/qod
REST API + UI : http://localhost:20900 (UI: http://localhost:20900/ui)
FlightSQL : grpc+tls://localhost:31338
Client connection strings (replace <tenant>, <pool>, <user>):
JDBC : jdbc:arrow-flight-sql://localhost:31338/?tenant=<tenant>&pool=<pool>&user=<user>&useEncryption=true&disableCertificateVerification=true
ADBC : uri=grpc+tls://localhost:31338 (adbc_driver_flightsql)
ODBC : Driver={Arrow Flight SQL ODBC Driver};Host=localhost;Port=31338;...
From zero to SQL in one command
One command boots the whole platform: manager, FlightSQL endpoint, admin UI, and demo data. No cluster, no YAML, no prerequisites beyond Python and a JVM.
The boot banner hands you working JDBC, ADBC, and ODBC connection strings. Paste one into your tool and you are querying.
qod> SELECT o_orderpriority, count(*) FROM orders GROUP BY 1 ORDER BY 1; +-----------------+----------+ | o_orderpriority | count(*) | +-----------------+----------+ | 1-URGENT | 30044 | | 2-HIGH | 30076 | | 3-MEDIUM | 29949 | +-----------------+----------+ 3 rows in 0.04s
Talk to it from anything that speaks SQL
One Arrow FlightSQL endpoint serves every client: JDBC and ODBC for BI tools, ADBC and Python for notebooks, the qod CLI for your terminal.
Statements are classified read or write and routed to the least-loaded node that can serve them, with transaction pinning, behind that single endpoint.
A real multi-tenant control plane
Tenants own databases, users, and pools of DuckDB nodes, isolated by storage layout and access control.
Idle pools suspend to zero nodes and keep their catalogs; the first query wakes them automatically. You pay for compute only while queries run.
| c_phone | c_mktsegment |
|---|---|
| *** | BUILDING |
| *** | BUILDING |
| *** | BUILDING |
| c_phone | c_mktsegment |
|---|---|
| 25-989-741-2988 | BUILDING |
| 23-768-687-3665 | AUTOMOBILE |
| 13-761-547-5974 | MACHINERY |
Every user sees only their data
The same query, two users, two answers: that is the access-control model working.
Tenant isolation at the edge, per-table grants (read, write, DDL), row-level security filters, and column masking are all enforced before a statement ever reaches a node.
Your data has an undo button
DuckLake gives every table a history: time-travel reads, named tags, undrop for deleted tables, and restore that rolls back as a new snapshot with nothing lost.
Mistakes stop being incidents and become queries.
See everything
Per-statement history with latency and routing, a full audit trail, usage trends per tenant, and Prometheus metrics for your dashboards.
Start on a laptop. Grow to a cluster.
The single-container mode is first-class, not a demo: run it on one box for years if that is all you need.
When you outgrow it, point the same gateway at your Postgres and object store, then move to Kubernetes with pools of pods and HA managers. Your clients never notice: same endpoint, same tenants, same SQL.
Reach for it when sharing matters.
Many users on shared DuckDB/DuckLake data, access control on every query, horizontal scale, tenant isolation, or federation. Querying one local file? Use DuckDB directly.