dbt vs Airflow

Transformation vs Orchestration (2026)

dbt transforms data that is already in your warehouse: you write SQL SELECT statements and dbt builds the tables in dependency order, then tests them. Apache Airflow orchestrates: it schedules and watches every step of a pipeline, including the step that runs dbt, and retries the ones that fail. They're not alternatives, and most teams that run both use Airflow to decide when dbt runs and dbt to decide what the warehouse builds.

Last updated: Proudly published by: Jeff Wahl13 min read

dbt vs Airflow: the short answer

dbt is a transformation framework. You write each table as a SQL SELECT, dbt works out the order from the references between them, builds the tables inside your warehouse and tests them. Apache Airflow is a workflow orchestrator. You write a pipeline as a Python DAG of tasks, and Airflow runs each task on a schedule or an event, retries it when it fails, and records what happened.

So the 2 answer different questions. dbt decides what the warehouse layer contains and how each table is built. Airflow decides when every step of the pipeline runs, including the step that runs dbt, and what happens when a step fails. In a typical stack an ingestion tool lands raw data, Airflow triggers dbt build once the data is there, and dbt turns raw tables into staging models and then into the fact and dimension tables that dashboards read.

The only real overlap is scheduling. dbt Core has no scheduler at all; the dbt platform, formerly dbt Cloud, has a job scheduler that can run dbt on a timer. So when every step of the pipeline is SQL inside 1 warehouse, the dbt platform's scheduler is enough. You need an orchestrator at the first step outside the warehouse, and Airflow is the most common one. An API extract or a wait for a file counts, and so does a Spark job or a model retrain.

dbt and Airflow compared at a glance

dbt
  • What it isTransformation tool
  • Unit of workModel (a SELECT)
  • Written inSQL and Jinja
  • Graph built fromref() and source()
  • Where work runsInside the warehouse
  • Schedulingdbt platform jobs only
  • Failure recoveryRerun or dbt retry
  • Data testsBuilt in
Apache Airflow
  • What it isWorkflow orchestrator
  • Unit of workTask
  • Written inPython
  • Graph built fromDeclared task order
  • Where work runsAirflow workers
  • SchedulingCron, events, assets
  • Failure recoveryAutomatic task retries
  • Data testsNone of its own

What dbt does, and what it leaves to other tools

A dbt project is a folder of models, each a SELECT statement in its own file. When 1 model selects from another through ref('stg_orders'), dbt records the dependency, so the project compiles into a graph of models that dbt runs in order. source() does the same for the raw tables an ingestion tool loaded. Nobody maintains a list of steps, because the graph already gives dbt the execution order and table-level lineage, and the docs site is generated from it.

Each model has a materialization that decides what dbt writes: a view, a table rebuilt on every run, an incremental table that only processes new rows, or an ephemeral model inlined into the models that use it. Snapshots record how rows change over time, which is how most dbt projects keep type 2 slowly changing dimensions. dbt build runs models and their tests in graph order, with seeds and snapshots in the same pass, and a failing test makes everything downstream of it skip instead of building on bad data.

The built-in tests (unique, not_null, accepted_values, relationships) check rules you can state in advance. They do not notice a load that arrived 40% short or a column whose values drifted, which is the gap data observability tools fill.

dbt does not extract or load data, doesn't wait for anything outside the warehouse and has no scheduler in its open-source form. It runs SQL, and on some warehouses Python models, on the warehouse's own compute. The dbt tutorial walks through a project from the first model.

2026 changed the product around it. Fivetran and dbt Labs completed their merger in June 2026, and dbt Core 2.0, rebuilt on the Rust foundations of the Fusion engine and still Apache 2.0 licensed, shipped its first alpha in June 2026 and reached release candidate in September 2026. dbt Core 1.12 remains the stable line, and none of this moves dbt into orchestration of steps outside the warehouse.

Prepare for the interview
01 / Open invite
02min.

Know dbt vs Airflow the way the interviewer who asks it knows it.

a dbt vs Airflow query, the same shape a screen would give you.
The diff against expected. Where ties broke. What you missed.
sandbox
1source → bronze → silver → gold
2 ingest : CDC + Kafka
3 transform : dbt + Airflow
4 serve : Snowflake
5
Execute your solution0.4s avg.
AppleInterview question
Solve a dbt vs Airflow problem

What Apache Airflow does, and what it does not know

An Airflow DAG is a Python file that declares tasks and the order between them. A task is an operator configured for 1 job: run a shell command, call an API, submit a Spark job, run a query, start a Kubernetes pod. The scheduler creates a run for each schedule interval or triggering event, hands ready tasks to workers and records each task's state. A task that fails with retries left goes to up_for_retry and runs again after its delay; one whose upstream failed ends upstream_failed without running.

The parts dbt lacks are the point of Airflow. Sensors wait for an external event such as a file landing in object storage. Deferrable operators hand a long wait to the triggerer process so it does not hold a worker slot. Backfills rerun a date range with each run seeing its own interval. When a task fails, the UI shows when it happened and why, and alerts and SLA misses tell someone about it. A guide to Airflow DAGs covers how these pieces are written.

Airflow 3.0, released in April 2025, brought a new UI and DAG versioning. It also moved backfills into the scheduler and added asset-based scheduling; the current release is 3.3.2. Assets let a DAG run when another DAG's task updates a named dataset instead of on a clock. They do not make Airflow aware of data: the Airflow documentation on asset scheduling explains that an asset counts as updated when the task that produces it succeeds, and Airflow never inspects the data itself. What a table contains, and whether it is correct, stays dbt's job.

How dbt fits inside an Airflow DAG

Airflow sees a pipeline as tasks. A daily orders pipeline might be 4: wait_for_file watches for the export, ingest_orders loads it into the warehouse, dbt_build runs the dbt project, and reverse_etl syncs the results to a CRM. Airflow knows the order of those 4 tasks, whether each succeeded, how long it took and when to retry it. It doesn't know what any of them did to the data.

dbt sees the warehouse as models. Inside the dbt_build task sits a second graph: stg_orders and stg_customers clean the raw tables. fct_orders and dim_customers build on them in the order the ref() calls imply. In the simplest setup Airflow runs that whole graph as 1 opaque task.

An Airflow DAG of 4 tasks, wait_for_file, ingest_orders, dbt_build and reverse_etl, where the dbt_build task opens into the dbt graph: stg_orders feeds fct_orders and stg_customers feeds dim_customers, all inside 1 warehouseAn Airflow DAG of 4 tasks, wait_for_file, ingest_orders, dbt_build and reverse_etl, where the dbt_build task opens into the dbt graph: stg_orders feeds fct_orders and stg_customers feeds dim_customers, all inside 1 warehouse

The 2 graphs have different kinds of nodes. Airflow's nodes are steps that can touch any system; dbt's nodes are tables in 1 warehouse. Most design decisions about running them together come down to how much of dbt's graph Airflow should see: the whole project as 1 task, a few tasks split by tag or folder, or 1 task per model.

Airflow vs dbt orchestration: what the dbt scheduler can and cannot do

dbt Core has no scheduler. Something has to call dbt build: a cron entry, a CI workflow such as GitHub Actions, or an orchestrator. For a single warehouse project on a daily cadence, cron plus alerting on the exit code is a legitimate production setup.

The dbt platform has a real job scheduler. A deploy job can run on a cron expression, and the UI also offers simpler interval and specific-hour triggers. On the Starter and Enterprise plans a job can run when another job finishes, which chains jobs across projects. On the Enterprise plans, state-aware orchestration checks each model before it builds and skips the ones whose code and upstream data have not changed.

Every one of those triggers is either a clock or another dbt job. The dbt scheduler can't wait for a file or call an API. It can't run a Spark or Python step outside the warehouse either. Nor can it branch on a condition or retrain a model when a feature table refreshes. When those steps exist, something else must start the dbt job, either through its API or through the dbt Cloud provider for Airflow, and that something is the orchestrator.

When dbt alone is enough, and when you need Airflow too

dbt on its own scheduler is enough when 4 things hold: all transformation happens in 1 warehouse, a managed ingestion tool lands the raw data on its own schedule, a fixed cadence such as hourly or daily meets the freshness your consumers need, and nothing downstream has to react to the run. Many small analytics teams live here for years, and adding Airflow would give them a metadata database and a fleet of workers to keep upgraded, in exchange for nothing.

You have outgrown dbt's scheduler once you write Python to extract from an API or to parse files before dbt can start. Steps outside the warehouse point the same way. They might run on Spark or in a container; some run on a machine learning platform. A pipeline that must wait for something, such as a partner's file or another team's run, is another sign. Conditional logic counts too, such as a heavy rebuild only on Sundays or skipping a mart when its source didn't arrive. So does wanting retries for steps dbt cannot see, with SLAs and paging when they miss. 1 of these can be patched around; 2 or 3 together are the usual reason teams add Airflow.

The opposite mistake happens too. A team that runs Airflow writes its warehouse transformations as SQL strings inside Python operators. It works until there are dozens of tables, and then the team is rebuilding by hand what dbt already does: dependency order and incremental logic first, then snapshots and tests. That is the point where dbt pays for itself.

How to run dbt from Airflow: 4 patterns

A BashOperator that runs dbt build on the Airflow worker is the simplest pattern and the most common first step. It needs dbt and its adapter installed in the Airflow environment, where their Python dependencies can conflict with Airflow's own, and the whole project is 1 task. Splitting the project with selectors, 1 task for the models tagged hourly and another for the daily marts, is the usual first refinement.

The KubernetesPodOperator runs dbt in its own container, which removes the dependency conflict; ECS and Docker have equivalent operators. Because the image pins its own dbt version, each team can upgrade on its own schedule, and the profiles and packages travel in the image too. The trade is start-up time for every pod and artifacts that disappear with the container unless you copy them out.

Teams on the dbt platform keep the job there and let Airflow start it. The dbt Cloud provider for Airflow offers DbtCloudRunJobOperator, which triggers a job and can wait for it in deferrable mode without holding a worker slot, and DbtCloudJobRunSensor, which waits on a run. The catch is 2 schedulers: decide which one owns the timing, or jobs will run twice.

Astronomer Cosmos is open source and currently at version 1.15.1. It parses a dbt Core project and renders it as an Airflow DAG (DbtDag) or a task group inside an existing DAG (DbtTaskGroup), with each model as its own task and its tests run right after it. Airflow then tracks each model separately, so a retry or an alert applies to 1 model. The costs are the parse at DAG load time, a separate dbt start-up for each task in the default local mode, and far more task instances in the metadata database. The watcher execution mode has been stable since 1.15. It runs 1 dbt build and has the per-model tasks follow its progress instead.

What a retry reruns: 1 dbt task vs 1 task per model

Airflow retries tasks, not models, so the task boundary decides how much work a failure costs. Take a 6 model project in which fct_orders hits a warehouse timeout after 4 models have already built, and rpt_revenue depends on it.

Run as 1 dbt build task, the failure fails the task and Airflow's retry runs the same command again: all 6 models, 4 of which had already succeeded. Run as 1 task per model, only fct_orders goes to up_for_retry; the 4 finished tasks keep their success, and after the retry succeeds rpt_revenue runs for the first time, 2 models in all.

Retrying a 6 model dbt project after fct_orders fails: run as 1 dbt build task, the retry runs 6 models and rebuilds 4 that had passed; run as 1 task per model, the retry runs 2 and keeps the 4Retrying a 6 model dbt project after fct_orders fails: run as 1 dbt build task, the retry runs 6 models and rebuilds 4 that had passed; run as 1 task per model, the retry runs 2 and keeps the 4

On a small project the difference is seconds. On a project where the upstream models take an hour of warehouse time, rebuilding them on every retry is an hour of compute and an hour of delay per attempt, and it is the main reason teams move from 1 task to Cosmos or to per-folder tasks.

There's a middle ground that keeps 1 task. `dbt retry` reads run_results.json from the previous invocation and re-executes from the point of failure, so a task whose retry attempt calls dbt retry instead of dbt build skips the models that passed. It needs the target/ artifacts from the failed attempt to still exist, which a fresh pod per attempt does not give you, and it runs nothing if the failure happened before any model started, such as a refused connection.

What dbt and Airflow cost to run

Both open-source cores are free under the Apache 2.0 license: dbt Core and Apache Airflow cost nothing to download. You pay for the hosting and the people who operate it. You also pay for the warehouse compute the dbt models consume, which is the same whichever tool triggers them.

The dbt platform prices by seat. Its Developer plan is free for 1 seat and 3,000 successful model builds a month; Starter costs $100 per developer seat per month for up to 5 seats and 15,000 model builds; Enterprise is quoted. A team of 4 analytics engineers on Starter pays $400 a month, scheduler included.

Managed Airflow prices by environment. On Amazon MWAA a small environment costs $0.49 an hour in US East, which over 730 hours is $357.70 a month before extra workers and metadata storage. Self-hosting removes that bill and replaces it with engineering time: you operate every component yourself, from the scheduler to the metadata database, and you own the upgrades. The move from Airflow 2 to 3 was a migration with breaking changes, not a version bump.

Set side by side, the license line rarely decides it. The deciding cost is the pipeline you can't build without an orchestrator, or the orchestrator you run for a pipeline that never needed one.

How often job postings ask for dbt and Airflow together

Job postings are the cleanest evidence that dbt and Airflow are complements. The site tags every active data engineering posting with the tools it names, and the 2 names travel together far more often than chance would put them on the same page.

Airflow is named on 7.5% of the postings that name any tool, 2,756 of them, and dbt on 5.2%, 1,905. Of the postings that ask for dbt, 50% also ask for Airflow, and 35% of the Airflow postings ask for dbt. That pairing is 5.2 times as common as it would be if the 2 tools were listed independently.

The newer orchestrators have not displaced Airflow in hiring. Even postings that name Dagster mention Airflow 79% of the time, usually because the team runs both or is migrating between them. For a data engineer the practical reading is to learn both: dbt for how the warehouse layer is modeled and tested, Airflow for how every step around it is scheduled and recovered.

Share of data engineering job postings that name each tool

Airflow
7.5%
dbt
5.2%
Dagster
1.4%
Prefect
0.8%

Dagster, Prefect and other ways to orchestrate dbt

Dagster is the orchestrator most often weighed against Airflow for dbt work, because it models pipelines as assets rather than tasks and represents each dbt model as its own asset. The dbt graph and the orchestrator graph become 1 graph, so each model's status and freshness show up in the orchestrator, lineage included, with no translation layer such as Cosmos. The trade is fewer integrations than Airflow's providers offer and a mental model the team has to learn.

Prefect writes flows as decorated Python functions and suits teams whose pipelines are mostly Python. Warehouse-native schedulers, such as the task schedulers built into the big cloud warehouses and lakehouse platforms, can run dbt when every step lives on that platform.

For a new platform with no orchestrator yet, the choice between Airflow and Dagster is real and worth a proof of concept on your own dbt project. For a team with a working Airflow deployment, Airflow 3 assets plus Cosmos close most of the gap, and a migration rarely pays for itself.

Where data modeling meets orchestration: dbt snapshots

dbt is where most teams encode their dimensional model, and snapshots are the clearest case of the 2 tools depending on each other. A snapshot compares the current source rows with the last recorded version and writes a new version with dbt_valid_from and dbt_valid_to whenever a row changed, detected by an updated_at timestamp or by comparing chosen columns. That is a type 2 slowly changing dimension with the merge logic written for you.

A snapshot only records the changes it sees, so its schedule is part of its correctness. A customer record that changes twice between 2 snapshot runs keeps only the second change. That's why snapshots often run more often than the nightly models built on them, which is a cadence decision that belongs in the orchestrator, not in the SQL.

The production questions that follow are orchestration questions too: how fast the snapshot table grows, how you backfill it when a source was wrong for a week, and how you rebuild a dimension without losing history. None has a dbt-only answer.

How interviewers test dbt and Airflow knowledge

Interviewers rarely ask which tool is better. They give a scenario and listen for whether you keep transformation and orchestration in separate layers. A common opener is to design the pipeline behind a set of dashboards: a strong answer names the ingestion tool, the orchestrator, the dbt layers from staging to marts, where freshness checks live and who is paged when a source is late.

Failure questions follow. What happens when 1 model fails halfway through a run, and what does the retry rerun? Explaining that a whole-project retry of a 6 model project can rebuild 4 models that had already passed, and how to avoid it, is exactly the reasoning they want. Late-arriving events are another favorite: an incremental model that filters on the maximum loaded timestamp misses rows that arrive late, and the fix is a lookback window with a merge on a unique key, sized against how late the data really arrives.

These scenarios sit in the system design round of a data engineering interview. To prepare, work through the data pipeline interview questions, the orchestration-specific Airflow interview questions, and the data pipeline practice problems, which make you build the transformations an orchestrator would run.

dbt vs Airflow FAQ

Are dbt and Airflow really competitors?+
No. dbt is a transformation framework that turns SQL SELECT statements into tested tables inside 1 warehouse. Airflow is an orchestrator that runs and monitors the steps of a pipeline, retrying any that fail, and one of those steps is usually the dbt run. They overlap only on scheduling, and only when dbt runs on the dbt platform, whose job scheduler can run dbt on a timer without Airflow.
Should I learn dbt or Airflow first?+
Learn dbt first if you're aiming at analytics engineering or a warehouse-heavy role: it is SQL you already know plus a small set of ideas (models, ref, tests, materializations). Learn Airflow first if you are aiming at platform or pipeline work, where interviews turn on scheduling and retries, and on backfills that only work if tasks are idempotent. Airflow appears on 7.5% of tool-tagged data engineering postings and dbt on 5.2%, and the 2 are often listed together, so most data engineers end up needing both.
Is dbt Core or dbt Cloud (the dbt platform) the right choice?+
dbt Core is the free, open-source command line tool; it has no scheduler, so something else has to call it. The dbt platform, formerly dbt Cloud, adds a job scheduler with cron triggers and job chaining, plus a hosted IDE and CI. Its Developer plan is free for 1 seat and 3,000 successful model builds a month, and its Starter plan costs $100 per seat per month for up to 5 seats. Teams that already run Airflow usually run dbt Core from it; teams without an orchestrator often start on the platform.
Can I use dbt without Airflow?+
Yes. The dbt platform's scheduler runs jobs on a cron or interval and can chain 1 job after another, and dbt Core can run from cron or from any CI system such as GitHub Actions. That's enough while every step lives in the warehouse. You need Airflow once the pipeline has to wait for files, call APIs, run non-SQL compute or coordinate with other teams' jobs.
Can I use Airflow without dbt?+
Yes. Many Airflow deployments have no dbt at all: they run SQL through the database providers' SQL operators, or they run Spark and Python jobs. dbt becomes worth adding when the warehouse layer grows past a few dozen SQL files and the team wants dependency order from ref and tests on every table without writing that machinery by hand. Documentation and lineage come with it.
Should I migrate from Airflow to Dagster?+
Consider Dagster for a new platform. Dagster represents each dbt model as its own asset, so the dbt graph and the orchestrator graph are the same graph, with per-model status and lineage out of the box. For a team with an established Airflow deployment, Cosmos gives most of the per-model visibility without a migration, and Airflow 3 added asset-based scheduling of its own.
Does Cosmos solve the dbt-model visibility problem in Airflow?+
Mostly. Astronomer Cosmos parses a dbt Core project and renders each model as its own Airflow task or task group, with its tests after it, so the Airflow UI shows model-level status and retries reach 1 model. The costs are parsing the project when Airflow loads the DAG and many more task instances in the metadata database. Its watcher execution mode, stable since version 1.15, runs the project as 1 dbt build and lets the per-model tasks follow it, which cuts the per-task dbt start-up cost.
How important is Airflow knowledge for data engineering interviews?+
Important enough to prepare deliberately. Airflow is named on 7.5% of data engineering postings that name any tool, more than any other orchestrator. Interviewers rarely ask for operator names; they ask how you would schedule a pipeline and what happens when a task fails halfway. Expect to explain how you backfill a month without double counting and where the retries and alerts are configured. The same questions apply if the team runs Dagster or Prefect.
02 / Why practice

The candidate who gets the offer

  1. 01

    Reading a solution is not the same as writing one

    Every engineer who has frozen on a query they had read a dozen times knows the gap. The only preparation that closes it is producing the answer yourself, under time, before the interview does it for you

  2. 02

    76% of hiring managers reject on the coding task, not the resume

    From HackerRank's 2024 Developer Skills Report. Candidates who look strong on paper still fail the live screen if they haven't done timed, executable practice

  3. 03

    System design comes down to the calls you defend out loud

    Ingestion, batch vs streaming, the bronze/silver/gold layers, idempotency, backfill and replay. Sketching the pipeline and naming the failure modes is the signal, not the boxes

Related guides