dbt-sqlserver

The dbt adapter plugin that connects dbt-core to Microsoft SQL Server and Azure SQL, with pluggable pyodbc, mssql-python, and ADBC backends.

Library
PyPI
v1.11.1
255stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
87/100Excellent
Development Activity96
Maintenance96
Community76
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
87/100Excellent
Architecture85
Code Quality90
Innovation78
Learning Curve95

dbt-sqlserver is the community-maintained dbt adapter plugin that lets dbt-core projects target Microsoft SQL Server and Azure SQL Database/Managed Instance. It implements dbt’s adapter interface (relations, connections, materializations, catalog) against T-SQL, translating dbt’s incremental, snapshot, seed, ephemeral, and Python model workflows into SQL Server-native DDL/DML, including clustered columnstore index creation, safe column-type expansion, and transaction-aware hook execution.

The adapter is backend-pluggable: the default pyodbc path uses the Microsoft ODBC Driver, an alternative mssql-python backend drops the ODBC driver requirement entirely, and an experimental Arrow-native adbc backend bypasses the row-based DB-API bridge. Authentication covers SQL auth, Windows/Kerberos, and Azure Active Directory (interactive, service principal, managed identity, CLI, and access-token passthrough), and the project ships an extensive unit, functional, and integration test suite that runs against real SQL Server instances in CI.

What You Get

  • An adapter plugin registered with dbt-core’s plugin system, installed via pip install dbt-sqlserver and selected as type: sqlserver in profiles.yml
  • Three interchangeable connection backends (pyodbc, mssql-python, adbc) selectable per profile target without changing project code
  • Built-in support for dbt’s incremental, snapshot, seed, ephemeral, and Python model materializations translated into SQL Server-specific DDL/DML
  • Azure Active Directory authentication paths (interactive, service principal, managed identity, CLI, access-token passthrough) alongside SQL and Windows auth
  • Behavior flags for safe column-type widening, dbt-native transaction hooks, columnstore index creation, and legacy schema-naming compatibility

Common Use Cases

  • Running a dbt project against an on-prem SQL Server or Azure SQL Database warehouse instead of a cloud-native warehouse
  • Migrating an existing dbt project from autocommit-only legacy transaction handling to dbt-managed BEGIN/COMMIT semantics via dbt_sqlserver_use_dbt_transactions
  • Connecting to Azure SQL with managed identity or service principal credentials in a CI/CD pipeline, without embedding SQL credentials
  • Building incremental models on tables that need safe, low-risk column-type expansion instead of manual ALTER TABLE migrations

Under The Hood

Architecture The adapter is a thin translation layer between dbt-core’s SQLAdapter/SQLConnectionManager base classes and T-SQL: sqlserver_adapter.py (SQLServerAdapter, ~960 lines) implements column-schema introspection, index diffing (relation_configs/index.py), and constraint/materialization overrides, while sqlserver_connections.py (SQLServerConnectionManager, ~870 lines) owns cursor lifecycle, retryable-exception classification per backend, and query execution. Backend selection is isolated behind a small set of pure functions in sqlserver_backend.py (_connect_pyodbc, _connect_mssql_python, _connect_adbc) and sqlserver_auth.py (is_adbc_backend, is_mssql_python_backend), so the adapter, connection manager, and macros never branch on backend identity directly. Cross-cutting SQL Server concerns (column masking in sqlserver_mask.py, GRANT/DENY translation in sqlserver_deny.py, credential coercion in sqlserver_credentials.py) are each isolated into single-purpose modules rather than folded into the adapter class. The riskiest coupling point is sqlserver_runtime.py, which lazily imports optional driver packages (pyodbc, mssql_python, adbc_driver_manager) at call time so the package installs cleanly without any of them present.

Tech Stack The project targets dbt-core 1.12+, dbt-adapters 1.24+, and dbt-common 1.22+, built with setuptools and dynamic versioning pulled from a dedicated version module. Three optional driver backends are declared as extras: pyodbc>=5.2.0 (default, requires the Microsoft ODBC Driver plus unixodbc-dev on Linux), mssql-python>=1.7.1 (a no-ODBC alternative needing only a handful of system libraries), and an experimental adbc-driver-manager plus pyarrow combination for Arrow-native access; azure-identity is a separate extra for AAD token acquisition. Tooling is uv-managed, linted with ruff (import ordering, banned relative imports), type-checked with ty pinned to an exact version and scoped to the adapter package, and tested with pytest plus dbt-tests-adapter for the shared dbt adapter conformance suite. CI runs unit tests, a dedicated type-check job, integration tests against a live SQL Server container, and a Docker image publish workflow.

Code Quality Test coverage is extensive and stratified: dozens of files split across unit tests (pure-function tests for schema naming, index diffing, masking, DENY translation, connection logic, ADBC backend behavior) and functional tests (materializations, snapshots, seeds, Python models, transactions, grants, catalog, and provisioning run against a real SQL Server instance). Error handling favors explicit, typed exceptions and backend-specific retryable-exception classification rather than bare excepts. Code carries unusually dense inline rationale comments explaining why a given code path exists, full type hints throughout, and a pinned static type checker scoped to the adapter package with an explicit suppression justified in a comment about dbt’s split-namespace-package import mechanics.

API Design As a dbt adapter, the ‘API’ surface is a profiles.yml target block and a handful of dbt_project.yml behavior flags rather than an importable Python API. Getting started is a two-line install-and-configure with sensible defaults (columnstore indexes, dbt-managed transactions, safe type-widening) that require no extra configuration for the common case, while advanced behavior is opt-in via named flags with documented default values and migration notes. The three-backend abstraction is the adapter’s most distinctive ergonomic choice — it lets a project switch drivers, including to a fully ODBC-driver-free path, by changing one profile field, which is unusual among dbt adapters typically tied to a single client library.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search