Analysis
September 26, 2026
8 min read
Maxime Dalessandro

dbt v2 DuckDB adapter: what's built in and what's not

dbt 2.0.0 is the first release with a DuckDB adapter inside the engine. What the pinned driver adds, what stays in dbt-duckdb, and how to choose.

#dbt#DuckDB#dbt Fusion#DuckLake#Iceberg#column-level lineage#data engineering

dbt 2.0.0, released September 14, 2026, is the first dbt release that ships a DuckDB adapter inside the engine: install dbt, point a profile at a local file, and the driver downloads and caches itself on the first run. DuckDB's own blog walked through the details on September 22. The convenience is real, and it is the smallest part of the story. For four years the DuckDB adapter was a community Python package sitting between two other installs. In v2 it is a layer inside one Rust binary, and the line separating what ships together from what you bolt on moved with it. Which side of that line your current dbt-duckdb workflow sits on is the whole upgrade question, and neither the announcement nor the setup docs answer it in one place. This piece does.

Four years of dbt-duckdb, two days of asking

The dbt-duckdb package received its first pull request on August 27, 2021, and built a following on a simple proposition: one pip install, one path to a .duckdb file, and a working dbt project with no warehouse signup and nothing running on a server. It sits at 1.4k GitHub stars, and its reach shows in how the Fusion story started. When dbt Labs announced the Rust-based Fusion engine on May 28, 2025, DuckDB was not supported. Two days later a user opened the issue asking for it:

"There is a huge community utilizing the DuckDB adaptor to run DBT. For me personally, I was able to learn and start using DBT just because of the light-weight setup for the dbt-duckdb workflow and it has allowed me to get over the learning curve to start using DBT."

By the time DuckDB's post went out, that issue had collected 146 heart and 21 thumbs-up reactions. The answer arrived as part of something bigger than an adapter port. In June 2026 dbt Labs released the first alpha of dbt Core 2.0, moved a large part of the Fusion code into the dbt-core repository under Apache 2.0, and archived the dbt-fusion repository. The stable release then renamed the CLI branding: the proprietary distribution is now dbt, the open-source one is dbt-oss, and "Fusion" survives mostly as the engine's name. We covered what 2.0 does to the artifact layer every catalog ingests; this is what it does to the DuckDB seat specifically.

The adapter crossed into the engine

In v1, an adapter is a standalone Python package: dbt-core, dbt-duckdb, and the duckdb library resolve as three separate installs, and pip decides which DuckDB version you actually run. In v2, adapters live inside the engine's Rust monorepo and connect through ADBC, the Arrow Database Connectivity standard, which is what lets dbt ship as a single self-contained binary with no Python runtime. A basic profile is unchanged:

my_project:
  target: dev
  outputs:
    dev:
      type: duckdb
      path: ./warehouse.duckdb

Two panels. Left, dbt v1 as three separately installed pieces: dbt-core, the community dbt-duckdb package, and whichever DuckDB version pip resolves, with plugins, Python models, external files and extension loading attached to the lower two. Right, dbt v2 as one emerald-highlighted enclosure containing the Rust engine, the ADBC adapter and a pinned DuckDB driver, with column-level lineage, Parquet metadata, catalogs and native functions riding inside it, while extension loading, plugins and Python models sit outside.

The capability line follows the packaging line: what moved into the binary got new features, what stayed outside needs its own route in.

Being inside the binary has one structural consequence everything else hangs off: the DuckDB version is pinned. dbt ships one tested DuckDB build instead of whatever pip resolves, which lets the engine depend on features of that exact build. Read-write Iceberg REST catalog support depends on the pinned version, and some adapter logic that used to be a SQL macro is now a native DuckDB extension function, such as array_except exposed as sf_array_except.

What rides the pin

Three capabilities come with the move, and none of them exist in the Python adapter.

Catalogs as configuration. catalogs.yml can define DuckLake and Iceberg REST catalogs, and with the use_catalogs_v2 flag enabled, a model materializes into a catalog by naming it in its config while dbt generates and runs the ATTACH statements. dbt's DuckDB docs flag catalog support as v2-only; the legacy adapter attached DuckLake through the profile's attach block instead, without catalog-aware materializations.

Metadata as Parquet. Running dbt parse --generate-info-schema writes the project's manifest as Parquet files to target/info_schema/v1/. On a large project, manifest.json can grow to hundreds of megabytes, and answering any question about the project means parsing all of it. The Parquet files are columnar, so DuckDB reads only the columns a question needs:

SELECT name, materialized, schema_name
FROM 'target/info_schema/v1/dbt.models.parquet';

A CI check that enforces naming conventions, or an audit script that lists untested models, can now run against the project's own metadata without standing up dbt or a warehouse. This is the same artifacts-as-contract shift we traced in the dbt Core 2.0 piece, landing on the smallest possible deployment, and it is one more case of DuckDB becoming the default query plumbing for metadata itself, the pattern AWS paid an acquisition to be part of.

Column-level lineage, locally. The v2 engine parses SQL natively across dialects instead of treating compiled Jinja output as an opaque string, so it catches invalid column references and type mismatches before anything reaches the database. The same analysis produces lineage: dbt compile --generate-info-schema --static-analysis strict writes a dbt.column_lineage file into the info schema directory. No platform account is involved, and the lineage file is itself Parquet you can query.

What stayed outside the binary

The bundled driver has a hard limitation that dbt's setup docs state plainly: it "does not support loading DuckDB extensions (for example, httpfs, parquet, or spatial)." If your models read from S3 over httpfs or use spatial functions, the bundled driver cannot run them. The documented route is installing a system DuckDB driver with dbc; dbt v2 checks for a system-installed driver first and falls back to the bundled one only when none is found.

The docs also carry a broader warning: "Some features available in the dbt-duckdb adapter for dbt v1 are not yet supported." One named gap is static analysis over local flat files: v2 may fail to infer schemas for CSV, Parquet, or JSON sources, producing type-resolution warnings or compilation errors on queries that would succeed at runtime. Beyond the named gaps, a chunk of dbt-duckdb's surface simply has no documented v2 equivalent: the plugin system (Excel, Google Sheets, SQLAlchemy, and Iceberg built in, Delta experimental), Python models executed in-process and returning a Pandas or Polars DataFrame, a DuckDB relation, or an Arrow table, and external materializations that write models out as Parquet, CSV, or JSON files with optional AWS Glue registration. Neither DuckDB's announcement nor dbt's docs mention any of these for the built-in adapter.

None of this strands anyone. dbt-duckdb remains available and community maintained, targeting dbt-core 1.8 and later, and DuckDB's post is explicit that the Python versions of dbt Core remain available "if you'd rather not move or not move yet."

How to choose

The decision falls out of the boundary. Move to v2 now if your project is SQL models building into a local file or MotherDuck and you want the things the engine does natively: error detection before execution, column-level lineage, queryable metadata, catalog materializations into DuckLake or Iceberg. Stay on dbt-duckdb if your pipeline leans on the parts that live outside the binary: plugins, Python models, external file outputs, or extensions beyond what a dbc-installed system driver restores.

The pin itself cuts both ways, and it is worth being clear-eyed about that before treating it as pure upside. A pinned, tested DuckDB build is why catalog support works; it also means that when a DuckDB release ships a function or a fix you want, you wait for dbt to ship it, where the Python adapter let you resolve any version you liked. Teams that track DuckDB releases closely are giving up a degree of freedom that the pip model, for all its resolution headaches, did grant.

Testing the move is cheap. From dbt v1.12, dbt parse --use-v2-parser checks whether your project parses under the new engine before you migrate anything, and the dbt-autofix helper handles many of the mechanical changes the stricter v2 spec requires.

Where Datapace fits

A transformation tool whose project metadata is a queryable dataset is a small preview of a larger shift: the description of a data system becoming data you can join, filter, and build checks against, rather than a blob you parse. Datapace is building the context layer between your databases and your AI: resolved meaning validated by the people who own the data, the workload evidence beside it (cost, performance, usage and freshness, lineage), and a policy gate over what an agent may do and access, served over MCP. dbt's info schema, like the governed metrics dbt exposes over its MCP server, is exactly the kind of source that layer consumes and cross-checks. If your team is deciding what your agents should know about your dbt project, book a call.

Sources

  1. DuckDB, DuckDB Now Ships inside dbt v2, Geertjan Wielenga, September 22, 2026 (release dates, ADBC architecture, catalogs, info schema, lineage commands, pinned driver, reaction counts, CLI renaming, community quote).
  2. dbt Labs, DuckDB setup, dbt Developer Hub (bundled driver extension limitation, dbc system driver fallback, flat-file static analysis gap, "not yet supported" statement, MotherDuck and DuckLake connection strings).
  3. dbt Labs, Supported features on the dbt v2 engine, dbt Developer Hub, page dated September 22, 2026 (adapter list, DuckDB as CLI-only).
  4. dbt Labs, Upgrading to the dbt Fusion engine, dbt Developer Hub (ADBC single-binary statement, --use-v2-parser, dbt-autofix, package compatibility).
  5. duckdb/dbt-duckdb, README, GitHub (supported dbt-core versions, plugin list, Python model return types, external materializations, MotherDuck support).
  6. dbt Labs, dbt-fusion issue: DuckDB adapter feature request, opened by ran-codes, May 30, 2025 (request date and framing, engine:v2 label, closed status).

Frequently asked questions

Does dbt v2 include a DuckDB adapter?
Yes. dbt 2.0.0, released September 14, 2026, is the first dbt release with a DuckDB adapter built into the engine. dbt downloads and caches the DuckDB driver the first time you run it, so there is no separate package to install.
Can the dbt v2 DuckDB adapter load extensions like httpfs?
Not with the bundled driver: dbt's docs state it does not support loading DuckDB extensions such as httpfs, parquet, or spatial. Installing a system DuckDB driver with dbc restores them; dbt v2 checks for a system driver before falling back to the bundled one.
Is the dbt-duckdb Python adapter deprecated?
No. dbt-duckdb remains available and community maintained, targeting dbt-core 1.8 and later, and the Python line of dbt Core continues alongside v2. Its plugins, Python models, and external file outputs have no documented equivalent in the built-in adapter yet.
Do I need a dbt platform account for column-level lineage on DuckDB?
No. The v2 engine derives column-level lineage from its own SQL analysis. Running dbt compile with --generate-info-schema and --static-analysis strict writes a dbt.column_lineage file locally, queryable with DuckDB like any other dataset.

Keep reading

Ready to let agents touch production, safely?

Bring a use case. We will show you what agents can do on your live data, inside your guardrails.