Skip to main content
DuckDB’s functionality is extended by first-party extensions: JSON, Parquet, ICU (timezones and collations), spatial, and more. With better-duck an extension reaches a connection in one of two ways, and which one you pick is the central decision of this page.

Bundled at build time

The core features json, parquet, and icu compile that extension into the embedded static library (forwarded to better-duck-sys). The extension is then available with no runtime INSTALL / LOAD — the right choice for offline and embedded builds (Tauri, iOS) where downloading an extension at runtime isn’t an option.
Bundling an extension recompiles a DuckDB variant, so builds that enable json / parquet / icu take noticeably longer than a plain build. See Installation for build-time guidance.

Loaded at runtime

Extensions without a bundling feature — most notably spatial — load at runtime. The Connection extension methods drive INSTALL / LOAD and read duckdb_extensions(), so your code can check for and force-load an extension up front rather than failing later with an opaque SQL error.
  • ensure_extension(name) — a no-op if already loaded, otherwise LOAD, otherwise INSTALL + LOAD.
  • install_extension(name) → INSTALL name.
  • load_extension(name) → LOAD name.
  • is_extension_loaded(name) -> Result<bool> — queries duckdb_extensions(); an unknown extension reports false (no row), not an error.
Extension names must be bare identifiers ([A-Za-z0-9_]+); anything else is rejected up front, so the name can be embedded in SQL safely.
Runtime loading needs network / filesystem access and the enable_external_access Config flag (default on). In a locked-down or offline deployment, bundle the extensions you need instead.

Spatial through the Diesel backend

If you use the Diesel backend, its spatial feature gates a module whose ensure_loaded wraps the runtime load for the ST_* DSL functions. The feature carries no extra Rust dependencies — the ST_* functions are plain SQL and ensure_loaded installs/loads at runtime (so it needs network access unless the extension is already present). See the Diesel SQL DSL.

Pointing in-memory data at SQL

Not an “extension” in the DuckDB sense, but worth knowing alongside them: the arrow and polars features let you register in-memory Arrow streams and Polars DataFrames as queryable sources via replacement scans — no extension and no copy into a table.

Writing your own extension

Writing a loadable .duckdb_extension in Rust uses the experimental loadable-extension feature and the #[duckdb_entrypoint] macro. This is distinct from using the extensions above: it changes the whole linking model (no DuckDB is linked in; every call routes through the host’s API table) and is not for a normal embedded app.

Errors & Extensions

The full extension-management API reference.

Feature flags

json, parquet, icu, and every other core feature.

SQL dialect & statements

The dialect those extensions plug into.

Arrow & Polars interop

Register in-memory data as a queryable source.