DuckDB extension · pure C

DuckDB, on the network.

ducknng turns a DuckDB session into an NNG service — and into an NNG client. Framed RPC with Arrow and Quack payloads, query sessions, mTLS and policy admission in C, and an HTTP carrier. Anything that speaks NNG, WebSocket, or HTTP can call it: nanonext from R, a browser, your own client in any language, or another DuckDB.

Get started Read the protocol GitHub

inproc:// ipc:// tcp:// tls+tcp:// ws:// wss:// http:// https://

ANY NNG, WEBSOCKET, OR HTTP PEER nanonext (R) pynng · Go · Rust · C browser (duckdb-wasm) another DuckDB session DuckDB session running ducknng ducknng_start_server() framed call · Arrow or Quack result batches · end-of-stream ipc:// · tcp:// · tls+tcp:// · ws:// · wss:// · http:// Either side may be DuckDB: ducknng is a client as well as a server.

Get started

Two DuckDB sessions, three steps, no broker in between.
1

Load the extension

Build it first (see Development), then load the artifact into any DuckDB session.

LOAD 'build/release/ducknng.duckdb_extension';
2

Serve a session over TLS

Port 0 lets the OS assign a free port, and the self-signed certificate lives only in DuckDB memory — no files to manage.

Server session
SET VARIABLE tour_tls = ducknng_self_signed_tls_config('127.0.0.1', 365, 0);

SELECT ducknng_start_server(
  'tour',                            -- service name
  'tls+tcp://127.0.0.1:0',           -- TLS; port 0 = OS-assigned
  1,                                 -- REP contexts
  134217728,                         -- recv_max_bytes (128 MiB)
  300000,                            -- session_idle_ms
  getvariable('tour_tls')::UBIGINT   -- TLS config handle
);

SELECT name, listen FROM ducknng_list_servers();
namelisten
tourtls+tcp://127.0.0.1:41573
3

Query it from another session

The URL scheme picks the carrier. The same call works over ipc://, tcp://, wss://, or https:// without changing the method contract.

Client session · remote rows
SELECT *
FROM ducknng_query_rpc(
  'ipc:///tmp/ducknng.ipc',
  'SELECT i, i > 10 AS gt_10
     FROM rpc_demo_t ORDER BY i',
  0::UBIGINT
);
igt_10
7false
11true
42true
Client session · discovery
SELECT ok, type_name, name
FROM ducknng_decode_frame(
  ducknng_request_raw(
    getvariable('tour_url'),
    from_hex('0100000000000000000000
              00000000000000000000'),
    1000, getvariable('tour_tls')::UBIGINT
  )
);
oktype_namename
trueresultmanifest

Run it in your browser

The same extension compiles to a duckdb-wasm side module. The demo loads it in your own tab, runs the smoke checks, and opens a SQL shell against that connection — no server, no install.

Open the browser demo Support contract

SELECT provider, media_types
FROM ducknng_list_codecs()
ORDER BY provider
LIMIT 3;
providermedia_types
arrowapplication/vnd.apache.arrow.stream
ducknngapplication/vnd.ducknng.frame
jsonapplication/json

How it is layered

Each layer is separately contracted, so the one below can change without the one above.
TransportNNG sockets and listeners. Synchronous send and receive, one-shot AIO handles, pipe-event telemetry.
Framed RPCA versioned envelope carrying Arrow IPC or JSON control text, with an explicit status byte. HTTP and HTTPS mount the same methods at a URL path.
PolicyFast C admission: mTLS, exact peer-identity allowlists, IP and CIDR allowlists, per-service and per-principal limits, optional SQL authorizer.
CodecsContent-type-tagged bodies: JSON, Arrow IPC, ducknng frames, the Quack batch media type, and text or raw fallback. User codecs extend the set.

Where next

Eight published contracts. Everything else lives in the repository.
ProtocolEnvelope, statuses, session lifecycle ReferenceEvery SQL function TypesWhat crosses the wire TransportsChoosing a carrier by URL HTTPThe HTTP and HTTPS binding Browserduckdb-wasm client scope SecurityAdmission and the trust boundary DemoRun ducknng in a tab
Status. ducknng is pre-1.0 and the SQL surface is still sealing. The protocol envelope, supported types, and lifetime rules in the pages above are binding; anything not written there is subject to change.