The Rust SDK for building DuckDB loadable extensions — no C++ required.
What is quack-rs?
quack-rs is a production-grade Rust SDK that makes building DuckDB
loadable extensions straightforward and safe. It wraps the DuckDB C Extension API — the same
API used by official DuckDB extensions — and eliminates every known FFI pitfall so you can
focus on writing extension logic in pure Rust.
DuckDB's own documentation acknowledges the gap:
"Writing a Rust-based DuckDB extension requires writing glue code in C++ and will force you to build through DuckDB's CMake & C++ based extension template. We understand that this is not ideal and acknowledge the fact that Rust developers prefer to work on pure Rust codebases."
quack-rs closes that gap. No C++. No CMake. No glue code.
What you can build
| Extension type | quack-rs support |
|---|---|
| Scalar functions | ✅ ScalarFunctionBuilder |
| Overloaded scalars | ✅ ScalarFunctionSetBuilder |
| Aggregate functions | ✅ AggregateFunctionBuilder |
| Overloaded aggregates | ✅ AggregateFunctionSetBuilder |
| Table functions | ✅ TableFunctionBuilder |
| Cast / TRY_CAST functions | ✅ CastFunctionBuilder |
| Replacement scans | ✅ ReplacementScanBuilder |
| SQL macros (scalar) | ✅ SqlMacro::scalar |
| SQL macros (table) | ✅ SqlMacro::table |
Copy functions (COPY TO) | ✅ CopyFunctionBuilder (requires duckdb-1-5) |
Note: Window functions have no counterpart in DuckDB's public C Extension API and cannot be implemented from Rust (or any language) via that API. See Known Limitations.
Why does this exist?
quack-rs was extracted from
duckdb-behavioral, a production DuckDB
community extension. Building that extension revealed 16 undocumented pitfalls in DuckDB's
Rust FFI surface — struct layouts, callback contracts, and initialization sequences that
aren't covered anywhere in the DuckDB documentation or libduckdb-sys docs.
Three of those pitfalls caused extension-breaking bugs that passed 435 unit tests before being caught by end-to-end tests:
- A SEGFAULT on load (wrong entry point sequence)
- 6 of 7 functions silently not registered (undocumented function-set naming rule)
- Wrong aggregate results under parallel plans (combine callback not propagating configuration fields to fresh target states)
quack-rs makes each of these impossible through type-safe builders and safe wrappers.
The full catalog is documented in the Pitfall Reference.
Key features
- Zero C++ — no
CMakeLists.txt, no header files, no glue code - All C API function types — scalar, aggregate, table, cast, replacement scan, SQL macro, copy function (
duckdb-1-5) - Panic-free FFI —
init_extensionnever panics; errors surface viaResult - RAII memory management —
LogicalTypeandFfiState<T>prevent leaks and double-frees - Type-safe builders —
ScalarFunctionBuilder,AggregateFunctionBuilder,TableFunctionBuilder,CastFunctionBuilder,ReplacementScanBuilder - SQL macros — register
CREATE MACROstatements without any FFI callbacks - Testable state —
AggregateTestHarness<T>tests aggregate logic without a live DuckDB - Scaffold generator — produces a submission-ready community extension project from code
- 16 pitfalls documented — every known DuckDB Rust FFI pitfall, with symptoms and fixes
Navigation
New to DuckDB extensions? → Start with Quick Start
Adding quack-rs to an existing project? → See Installation
Writing your first function? → See Scalar Functions or Aggregate Functions
Want SQL macros without FFI callbacks? → See SQL Macros
Submitting a community extension? → See Community Extensions
Something broke? → See Pitfall Catalog