Map
โ†‘DuckDB

DuckDB Quack Protocol

Wiki summarydatabaseprotocolduckdbhttpperformance โ†ณ show in map Markdown
title
DuckDB Quack Protocol
type
summary
summary
DuckDB ships an HTTP-based client/server wire protocol; 60M rows in <5s (3ร— Arrow Flight, 32ร— Postgres), beats Postgres on small writes up to 8 threads
tags
database, protocol, duckdb, http, performance
parent
duckdb
created
2026-05-13
updated
2026-05-13

May 2026 announcement from DuckDB of Quack โ€” a new HTTP-based client/server protocol that lets multiple DuckDB instances modify the same database at the same time. Available in v1.5.2 (core_nightly), targeted for production in DuckDB v2.0 in fall 2026. The DuckDB team frames this as "biting the bullet" after years of declining to add a wire protocol โ€” the volume of workarounds people built to bolt client/server onto DuckDB convinced them users wanted it badly enough that doing it themselves was the better tradeoff than leaving the ecosystem to fragment between MotherDuck's protocol, GizmoSQL's Arrow Flight SQL, and ad-hoc RPC layers.

How it works

Two DuckDB instances both load the quack extension. One calls quack_serve(...); the other ATTACHes it as a remote database:

-- Server
INSTALL quack FROM core_nightly;
LOAD quack;
CALL quack_serve('quack:localhost', token => 'super_secret');
CREATE TABLE hello AS FROM VALUES ('world') v(s);

-- Client
INSTALL quack FROM core_nightly;
LOAD quack;
CREATE SECRET (TYPE quack, TOKEN 'super_secret');
ATTACH 'quack:localhost' AS remote;
FROM remote.hello;       -- 'world'

Tables on the remote side are addressable as remote.table. CREATE TABLE remote.t AS ... ships data the other direction. For complex queries, remote.query('SELECT s FROM hello') ships a whole query string to the server for execution.

Protocol design choices

  • HTTP-based. Quack rides on plain HTTP. The DuckDB team's reasoning: HTTP is universally supported by load balancers, auth proxies, firewalls, IDS โ€” and crucially, DuckDB-Wasm in a browser can speak Quack natively. The MIME type is application/duckdb, using DuckDB's internal serialization (already used in the WAL).
  • Request / response, client-driven. Subsequent fetches can run on multiple threads in parallel for large result sets.
  • One round-trip per query. This is the explicit design distinction from Arrow Flight SQL, which always needs two (CommandStatementQuery + DoGet).
  • Default port 9494 โ€” the year Netscape Navigator was released.
  • Auth. Server generates a random token at startup that the client must present; the auth callback is replaceable from SQL (LDAP, file, dice roll). Authorization callback defaults to yes to everything but is also replaceable. Both callbacks can be plain SQL macros โ€” auth-as-SQL is the unusual choice.
  • TLS. Off by default for localhost โ€” the DuckDB team's view is "don't add SSL infrastructure just to talk to yourself." Non-local connections assume SSL on. The recommended deployment is nginx in front terminating Let's Encrypt; documentation walks through it.
  • Default bind: localhost. Quack only listens on the loopback unless explicitly overridden.

Benchmarks

Same-AZ AWS m8g.2xlarge (8 vCPU, 32 GB, up-to-15 Gbps), ~0.28 ms ping. Comparison: Quack vs Arrow Flight SQL (via GizmoSQL, which uses DuckDB underneath) vs PostgreSQL.

Bulk transfer โ€” TPC-H lineitem, median of 5:

Rows DuckDB Quack Arrow Flight PostgreSQL
100k 0.07 s 0.07 s 0.20 s
1M 0.24 s 0.38 s 2.20 s
10M 0.89 s 2.90 s 25.64 s
60M 4.94 s 17.40 s 158.37 s

60M rows (~76 GB CSV) in under 5 seconds. ~3ร— Arrow Flight SQL, ~32ร— Postgres at scale. Postgres is single-threaded reads; Quack and Arrow parallelise.

Small writes โ€” single-row INSERT, 5s window, median of 5:

Threads Quack Arrow Flight PostgreSQL
1 1,038 tx/s 469 839
2 1,956 799 1,094
4 3,504 1,224 2,180
8 5,434 1,358 4,320

Quack outscales Postgres up to 8 threads and then hits DuckDB's concurrent-insert ceiling โ€” Postgres pulls ahead beyond that. The DuckDB team flags this as a known limitation to work on. Arrow Flight is roughly half of Postgres throughout โ€” the two-round-trip floor showing up.

Why not Arrow Flight SQL

The article addresses this head-on. Arrow / ADBC are interchange APIs, like ODBC / JDBC before them โ€” useful for moving data between systems, but DuckDB's internal structures are close-to-but-not-equal-to Arrow, and being bound by a format you don't control is a constraint on future evolution. Two concrete reasons:

  • Format-control freedom โ€” adding a new data type or protocol message in Quack is a same-day ship; Arrow Flight would need spec coordination.
  • The mandatory two round trips (CommandStatementQuery + DoGet) โ€” fine for big analytical queries, bad for small writes in higher-latency networks. Quack does single-round-trip query + result fetch for small queries.

Where it fits

  • In-process databases gaining wire protocols โ€” same arc as SQLite running into a class of users who need cross-process write coordination, except DuckDB shipped it. This is the opposite trajectory from Redis under ambition โ€” Redis started as a wire-protocol-first key-value server and accreted features it didn't need; DuckDB started in-process-first and added a wire protocol because the workaround zoo was getting bigger than the protocol would have been.
  • Database-protocol design โ€” Quack is the cleanest counter-example to "use the existing standard." The DuckDB team's published rationale is a useful reference for similar decisions: we are not letting our query intermediates be defined by a format we don't control, even at the cost of yet-another-protocol.
  • HTTP everywhere โ€” Quack is another data point for "in 2026, building a new TCP-level protocol that isn't on HTTP is a strange choice." The browser-Wasm story is part of the reason; the auth-and-proxy ecosystem is the rest.
  • Concurrent multi-writer over a shared store โ€” alternatives in the wiki: ursa-kafka-storage (S3-backed Kafka), ingodb (self-morphing LSM), lsm-trees-nosql (LSM as the writer-friendly substrate). Quack moves the problem to a single-server bottleneck instead of distributed log; the tradeoffs are different.

Next steps (from the post)

  • DuckLake integration so a DuckDB server can be a remote DuckLake catalog (large performance win for inlining).
  • Polish for v2.0 release in fall 2026; auto-install / auto-load.
  • New parser (new PEG-based parser) used to improve syntax for talking to remote SQL databases.
  • Push past the 8-thread concurrent-insert ceiling in DuckDB itself.
  • Extension API so DuckDB extensions can add protocol messages and handlers.
  • Replication protocol on top of Quack โ€” read-replica clusters.

Acknowledgements in the post name Boaz Leskes (MotherDuck) for sharing MotherDuck-protocol lessons learned and Philip Moore (GizmoSQL) for proving client-server DuckDB was worthwhile.