adbc-driver-quack — Arrow Database Drivers tool screenshot
Arrow Database Drivers

adbc-driver-quack: Open-Source Arrow Database Driver [N/A+ Stars]

8 min read·

adbc-driver-quack turns remote DuckDB Quack sessions into Arrow-native reads and writes, returning real `RecordBatch` objects and streaming `Statement.BindStream` ingest without row-by-row cursor overhead.

Pricing

Open-Source

Tech Stack

Apache Arrow, ADBC, DuckDB Quack, Python DB-API, Go

Target

Python and Go developers moving Arrow data into DuckDB

Category

Arrow Database Drivers

What Is adbc-driver-quack?

adbc-driver-quack is one of the best Arrow Database Drivers tools for Python and Go developers moving data in and out of DuckDB. Built by GizmoData, it wraps DuckDB's Quack remote protocol so clients can fetch Apache Arrow RecordBatches from a remote server and bulk ingest Arrow streams back through ADBC; the project ships a PyPI wheel for macOS, Linux, and Windows on x64 and arm64, plus a Go module, and the first release is v0.1.0-alpha.1.

This matters when you want a remote database session to behave like an Arrow pipe instead of a row-oriented driver. adbc-driver-quack is one of the best adbc-driver-quack for Python and Go developers moving Arrow data into DuckDB because it preserves columnar semantics end to end and keeps the client API close to the standard ADBC model.

Quick Overview

AttributeDetails
TypeArrow Database Drivers
Best ForPython and Go developers moving Arrow data into DuckDB
Language/StackApache Arrow, ADBC, DuckDB Quack, Python DB-API, Go
LicenseMIT
GitHub StarsN/A
PricingOpen-Source
Last Releasev0.1.0-alpha.1

Who Should Use adbc-driver-quack?

  • Data engineers piping Arrow tables between services who want a remote DuckDB endpoint without converting to CSV, JSON, or ad hoc row loops.
  • Platform teams standardizing on ADBC and Apache Arrow who need one transport that works from Python and Go against the same DuckDB Quack server.
  • Backend developers building ingestion jobs that need create_append, replace, or append semantics over a network connection.
  • Analytics engineers who already consume pyarrow.Table, Polars, Pandas, or ibis and want the source or sink to stay Arrow-native.

Not ideal for:

  • Embedded-only DuckDB workloads where an in-process duckdb package is simpler and the network hop adds no value.
  • Teams that want GA stability only, because adbc-driver-quack is still alpha and should be treated as pre-1.0 software.
  • Systems where you cannot manage the server token or Quack extension because the client expects a Quack-capable DuckDB server and an auth string.

Key Features of adbc-driver-quack

  • Arrow RecordBatch query path — adbc-driver-quack returns remote query results as Arrow batches instead of row objects. That makes the output directly usable in pyarrow, Polars, Pandas, ibis, or any downstream code that already speaks Arrow.
  • Bulk ingest via Statement.BindStream — adbc-driver-quack supports the standard ADBC bulk-load path and maps each Arrow batch into an APPEND_REQUEST. That is the right shape for column-oriented loads and avoids row-by-row inserts.
  • Streaming reads with bounded memoryCursor.fetch_record_batch() exposes a pyarrow.RecordBatchReader that pulls one server-side DataChunk per read_next_batch() call. Memory stays bounded by the server chunk size, which the README describes as roughly 2k rows per chunk.
  • Python and Go distribution — the same project ships as a Python wheel and a Go module. That matters if one service uses adbc_driver_quack.dbapi and another loads github.com/gizmodata/adbc-driver-quack directly.
  • DB-API wrapper plus direct driver loading — adbc-driver-quack works through quack.connect() for the common Python path, and it also works through adbc_driver_manager.dbapi.connect when you want to manage the bundled shared library yourself.
  • Token-based Quack connection config — the client uses a simple URI format, quack://host[:port], with adbc.quack.token passed in db_kwargs. That keeps the transport explicit and avoids hidden connection state.
  • Transaction control is explicitautocommit is off by default, so writes only persist after conn.commit() unless you opt into autocommit. That is safer for multi-statement ingest jobs, but it will surprise anyone expecting implicit commit-on-close behavior.

adbc-driver-quack vs Alternatives

ToolBest ForKey DifferentiatorPricing
adbc-driver-quackRemote DuckDB over Quack with Arrow reads and writesNative ADBC support for Quack plus Arrow RecordBatch streamingOpen-Source
adbc-driver-managerGeneric ADBC client loading many different driversOne client API across many backends, not Quack-specificOpen-Source
quack-jdbcJVM services that need Quack over JDBCJava/Kotlin/Scala friendly driver surfaceOpen-Source
duckdb Python packageEmbedded local analytics and SQL in-processNo remote driver layer, just the DuckDB engine in PythonOpen-Source

Pick adbc-driver-quack when your code already depends on Arrow and the server is DuckDB with Quack enabled. Pick DataHaven when the real goal is storing or sharing the resulting data set instead of moving it, because adbc-driver-quack is the transport layer, not the warehouse.

Pick adbc-driver-manager when you need one Python entry point for several database engines and do not want a Quack-specific dependency. Pick quack-jdbc when the application stack is JVM-first, and pick duckdb when the best answer is to skip the network and run SQL in process.

If you are tracing a failed login, host binding mismatch, or an unexpected rollback, OpenTrace is useful around the driver because the failure mode is usually in the request path, not in Arrow itself. The driver only moves batches; the surrounding observability has to explain why the server refused them.

How adbc-driver-quack Works

adbc-driver-quack sits between an ADBC client and a DuckDB server that has the Quack extension loaded. The client opens quack://host[:port], passes adbc.quack.token for auth, and then talks to the server in Arrow-shaped batches instead of fetching one row at a time.

The design is intentionally small. Query execution returns Arrow RecordBatches, while ingest uses the ADBC bulk path so each Arrow batch becomes an APPEND_REQUEST on the wire. That keeps the protocol aligned with columnar storage and makes the same driver useful for reads, writes, and streaming transforms.

from adbc_driver_manager import dbapi
import adbc_driver_quack

with dbapi.connect(
    driver=adbc_driver_quack._driver_path(),
    entrypoint='QuackDriverInit',
    db_kwargs={
        'uri': 'quack://localhost:9494',
        'adbc.quack.token': 'my-secret-token',
    },
) as conn, conn.cursor() as cur:
    cur.execute('SELECT 42 AS answer')
    table = cur.fetch_arrow_table()

That example loads the bundled driver directly, connects to a Quack endpoint, and fetches the result as a real Arrow table. The important part is that the data stays columnar the whole time, so downstream code can pass it to Polars, Pandas, or another Arrow consumer without a copy-heavy rewrite.

On the server side, DuckDB must be new enough to support Quack, and the README uses DuckDB v1.5.2+ with INSTALL quack FROM core_nightly; LOAD quack;. The server lives inside the DuckDB session until that session exits, which makes the deployment model lightweight but also means the lifetime is tied to the REPL or process that started it.

Pros and Cons of adbc-driver-quack

Pros:

  • Arrow-native output — results come back as pyarrow.Table or RecordBatchReader, which keeps the client path aligned with columnar processing.
  • Fast bulk ingest pathadbc_ingest uses the standard ADBC create/append modes, so large loads can stay batch-oriented instead of paying per-row overhead.
  • Works in Python and Go — one protocol, two client surfaces, which is useful for mixed-language data platforms.
  • Direct driver loading is supported — you can use the wrapper or hand the driver to adbc_driver_manager, which makes integration into existing ADBC code easier.
  • Memory stays bounded during streaming — record batches are pulled incrementally, so giant queries do not have to materialize the whole result at once.

Cons:

  • Alpha statusv0.1.0-alpha.1 means API and behavior can still change, so this is not a drop-in choice for conservative production fleets.
  • Quack server dependency — the client only works when DuckDB is running the Quack extension, so there is extra server setup compared with local DuckDB.
  • Transaction defaults are easy to miss — autocommit is off by default, and forgetting conn.commit() can roll back a load that looked successful.
  • Protocol scope is narrow — adbc-driver-quack is specific to DuckDB's Quack remote protocol, not a universal driver for arbitrary databases.
  • Auth and host binding can be fiddly — the README calls out localhost versus 127.0.0.1 edge cases, which is the kind of networking detail that shows up in real deployments.

Getting Started with adbc-driver-quack

Install the Python wheel first, or grab the Go module if your service is written in Go.

pip install adbc-driver-quack pyarrow
# or
# go get github.com/gizmodata/adbc-driver-quack@latest

Start a Quack-enabled DuckDB session, then launch the server endpoint.

INSTALL quack FROM core_nightly;
LOAD quack;
CALL quack_serve('quack:localhost:9494', token=>'my-secret-token');

After the server starts, connect from Python with quack.connect() and run a simple query or an ingest job. If you are writing data, set autocommit=True or call conn.commit() before the connection closes, because adbc-driver-quack follows ADBC transaction rules and will roll back uncommitted work.

Verdict

adbc-driver-quack is the strongest option for Arrow-native access to DuckDB over Quack when you want Python and Go clients on the same wire protocol. Its best strength is returning real Arrow batches with bounded-memory streaming, while the main caveat is alpha status and explicit transaction handling. Choose it when you value columnar I/O over row APIs.

Frequently Asked Questions

Looking for alternatives?

Compare adbc-driver-quack with other Arrow Database Drivers tools.

See Alternatives →

You Might Also Like