SQLMesh vs dbt: what it fixes, and what it costs

By Arshad Ansari

dbt won. It is the default way teams turn raw tables into modelled ones, and the ecosystem around it — packages, adapters, BI integrations, people who already know it — is the real product. Any comparison that pretends otherwise is selling something.

SQLMesh is the most serious alternative anyone has built. It does the same job: SQL files, a dependency graph, tables in your warehouse. The difference is underneath. SQLMesh parses your SQL instead of templating strings, keeps track of which date ranges it has already computed, and gives you development environments that cost almost nothing to create.

Two things I should say up front. I have not run SQLMesh in production. This is an evaluation from its documentation, read against the dbt projects I work on and the Dagster-orchestrated pipelines I run behind my own product. And the ownership picture changed twice in a year: the company that bought SQLMesh's maker has since merged with dbt Labs, and SQLMesh itself now belongs to the Linux Foundation. That changes how you should read the choice.

The short answer

Stay on dbt if the thing that limits your team is people and integrations — the next hire has to be productive in a week, a BI tool needs to read your metadata, and you rely on packages for things like snapshots and utility macros. That is most teams, and it is not a compromise.

Move to SQLMesh if the thing that limits you is the engineering — the dev warehouse bill, incremental models nobody trusts, changes that break downstream tables in silence, backfills tracked in a spreadsheet. SQLMesh fixes those four by design, not by convention.

If none of those four describes your week, you do not have a SQLMesh-shaped problem.

What each one is

dbt compiles Jinja-templated SQL into warehouse queries and runs them in dependency order. It has tests, documentation, snapshots, sources and a large package ecosystem. Since 2026 it has two lines: the Python v1 series, and v2, which is built on the Rust Fusion engine and understands SQL rather than treating it as text. The difference between dbt Core and dbt Cloud is a separate question from this one, and worth being clear on before you compare anything.

SQLMesh defines models with a MODEL (...) block above plain SQL — no Jinja required — and parses everything through SQLGlot, the SQL parser and transpiler from the same authors. Its docs say dbt "has no understanding of SQL and treats all queries as raw strings", which is blunt but accurate, and that "SQLMesh supports Jinja, but it does not rely on it". It ships a built-in scheduler, unit tests with fixtures, audits, Python models, and support for sixteen engines including BigQuery, Snowflake, Databricks, Redshift, Postgres, ClickHouse, Trino and DuckDB.

At a glance

dbtSQLMesh
Model fileJinja + SQL, config in a macro callMODEL (...) block + plain SQL
Understands your SQLv2 (Fusion, Rust) does; v1 does notYes, via SQLGlot, since the start
Dev environmentA schema you build; dbt clone and deferral helpVirtual: views over reused physical tables
Change reviewYou read the diff and the DAGsqlmesh plan classifies breaking / non-breaking
Incremental stateYour is_incremental() SQL decides what to loadSQLMesh tracks which intervals exist
BackfillsYou run them, with date ranges by handComputed from missing intervals
Unit testsYes, since v1.8Yes, with fixtures
SchedulerNone built in; you bring oneBuilt in, or bring one
EcosystemVery large — packages, adapters, every toolSmall but real
LicenceApache 2.0 (dbt Core)Apache 2.0

The clearest difference: who tracks the state

Here is an incremental model in each tool. Start with dbt:

{{ config(
    materialized = 'incremental',
    incremental_strategy = 'delete+insert',
    unique_key = 'event_date'
) }}

select
    cast(event_at as date) as event_date,
    merchant_id,
    count(*) as events
from {{ source('raw', 'events') }}
{% if is_incremental() %}
where event_at >= (select coalesce(max(event_date), '1900-01-01') from {{ this }})
{% endif %}
group by 1, 2

Read what that is_incremental() block is doing. It asks the target table what it already has, and trusts the answer. If a late-arriving row lands before yesterday's maximum, it is missed. If a run half-fails, the watermark is wrong and nothing tells you. If you need to rebuild March, you run a full refresh of everything or write a one-off query. The state lives in the data, and the logic for reading it lives in your SQL.

Now SQLMesh:

MODEL (
  name analytics.events,
  kind INCREMENTAL_BY_TIME_RANGE (
    time_column event_date
  ),
  start '2024-01-01',
  cron '@daily'
);

SELECT
  event_at::DATE AS event_date,
  merchant_id,
  count(*) AS events
FROM raw.events
WHERE event_at::DATE BETWEEN @start_ds AND @end_ds
GROUP BY 1, 2;

The model says which column is time and when history begins. @start_ds and @end_ds are filled in per run. SQLMesh records which intervals it has computed in a state database, so a missing range is a fact it knows rather than something you discover. Backfilling March is asking for March. Its own docs put the contrast plainly: it "keeps track of which date ranges exist", while "dbt does not check whether the data inserted into an incremental table should be there or not".

That state has to live somewhere, which is the cost. SQLMesh needs a state connection, and its docs recommend Postgres for production, warning that warehouses "aren't optimized for executing transactions" and that sharing one connection for data and state "is not recommended for production deployments". So you are running a small database you did not have before. If you already run Postgres, that is nothing. If your whole stack is one warehouse and a CI runner, it is a new piece.

dbt's answer to the same problem is the microbatch incremental strategy, added in v1.9, where you declare event_time, batch_size and begin and dbt splits the run into batches it can retry. It is a real improvement and it closes part of the gap. It still does not maintain a record of which batches exist across time.

Virtual data environments

This is the feature with no dbt equivalent, and the one I would most want in dbt.

Every version of a SQLMesh model gets a fingerprint. Whenever a model definition changes, a new snapshot is created with a unique fingerprint, and each snapshot has its own physical table. An environment — prod, dev, pr_412 — is a set of views pointing at those tables. Creating a dev environment does not copy or recompute anything whose fingerprint already exists; SQLMesh, in its words, "only computes data gaps that have been directly caused by the changes". Promoting to production swaps views.

The consequence is that a developer environment for a 400-model project costs the compute of the handful of models you touched. Not a full build. Not a clone of the warehouse. The docs make the claim directly: "Environments in dbt cost compute and storage, but creating a development environment in SQLMesh is free."

dbt has pieces of this. dbt clone, added in v1.6, uses the warehouse's own zero-copy clone where it exists. Deferral plus state:modified — Slim CI — lets a pull request build only changed models and read the rest from production. Together they get you most of the way for most teams. The difference is that in dbt this is a pattern you assemble and then have to keep working, and in SQLMesh it is what the tool is.

Plans, and knowing what a change breaks

sqlmesh plan compares your local project to a target environment and shows what will change before anything runs. It sorts modifications into three categories. A breaking change backfills the model and everything downstream. A non-breaking change backfills the model only. A forward-only change reuses the existing physical tables and backfills nothing. Because SQLMesh parses the SQL, it works this out with column-level lineage rather than asking you.

If you have ever merged a change to a staging model and found out two days later that a mart three hops away had been quietly wrong, you know what this is worth. It is the review step dbt leaves to a human reading a diff.

dbt v2 narrows this. Fusion is written in Rust "with a native understanding of SQL across multiple engine dialects", catches incorrect SQL before it reaches the warehouse, and traces model and column definitions across the project. SQL comprehension came to dbt eventually. The plan-and-categorise workflow on top of it has not.

What dbt has that SQLMesh does not

The ecosystem, and it is not close.

Packages for the things you would otherwise write yourself. Adapters for every warehouse anyone runs. Every BI tool, catalogue and orchestrator has a dbt integration, because integrating with dbt is table stakes. Documentation written a hundred times over by people who are not the vendor. Most importantly, a hiring pool: an analytics engineer you hire next month has used dbt and has not used SQLMesh.

There is a second, quieter advantage. dbt is what AI coding tools know. When I write about letting Claude Code write dbt models, the reason it works is that dbt projects are text with a CLI that reports errors clearly, and the model has read an enormous amount of dbt. Ask the same tool for SQLMesh and you get more hallucinated syntax, because there is less of it in the world. That gap will close. It has not closed yet.

And dbt in 2026 is not dbt in 2022. Unit tests arrived in v1.8. Model contracts, versions and access control arrived in v1.5. dbt clone in v1.6. Microbatch in v1.9. If your mental picture of dbt is "Jinja string templating with no tests", you are comparing SQLMesh against a tool that no longer exists.

Who owns what now

This is the part that has changed most, and the part most comparison posts are out of date on. The dates, from the companies' own announcements:

  • 3 September 2025 — Fivetran announces it has acquired Tobiko Data, the company behind SQLMesh and SQLGlot.
  • 13 October 2025 — Fivetran and dbt Labs announce a merger.
  • 25 March 2026 — Fivetran contributes SQLMesh to the Linux Foundation. Initial project members are Benzinga, CloudKitchens, Harness, Infinite Lambda, Jump AI and Minerva. The Foundation's statement: under its governance "SQLMesh will remain vendor neutral".
  • 1 June 2026 — the Fivetran and dbt Labs merger completes. George Fraser is CEO, Tristan Handy is President. The same day, dbt Labs publishes the first alpha of dbt Core v2.0, open-sourcing the Fusion engine runtime under Apache 2.0. The first stable release, 2.0.0, was tagged on 14 September 2026, and the Python v1 line was still getting releases that same week.

Read the order. SQLMesh went to a neutral foundation two months before the merger closed, which is the strongest available signal that it is not going to be quietly retired to protect dbt. What has not been said publicly, as far as I can find, is how one company intends to invest in two transformation frameworks over the next few years. Tobiko Cloud still sells, and tobikodata.com carries the banner "Tobiko Data is now part of Fivetran".

My reading, and it is a reading rather than a fact: the Apache 2.0 licence and the Linux Foundation governance mean a SQLMesh bet made today cannot be taken away from you. What is genuinely uncertain is the pace — whether SQLMesh keeps getting the engineering attention that made it interesting, or settles into maintenance while the money goes to dbt. Nobody outside the company can tell you that, and anybody who says they can is guessing.

Migrating: the adapter is real, the work is in the incrementals

You do not have to rewrite your project to try SQLMesh. Install it with the dbt extra, run sqlmesh init -t dbt in your dbt project root, set a default model start date in sqlmesh.yaml, and run sqlmesh plan. It reads your existing profiles.yml, so connections are not duplicated, and it handles most dbt Jinja methods, snapshots and package management.

The honest limits, from the SQLMesh docs: dbt's recommended incremental logic is not compatible with SQLMesh, so incremental models need tweaking. A handful of Jinja methods are unsupported. And the vocabulary flips — what dbt calls tests are audits in SQLMesh, and SQLMesh tests are unit tests with fixtures.

Which tells you where the migration cost actually sits. Your staging views port almost for free. Your incremental models — the ones with the hand-written is_incremental() blocks, which are the ones you least want to touch — are the work. That is not an accident. Those models are precisely what SQLMesh is rebuilding the mechanism for.

When to stay on dbt

  • Your models are mostly views and full-refresh tables, and builds are cheap.
  • Your team is analysts and analytics engineers, and hiring for a known tool matters.
  • You depend on packages, or on a BI tool or catalogue that reads dbt metadata.
  • Nobody has complained about the dev warehouse bill.
  • You have not yet adopted unit tests, contracts, microbatch or Slim CI. Do that first. It is a much smaller change than a migration, and it may be all you needed.

When SQLMesh is worth the switch

  • Dev environments cost real money, or people skip them because of it.
  • Incremental models are full-refreshed by hand because nobody trusts the watermark.
  • Someone has shipped a change that silently broke a downstream model in the last quarter.
  • Backfills are managed by a person with a list of date ranges.
  • You run several engines, or you want models to be plain SQL the tool can actually check.
  • You are starting a project, have engineers rather than analysts writing the models, and can take the smaller ecosystem.

That last one is worth sitting with. Most of the SQLMesh case is strongest for greenfield projects with an engineering-heavy team. That was the shape when I built my own platform — the teardown of how I run a data platform solo is a Dagster-orchestrated stack, not a dbt one, and the thing that made it workable was the orchestrator knowing what had already been computed. SQLMesh brings that property to SQL modelling, which is why it is interesting regardless of which tool you end up running.

If you want to test your own project against this rather than a blog post, the data platform teardown is the list of questions I would ask first, free and ungated. If you would rather have someone go through the stack properly and tell you whether a migration earns its keep, a Data Platform Audit is a week and a written roadmap you keep. The scoping call below is free.

Primary sources worth reading yourself: the SQLMesh comparison docs, which argue their own side well, and dbt's own post on dbt Core v2.

Common questions

What is SQLMesh?
SQLMesh is an open-source SQL transformation framework — the same job dbt does, built on different foundations. You write models as SQL files, it works out the dependency graph, and it builds tables in your warehouse. What makes it different is that it parses your SQL rather than treating it as a string to template, so it can tell you which downstream models a change actually breaks, and it tracks which date ranges of each incremental model have already been computed. It was built by Tobiko Data and, at the time of writing (September 2026), is a Linux Foundation project under the Apache 2.0 licence.
Is SQLMesh better than dbt?
It is better engineered in specific places, and worse supported everywhere else. SQLMesh's virtual data environments, its plan step, its automatic breaking versus non-breaking change categorisation and its interval tracking for incremental models are genuinely ahead of what dbt does. dbt has the ecosystem: packages, adapters, every BI and orchestration tool, and a hiring pool that already knows it. Pick SQLMesh if the pain you have is one of the four things it fixes. Pick dbt if your pain is that nobody can maintain what you build.
Is SQLMesh open source?
Yes. SQLMesh is Apache 2.0 licensed and the source is public at github.com/SQLMesh/sqlmesh. Fivetran, which acquired Tobiko Data in September 2025, contributed the project to the Linux Foundation in an announcement dated 25 March 2026, with initial project members including Benzinga, CloudKitchens, Harness, Infinite Lambda, Jump AI and Minerva. The Linux Foundation's statement says SQLMesh "will remain vendor neutral". There is also a paid product, Tobiko Cloud, which is a separate commercial thing built around the open-source framework.
Can SQLMesh run an existing dbt project?
Mostly, yes. SQLMesh ships a dbt adapter: you install it with the dbt extra, run `sqlmesh init -t dbt` in your dbt project root, add a default model start date, and then use `sqlmesh plan` and `sqlmesh run` against your existing models. It reads your `profiles.yml`, so warehouse connections are not duplicated. The documented catch is incremental models — the docs say dbt's recommended incremental logic is not compatible with SQLMesh and small tweaks to the models are required. A few Jinja methods are unsupported, and dbt "tests" map to SQLMesh audits while SQLMesh "tests" means unit tests.
What are virtual data environments in SQLMesh?
They are how SQLMesh makes a development environment cost almost nothing. Every version of a model gets a fingerprint and its own physical table; an environment is a set of views pointing at those tables. When you create a dev environment, SQLMesh reuses the physical tables whose fingerprints already exist and only computes the gaps your changes actually caused. Promoting to production swaps views rather than rebuilding data. dbt's nearest equivalents are `dbt clone` and deferral, which help, but they are conventions you apply rather than the model the tool is built on.
Who owns SQLMesh now?
No single company, as of September 2026. Fivetran announced the acquisition of Tobiko Data — the company behind SQLMesh and SQLGlot — on 3 September 2025, and then contributed SQLMesh to the Linux Foundation in an announcement dated 25 March 2026, where it is now governed under an open community model. Fivetran also completed its merger with dbt Labs on 1 June 2026, having announced it on 13 October 2025. So the same company is behind both dbt and the commercial products around SQLMesh, while SQLMesh itself sits with a neutral foundation.
Should I switch from dbt to SQLMesh?
Only if you can name the pain. The four that SQLMesh answers directly are: dev environments that cost real warehouse money, incremental models that get full-refreshed by hand because nobody trusts them, changes that break downstream models nobody spotted in review, and backfills managed with a spreadsheet of date ranges. If none of those describe your week, a migration buys you a smaller ecosystem and a tool your next hire has not used. If two or more do, it is worth a real evaluation on one project.
What are the alternatives to dbt?
SQLMesh is the closest like-for-like — same shape, same SQL-files-and-a-DAG idea, different engineering underneath. The rest are not really like-for-like. Dataform does SQL transformations inside Google Cloud. General orchestrators such as Dagster and Airflow run transformations as one kind of asset among many, and can replace dbt outright if modelling is not the bulk of your work. And plenty of teams write SQL or Python behind an orchestrator with no transformation framework at all, which is more common in production than the tooling conversation admits.

Get new posts by email

Data engineering notes like this one — pipelines, warehouse cost, and what actually breaks in production. A few a month, never padded to hit a schedule.

No sequence, no pitch deck. Reply 'stop' once and you're off — it reaches me, not a queue.

Want the whole playbook?

If this was useful, the long version is my book. Local-First Analytics — 314 pages, runnable code for every chapter — is the full build: DuckDB, Parquet and Arrow, from install to production. On Amazon, or request a free review copy.

Get the book

Not ready to buy? Read chapter 1 free — the whole chapter, no email required.

Rather talk it through? Book a free 30-minute call. No slot that suits your time zone? Email [email protected].