Skip to main content

Quack on Demand: multi-tenant SQL gateway for DuckDB and DuckLake

Quack on DemandQuack on Demand

Quack on Demand is a multi-tenant SQL gateway for DuckDB and DuckLake. It puts a single, governed, horizontally-scaled SQL endpoint in front of many DuckDB engines that share DuckLake catalogs, so a fast embedded database becomes a service that teams and applications can query together.

It serves two wires from that one endpoint: Arrow Flight SQL for the JDBC / ODBC / ADBC estate, and DuckDB's own Quack protocol, so any DuckDB carrying the quack extension can ATTACH the gateway as a database with no driver in between.

What it does​

Clients speak Arrow Flight SQL or the native Quack protocol to the gateway. Either way, it authenticates the connection, authorizes every statement against a role-based access model, classifies it read or write, and routes it to the least-loaded DuckDB node that can serve it (on object-store pools, biased toward a node that already has the query's tables cached). The nodes read and write Parquet through shared DuckLake catalogs, so they present one consistent view and a pool can scale out across many of them.

The two wires are two front doors to the same gateway, not two products: same tenants, same users, same per-statement ACL, column masking and row filters, same router, same audit log. Only the wire differs.

In other words, it adds the things a single embedded DuckDB does not have on its own: multi-tenancy, authentication and per-statement access control, horizontal scale, and a stable client endpoint, without replacing DuckDB as the engine.

Why it exists​

DuckDB is excellent for fast analytics, and DuckLake gives it a durable, object-store-backed catalog. But on their own they are single-process: there is no shared endpoint, no notion of tenants or users, no access control on a query, and no way to spread load across nodes. Teams that want to expose DuckDB/DuckLake data to many users or applications end up rebuilding the same gateway concerns each time. Quack on Demand is that gateway, built once: connection management, identity, authorization, routing, failover, and observability around the engine you already use.

When to use it​

Reach for Quack on Demand when you want to:

  • Serve many users or applications from shared DuckDB/DuckLake data through one governed endpoint, instead of handing out database files.
  • Enforce access control on every query: role-based, per-table permissions with tenant isolation, applied before a statement touches a node.
  • Scale horizontally: spread read and write traffic across a pool of DuckDB nodes over a single shared catalog, with least-loaded routing (cache-aware on object-store pools) and retry on failure.
  • Isolate tenants: keep each tenant's databases, users, and compute separate, with its own auth provider.
  • Federate external sources (Postgres, S3 / Iceberg, anything DuckDB can attach) behind the same SQL surface and the same access model.
  • Keep the clients you already have: Arrow Flight SQL covers JDBC, ADBC, ODBC, PyArrow, DBeaver, and Spark, which all connect the same way.
  • Attach the gateway from DuckDB itself over DuckDB's native Quack protocol (ATTACH 'quack:host:9494' AS qod), so a laptop DuckDB, a notebook, or an embedded engine joins its local tables with governed shared tables in one query, with no driver to install. See DuckDB (native Quack).
  • Give AI agents governed data access: an embedded MCP server lets agents such as Claude Code discover schemas and run SQL with the same per-statement access control as any other client.

When not to use it​

It is the wrong tool when:

  • One user or app queries a local DuckDB file. Use DuckDB directly. The gateway adds operational machinery (a manager, Postgres, pools) that only pays off when you need sharing, isolation, or scale.
  • You do not need multi-tenancy, access control, or horizontal scale. If none of the reasons above apply, the gateway is overhead.
  • You need OLTP semantics or cross-node transactions. This is an analytical query gateway: transactions pin to a single node, and it is not a substitute for a transactional database.
  • You need engine features DuckDB does not have. The gateway executes DuckDB SQL; it routes and governs queries, it does not extend the engine.

What is inside​

CapabilityIn short
Client protocolsArrow Flight SQL (:31338) and DuckDB's native Quack protocol (:9494), one identity and policy model behind both
Multi-tenancyTenants own databases (DuckLake catalogs) and pools of DuckDB nodes
Access controlAuthentication (database, JWT, OIDC) plus role-based, per-statement table ACL
RoutingStatement classification, least-loaded node selection (cache-aware on object-store pools), transaction pinning, retry-once
StorageDuckLake catalogs over a filesystem or S3-compatible object store
FederationAttach external catalogs (Postgres, S3/Iceberg) under the same ACL
AI agentsEmbedded MCP server with personal-access-token auth; every tool call goes through the same RBAC
OperationsPrometheus / cloud metrics, a config manifest for backup and restore, an admin UI
DeploymentA single Docker container on one node (ideal for a single tenant), or Kubernetes for multi-host fleets and manager HA

Looking for something specific?​

The DuckDB how-tos answer the questions people arrive with, one page each: access control, authentication, single sign-on, ADBC, a Flight SQL server and multi-tenancy.

Where to go next​

Questions or feedback? Join the community on Discord or open an issue on GitHub.

QoD and Starflow​

QoD is a standalone product; you do not need Starflow to run it. If you use Starflow, the starlake quack command can host a Quack DuckDB server inside the Starflow process for local, single-node use, and Starflow can query a QoD fleet as a regular connection, over either wire: ATTACH 'quack:host:9494' from its DuckDB engine, or a Flight SQL driver. For multi-tenant fleets with autoscaling and ACLs, use QoD.