dbt Fusion e dbt Core v2 in Python 2026: Motore Rust, Type-checking SQL e Test di Pipeline Non Negoziabili

Guida pratica a dbt Fusion in Python 2026: motore Rust 20-30x più veloce, type-checking SQL statico e migrazione senza dolore da dbt Core 1.9 a Core v2.0.

dbt Fusion Python 2026: Guida Rust

Aggiornato: 16 settembre 2026

dbt Fusion è il nuovo motore di esecuzione scritto in Rust da dbt Labs che analizza il tuo progetto dbt esistente da 20 a 30 volte più velocemente rispetto a dbt Core 1.9 e aggiunge type-checking SQL statico prima che una query tocchi il data warehouse. In Python 2026 puoi installarlo come sostituto drop-in con uv tool install dbt-fusion, oppure affiancarlo a dbt-core per una migrazione graduale verso dbt Core v2.0 (GA prevista per dicembre 2026). Questa guida mostra come effettuare il passaggio senza spezzare i test della pipeline.

  • dbt Fusion 0.5 (agosto 2026) gira su un motore Rust con velocità di parse 20-30 volte superiore a dbt Core 1.9 e introduce type-checking SQL statico prima dell'esecuzione sul warehouse.
  • Il nuovo manifest v20 contiene lineage a livello di colonna, nullability e vincoli; la tooling esistente basata su manifest v12 continua a funzionare grazie a uno shim di compatibilità.
  • La strategia incrementale microbatch è ora quella consigliata per tabelle di eventi di grandi dimensioni, tramite batch_size, lookback ed event_time.
  • dbt Core v2.0 (alpha luglio 2026, GA dicembre 2026) passa alla licenza ELv2; la maggior parte dei progetti può continuare a girare su Core 1.9 e Fusion in parallelo.
  • Gli adapter Fusion per Snowflake, BigQuery, Databricks, Postgres e Redshift sono GA; DuckDB, Trino e Athena sono ancora in beta.
  • Gli unit test con dbt test girano in-memory tramite il motore Fusion, perfetti per pipeline CI dove non vuoi bruciare crediti warehouse.

Cos'è dbt Fusion e perché dovresti farci attenzione?

Allora, partiamo dalle basi. dbt Fusion è un motore di esecuzione completamente riscritto in Rust che dbt Labs ha reso open source a febbraio 2026 sotto licenza Apache 2.0. Dove dbt Core 1.9 usa ancora Python per renderizzare Jinja, costruire il DAG e serializzare i manifest, Fusion fa tutto in binari nativi. Il risultato? Una fase di parse che su un progetto medio (~500 modelli) passa da trenta secondi a circa uno. Suona come una benchmark carina, ma nella pratica è la differenza tra sentire ogni azione dell'IDE come una build e non accorgersi nemmeno che dbt sta girando.

Da data engineer, ciò che per me conta ancora di più è un altro fatto: Fusion ha un vero parser SQL che comprende lo schema del tuo warehouse. Prima di un dbt run, Fusion sa già se stai scrivendo SELECT user_id::text su una colonna bigint, se stai facendo una JOIN su tipi incompatibili o se stai referenziando una colonna che non esiste. Ho visto anni di page alle 3 di mattina per pipeline crashate che poi erano semplici typo nei tipi. Fusion cattura tutto questo prima che la CI faccia anche solo una chiamata al warehouse.

Fusion non sostituisce dbt Core direttamente. Puoi installare entrambi affiancati e migrare modello per modello. dbt Cloud gira di default su Fusion da luglio 2026, ma i team self-hosted mantengono la scelta.

Installazione in Python: uv, pip e compatibilità

Il modo consigliato per installare Fusion nel 2026 è tramite uv, perché il binario Rust viene distribuito con un wrapper Python sottile e uv lo risolve molto più rapidamente di pip. Se non hai mai lavorato con moderni tool Python per il data engineering, ti consiglio prima la nostra guida a DuckDB con Python su DataFrame, Parquet e Data Lake. Troverai un'introduzione al tooling che oggi qualsiasi team dati serio si aspetta.

# installa Fusion come CLI standalone (consigliato)
uv tool install dbt-fusion

# oppure affianca dbt-core nello stesso ambiente
uv add dbt-fusion dbt-core dbt-postgres

# verifica la versione e il motore
dbt --version
# dbt Fusion 0.5.3 (rust-engine 2026.08.14)
# dbt Core 1.9.4 (fallback available)

La tabella di compatibilità ufficiale elenca quali adapter sono GA su Fusion. Al momento della scrittura (settembre 2026): Snowflake, BigQuery, Databricks, Postgres e Redshift sono GA; DuckDB, Trino e Athena sono in beta; Materialize e Firebolt sono ancora in preview. Per gli adapter non ancora GA, Fusion effettua un fallback automatico al motore Python (vedrai un warning nei log).

Manifest v20: lineage a livello di colonna e type inference

Uno dei miglioramenti meno discussi ma praticamente più impattanti è nel formato del manifest. dbt Core 1.9 usa il manifest v12; Fusion scrive il manifest v20. Il nuovo formato contiene, per ogni modello, una descrizione completa per colonna: nome, tipo inferito, nullability, vincoli e (soprattutto) riferimenti alle colonne upstream da cui il campo deriva. Questo è lineage a livello di colonna senza dover aggiungere un tool separato come SQLGlot.

import json
from pathlib import Path

manifest = json.loads(Path("target/manifest.json").read_text())
print(f"versione manifest: {manifest['metadata']['dbt_schema_version']}")

model = manifest["nodes"]["model.jaffle_shop.orders"]
for col_name, col in model["columns"].items():
    upstream = col.get("depends_on", {}).get("columns", [])
    nullable = col.get("constraints", {}).get("not_null", False)
    print(f"{col_name}: type={col['data_type']}, "
          f"nullable={not nullable}, upstream={upstream}")

Per i tool che si aspettano ancora il manifest v12 (pensa a versioni vecchie di dbt-metabase, Elementary o dashboard interne che hai scritto tu), Fusion fornisce uno shim retrocompatibile: dbt compile --manifest-version 12. Consideralo come una via di fuga temporanea, non uno stato finale, perché lo shim scarta proprio i nuovi campi ed è per quei campi che stai facendo girare Fusion.

Type-checking SQL statico nella pratica

Il type-checking statico di Fusion viene eseguito come parte di dbt parse. Fusion recupera una volta lo schema del warehouse (o legge una versione cacheata in .dbt/schema_cache.json) e poi verifica ogni statement SELECT. Lo faccio girare in un pre-commit hook, ed è il cambiamento più prezioso del 2026 per il mio team.

-- esempio: bug che Fusion cattura prima della CI
-- models/staging/stg_orders.sql
select
    order_id,
    customer_id::text as customer_id,
    -- customer_id upstream è bigint; il cast a text spezza una JOIN downstream
    amount / 100 as amount_usd
from {{ source('raw', 'orders') }}
$ dbt parse --engine fusion
[error] models/staging/stg_orders.sql:3:5
  type mismatch: customer_id declared as text but downstream model
  model.jaffle_shop.dim_customers expects bigint (from stg_customers.customer_id)
  hint: remove ::text or update dim_customers join condition

Prima questo tipo di errori emergeva solo durante dbt test, e con dati intermittenti a volte solo in produzione. Fusion li cattura in secondi. Puoi regolare la sensibilità tramite dbt_project.yml:

# dbt_project.yml
flags:
  fusion:
    type_checking: strict          # strict | warn | off
    check_unused_columns: true     # avvisa su colonne di modello non usate
    max_query_complexity: 500      # righe del query plan; blocca CTE runaway

Nei progetti nuovi imposta type_checking direttamente a strict. In un progetto esistente parti da warn, sistema l'output e poi gira la chiave. Considera un'ora ogni cento modelli, se la codebase era abbastanza disciplinata. Per approfondire pratiche di data quality complementari a monte, dai un'occhiata alla nostra guida alla pulizia dei dati in Python con pandas e PyJanitor.

Microbatch: il nuovo standard per tabelle grandi

La strategia incrementale microbatch nel 2026 ha silenziosamente sostituito insert_overwrite come strategia consigliata per tabelle di eventi con più di qualche centinaio di milioni di righe. Invece di una singola query che elabora tutti i nuovi dati, Fusion divide il lavoro in finestre temporali basate su event_time e fa girare ogni finestra come una transazione separata. Il risultato: transazioni più piccole, backfill riavviabili e drammaticamente meno rischio di runaway cost.

-- models/marts/fct_orders.sql
{{ config(
    materialized='incremental',
    incremental_strategy='microbatch',
    event_time='ordered_at',
    batch_size='day',
    lookback=2,
    begin='2024-01-01'
) }}

select
    order_id,
    customer_id,
    ordered_at,
    amount_usd
from {{ ref('stg_orders') }}
{% if is_incremental() %}
  where ordered_at >= '{{ model.config.begin }}'
{% endif %}

batch_size può essere hour, day, month o year. lookback=2 significa che ogni run rielabora le ultime due finestre (cruciale se i dati upstream sono late-arriving, pensa a eventi che arrivano 24 ore dopo). Un backfill lo fai con un comando semplice: dbt run --event-time-start 2024-06-01 --event-time-end 2024-07-01. Fusion esegue le finestre in parallelo se il warehouse lo regge.

Unit test: perché i test della pipeline non sono negoziabili

Questa è la parte per cui divento più appassionata, quindi seguimi. In dbt 1.8 sono stati introdotti gli unit_tests; in Fusion girano completamente in-memory senza mai toccare il warehouse. Questo significa che la tua test suite passa da dieci minuti a dieci secondi, e in CI puoi lanciare centinaia di edge case senza spendere un centesimo di compute. Onestamente, non c'è più alcuna scusa per deployare trasformazioni non testate.

# models/marts/_fct_orders.yml
unit_tests:
  - name: test_orders_amount_conversion
    model: fct_orders
    given:
      - input: ref('stg_orders')
        rows:
          - {order_id: 1, customer_id: 100, ordered_at: '2026-01-01', amount_cents: 12500}
          - {order_id: 2, customer_id: 100, ordered_at: '2026-01-01', amount_cents: 0}
          - {order_id: 3, customer_id: 200, ordered_at: '2026-01-01', amount_cents: null}
    expect:
      rows:
        - {order_id: 1, customer_id: 100, amount_usd: 125.00}
        - {order_id: 2, customer_id: 100, amount_usd: 0.00}
        # order_id 3 viene filtrato: amount_cents è null
$ dbt test --select fct_orders --engine fusion
1 of 1 START unit_test fct_orders::test_orders_amount_conversion .. [RUN]
1 of 1 PASS test_orders_amount_conversion .............. [PASS in 0.04s]

Done. PASS=1 WARN=0 ERROR=0 SKIP=0 TOTAL=1

Se la data quality nel tuo team conta, combina pure dbt test con un framework generico come Great Expectations o Pandera per la validazione dopo la load. Per un contesto più ampio su feature engineering e trasformazioni pandas, vedi la nostra guida al feature engineering in Python con pandas e scikit-learn. Ma inizia con unit_tests: proteggono la logica SQL in sé, non solo i valori dei dati.

dbt Fusion vs SQLMesh vs SDF a confronto

Fusion non è l'unico framework moderno di trasformazione SQL nel 2026. SQLMesh (Tobiko Data) e SDF (ora parte di dbt Labs dall'acquisizione di fine 2025) vengono spesso nominati nella stessa frase. Ecco un confronto onesto sulle dimensioni che contano davvero se stai scegliendo uno strumento per i prossimi anni:

Caratteristicadbt Fusion 0.5SQLMesh 0.55SDF 0.20 (via dbt)
MotoreRustPythonRust (fuso in Fusion)
Type-check SQL staticoSì (nativo)NoSì (ora in Fusion)
Ambienti virtualiNoSì (blue/green)No
Lineage a livello colonnaSì (manifest v20)SìSì
Unit testSì (in-memory)Sì (in-memory)Sì
Copertura adapter5 GA + 3 beta10+ GALimitata
Ecosistema/communityMolto grande (dbt)Medio, in crescitaAssorbito da dbt
LicenzaApache 2.0Apache 2.0Apache 2.0

Consiglio pratico: se sei già su dbt, Fusion è ovvio. Ottieni velocità Rust e i typecheck di SDF in un passo solo, senza riscrivere il progetto. SQLMesh è interessante se ti serve fortemente su ambienti virtuali (deploy blue/green di modelli interi), ma per la maggior parte dei team è overkill. Comprare SDF a sé stante non ha più senso, ora che le feature sono in Fusion.

Percorso di migrazione da dbt Core 1.9 a Fusion e Core v2.0

La migrazione più sicura è a tre stadi. Non saltare passi, anche se in un progetto piccolo sembra superfluo. Le tappe intermedie producono proprio i log con cui poi puoi debuggare una breaking change.

  1. Stadio 1 (settimana 1): fai girare Fusion in modalità warn a fianco di Core 1.9. Aggiungi dbt parse --engine fusion --warn-only alla CI e raccogli una lista di warning. Sistema le incoerenze di tipo e rimuovi macro execute non necessarie.
  2. Stadio 2 (settimana 2-3): attiva type_checking: warn in produzione e promuovi Fusion a motore primario per lo sviluppo locale e i pre-commit hook. Continua a far girare la produzione su Core 1.9 finché non passi una settimana senza warning.
  3. Stadio 3 (settimana 4+): promuovi Fusion a motore di produzione, attiva type_checking: strict e pianifica l'upgrade a dbt Core v2.0 (GA prevista dicembre 2026, licenza ELv2). Per dbt Cloud managed, v2.0 avviene automaticamente; per i progetti self-hosted seguirà uno script di migrazione.

CI/CD con dbt Fusion in GitHub Actions

Una pipeline è tua solo quando la CI diventa verde. Sotto la configurazione che tengo in produzione per team Python che usano Fusion. Nota l'uso di --defer --state: solo i modelli modificati girano, il resto viene dall'ultimo manifest di produzione. Su un progetto grande, questo può facilmente risparmiare il 90% del compute.

# .github/workflows/dbt-ci.yml
name: dbt CI

on:
  pull_request:
    paths: ['dbt_project/**']

jobs:
  build:
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v5
      - uses: astral-sh/setup-uv@v5
        with:
          version: '0.12.7'

      - name: install dbt Fusion
        run: uv tool install dbt-fusion==0.5.3

      - name: download production manifest
        run: |
          aws s3 cp s3://dbt-artifacts/prod/manifest.json ./prod-artifacts/

      - name: parse and typecheck
        working-directory: dbt_project
        run: dbt parse --engine fusion --warn-only

      - name: run only changed models
        working-directory: dbt_project
        run: |
          dbt build \
            --defer --state ./prod-artifacts \
            --select state:modified+ \
            --engine fusion

      - name: run unit tests
        working-directory: dbt_project
        run: dbt test --select test_type:unit --engine fusion

Il selector state:modified+ prende i modelli cambiati e tutto ciò che sta a valle. dbt build combina run e test: se un test fallisce, i modelli downstream vengono skippati automaticamente. Per progetti più grandi aggiungi --vars '{"is_ci": true}' così i modelli che lo leggono possono girare in una variante campionata (per esempio where sampled in una macro).

Trappole di produzione che ho incontrato di persona

Nessun motore è privo di spigoli. Queste sono le quattro trappole in cui io e i miei colleghi siamo inciampati da quando in Q2 2026 siamo passati a Fusion. I modelli che deploi oggi non devono cadere qui domani.

  1. Manifest shim dimenticato nei tool downstream. Elementary v2 legge ancora manifest v12; se fai girare Fusion senza --manifest-version 12, i grafici di data observability si svuotano. Soluzione: attiva lo shim o passa a Elementary v3.
  2. Macro Jinja che eseguono query in parse-time. In Core 1.9 potevi mettere {% if execute %} attorno a una SELECT contro il warehouse dentro una macro. Fusion lo consente ma serializza queste query, facendo esplodere il parse-time. Riscrivi tali macro come hook on-run-start o come dbt run-operation che invochi esplicitamente.
  3. Timezone in microbatch. event_time deve essere timezone-aware. Se i dati upstream sono timezone-naive (la colonna è timestamp invece di timestamptz), ottieni silenzio off-by-one sui confini della finestra e un backfill che sembra corretto ma non lo è. Esegui un cast esplicito a UTC nel layer di staging.
  4. Adapter fallback senza logging. Se giri un adapter non-GA, Fusion effettua fallback al motore Python. In CI lo vedi come WARNING; in dbt Cloud finisce nei deep-log. Imposta fail_on_adapter_fallback: true in dbt_project.yml per bloccare fallback accidentali.

Per i team che dopo una migrazione riuscita vogliono anche modernizzare le pipeline ML in Python, rimando volentieri alla nostra guida pratica al machine learning con scikit-learn su pipeline, validazione e selezione dei modelli. Pipeline dati affidabili sono le fondamenta; un buon model serving posa il resto.

Domande frequenti

dbt Fusion è open source?

Sì. dbt Fusion è open source dal febbraio 2026 sotto licenza Apache 2.0. Il codice sta su GitHub in dbt-labs/dbt-fusion. Questo non cambia con il rilascio di dbt Core v2.0 (che passa a ELv2).

Devo passare da dbt Core 1.9 a dbt Fusion?

Se il tuo progetto ha più di cento modelli, sì. Il type-checking statico e il parse 20-30 volte più veloce si ripagano in poche settimane. Per progetti piccoli (<30 modelli) Fusion resta utile ma è meno urgente. Segui il percorso di migrazione in tre stadi sopra per tenere basso il rischio.

dbt Fusion funziona con DuckDB?

Sì, ma a settembre 2026 l'adapter DuckDB è ancora in beta. Per sviluppo locale va benissimo; per la produzione aspetterei un ciclo o preparerei piani di contingenza. Lo status GA è atteso per il Q4 2026.

Qual è la differenza tra dbt Fusion e SDF?

SDF era uno strumento standalone di trasformazione SQL con motore Rust e type-check statici. Dopo l'acquisizione di SDF da parte di dbt Labs a fine 2025, le feature core sono state assorbite in dbt Fusion. Nel 2026 si usa Fusion; SDF come prodotto separato non viene più sviluppato attivamente.

Posso combinare dbt Fusion con dbt Cloud?

Sì. dbt Cloud gira di default su Fusion da luglio 2026, quindi ottieni automaticamente i miglioramenti di velocità e i typecheck. Per team self-hosted che usano dbt Cloud solo per lo scheduling ma girano Fusion in locale, la configurazione è identica: Fusion rispetta gli stessi profiles.yml e dbt_project.yml.

Come verifico se Fusion supporta il mio progetto dbt esistente?

Fai girare dbt parse --engine fusion --warn-only in un branch. Tutte le incompatibilità appaiono come warning senza spezzare la build. Sistemale, poi attiva type_checking: warn e smaltisci l'output in una sprint. Dopodiché passi a strict e hai finito.

Hannah Walsh
Sull'Autore Hannah Walsh

Data engineer making sure the pipelines feeding the models don't silently break at 3am. Big fan of dbt and bigger fan of testing.