MICROSOFT FABRIC
Fabric warehouses and lakehouse SQL endpoints are first-class engines in DVT: make one your default target and run a whole dbt project against it, or point meta.connection at it and read its tables live inside cross-engine federation models. Fabric is the Entra-only member of the SQL Server family — same TDS protocol as its SQL Server sibling, but you always sign in with Entra ID, never a SQL password.
A COMPLETE PROFILES.YML
The most common setup for pipelines — an Entra service principal (an app registration, not a person). Copy it, change the endpoint and warehouse name, point the three env vars at your registration, and you're connected:
# ~/.dbt/profiles.yml
my_project:
target: fabric_prod
outputs:
fabric_prod:
type: fabric
server: abc123xyz.datawarehouse.fabric.microsoft.com
database: my_warehouse # warehouse or lakehouse SQL endpoint name
schema: dbo
authentication: ServicePrincipal
client_id: "{{ env_var('AZURE_CLIENT_ID') }}"
tenant_id: "{{ env_var('AZURE_TENANT_ID') }}"
client_secret: "{{ env_var('AZURE_CLIENT_SECRET') }}"
encrypt: true # Fabric requires TLS — always set this
threads: 4The servervalue is your workspace's SQL connection string — in Fabric, open the warehouse (or lakehouse SQL endpoint), choose Settings → SQL connection string, and copy it. Give the service principal access to the workspace (or the specific item) in Fabric before the first run, or the sign-in succeeds and the database lookup fails.
Then run dvt sync once from your project. It reads this profile, sees a Fabric output, and installs the adapter and the pyodbcdriver for you. One OS-level prerequisite remains yours: the unixODBC runtime and Microsoft's msodbcsql ODBC driver (on macOS, brew install unixodbc plus Microsoft's driver package). dvt sync checks for this and names the fix if it's missing; dvt debug confirms the connection end to end.
WHY ENCRYPT: TRUE IS SPELLED OUT
The SQL Server family's defaults are tuned for local dev containers — encrypt defaults to false. There is no local Fabric, and the real endpoint requires TLS, so on a type: fabric output always write encrypt: trueyourself. Fabric's certificate is a real one, so the family's trust_cert default is fine to override too: trust_cert: false makes the driver actually verify it.
ENTRA ID PASSWORD — ACTIVEDIRECTORYPASSWORD
For working interactively as yourself, use your organizational account as the user and password:
fabric_dev:
type: fabric
server: abc123xyz.datawarehouse.fabric.microsoft.com
database: my_warehouse
schema: dbo
authentication: ActiveDirectoryPassword
user: analyst@yourcompany.com
password: "{{ env_var('ENTRA_PASSWORD') }}"
encrypt: true
trust_cert: falseAccounts behind MFA typically can't authenticate this way — the password grant has no second-factor step. That's the usual reason to switch to a service principal even for development.
WHAT FABRIC DOES NOT ACCEPT
No SQL auth. Fabric has no SQL logins. A profile with plain user/password and no authentication line is treated as SQL auth — the family default — and Fabric's endpoint refuses the sign-in. If you hit a login failure with a working password, this is almost always the missing line: set authentication: ActiveDirectoryPassword.
No Windows integrated auth. windows_login exists in the shared SQL Server family, but a SaaS endpoint has no domain trust to lean on — leave it out on Fabric outputs.
HOW FABRIC BEHAVES IN DVT
database is the item, schema is dbo. database names the warehouse or lakehouse SQL endpoint — the thing you opened in the workspace — and schema defaults to dbo, where Fabric puts tables unless you've created schemas of your own.
Lakehouse SQL endpoints are read-only.A lakehouse's SQL endpoint serves queries, not DDL — so it works as a federation source, while models should build into a warehouse. If you're doing both, that's simply two outputs in profiles.yml, one per item.
Reading Fabric live from a federation model takes one meta.connection line pointing at the output you defined above — the classic pairing is Fabric next to an on-prem engine like Oracle in one model:
# models/staging/sources.yml
sources:
- name: fabric_data
meta:
connection: fabric_prod # a profiles.yml output name
schema: dbo
tables:
- name: sales
- name: inventoryINCREMENTAL MODELS — MERGE, AND TWO DELETE MODES IT ALONE ALLOWS
The Fabric adapter accepts four strategy names, spelled exactly as they go into config: append, delete+insert, merge, and microbatch. insert_overwrite is not among them — a helper macro for it exists in the adapter, but the name is rejected before that macro can be reached.
Leave incremental_strategy unset and the adapter runs its default, which branches on the key: with a unique_key it emits a MERGE, without one it appends. Fabric is the one engine in the SQL Server family with extra merge-time behaviour you can ask for — two ways of deleting from the target as part of the same run:
{{ config(
materialized='incremental',
incremental_strategy='merge', -- append | delete+insert | merge | microbatch
unique_key='sale_id',
delete_condition="DBT_INTERNAL_SOURCE.is_deleted = 1"
) }}
select sale_id, amount, is_deleted, updated_at
from {{ source('fabric_data', 'sales') }}
{% if is_incremental() %}
where updated_at > (select max(updated_at) from {{ this }})
{% endif %}delete_condition runs a separate delete after the MERGE, joining target to source on the unique_key and removing the rows your condition matches — the shape to use when the source carries a soft-delete flag. Both DBT_INTERNAL_SOURCE and DBT_INTERNAL_DEST are available as aliases inside the condition. delete_not_matched_by_source is the other mode: it deletes target rows whose key has no match in the source at all, for models that return the complete current dataset rather than a delta.
Both are merge-only, and the check is on the literal string — leaving incremental_strategy unset raises too, even though the default routes to a merge when a key is present. They are also mutually exclusive. All three refusals are compile-time, which means you find out before any SQL runs:
delete_condition requires incremental_strategy: merge, got 'default' delete_not_matched_by_source requires incremental_strategy: merge, got 'append' delete_condition and delete_not_matched_by_source are mutually exclusive — use one or the other
DELETE_NOT_MATCHED_BY_SOURCE NEEDS A UNIQUE_KEY
Without one, the generated MERGE matches nothing and still emits when not matched by source then delete — which is every pre-existing row in the target. Nothing raises. Treat unique_key as required whenever you set this config.
The other key-shaped surprises. delete+insert without a unique_key silently degrades to an append — the delete block is skipped and the insert still runs, with no error. merge without a unique_key compiles to a MERGE whose match predicate is FALSE and which carries no update clause, so every incoming row is inserted and nothing is updated. microbatch needs an event_time config and the batch boundaries dbt passes with it, and ignores unique_key entirely.
None of this is gated on a Fabric version, on a table format, or on whether you point at a warehouse or a lakehouse SQL endpoint — the adapter declares no such conditions in the incremental path. What does apply is the earlier rule on this page: a lakehouse endpoint serves queries rather than DDL, so build incrementals into a warehouse. Strategies also never run on a full refresh or against an existing view; the model is simply rebuilt.
A name the adapter does not accept is refused by dbt's own gate rather than by the adapter, and the message depends on the kind of name you wrote:
incremental_strategy='insert_overwrite' The incremental strategy 'insert_overwrite' is not valid for this adapter incremental_strategy='upsert' dbt could not find an incremental strategy macro with the name "get_incremental_upsert_sql" in <your project>
When Fabric is the target of a federated model. An f_incremental model is computed by DVT and landed through its data-movement layer, so the vocabulary narrows to append, merge, and delete+insert; insert_overwrite and microbatch are refused as DVT025— "has no Sling equivalent — f_incremental supports append, merge and delete+insert". Fabric's two delete configs are adapter macros, so they belong to the native lane only. On the federated lane merge and delete+insert collapse into the same key-based upsert on unique_key, either one without a key warns and falls back to a full refresh rather than failing, and append without a watermark_column does the same. One refusal is specific to this engine: Fabric is not in the keyless-watermark allow-set, so an f_incremental that leans on a watermark instead of a unique_key is refused here with DVT026. DVT has verified that path on Postgres, Redshift, MySQL, DuckDB, SQLite, SQL Server, Oracle, ClickHouse, and Trino, and refuses it everywhere it has not — Fabric alongside StarRocks, Snowflake, Databricks, BigQuery and Athena. Give the model a unique_key and the ordinary merge lane applies.
REFERENCE — EVERY PROFILE FIELD
Everything a type: fabricoutput reads. The fields are the SQL Server family's — with Entra auth doing all the signing in.
| FIELD | TYPE | REQUIRED | DEFAULT | NOTES |
|---|---|---|---|---|
| type | string | yes | — | Must be fabric. |
| server | string | yes | — | The workspace SQL connection string (…datawarehouse.fabric.microsoft.com). host is an accepted alias. |
| port | integer | no | 1433 | Fabric listens on the standard TDS port — you'll rarely write this. |
| database | string | yes | — | Warehouse or lakehouse SQL endpoint name. |
| schema | string | no | dbo | Default schema for models. |
| authentication | string | yes | — | ActiveDirectoryPassword, ServicePrincipal, or ActiveDirectoryServicePrincipal (same thing). Fabric is Entra-only — leaving it unset means SQL auth, which Fabric refuses. |
| user | string | see notes | — | Required with ActiveDirectoryPassword — the Entra sign-in (user@domain). Unused with a service principal. |
| password | string | see notes | — | Partner of user — same rules. Keep it in env_var(). |
| client_id | string | see notes | — | Required for service principal auth — the app registration's client id. |
| tenant_id | string | see notes | — | Required for service principal auth — the Entra tenant id. |
| client_secret | string | see notes | — | Required for service principal auth. Keep it in env_var(). |
| encrypt | boolean | no | false | Family default is false (local-dev tuning) — always set true on Fabric; the endpoint requires TLS. |
| trust_cert | boolean | no | true | Set false on Fabric so the real certificate is verified. |
| windows_login | boolean | no | false | Exists in the shared SQL Server family; not usable against Fabric — leave it out. |
| threads | integer | no | 4 | Parallel model threads when Fabric is your default target. |