Skip to content
Reviewed by Siddharth Sharma Sep 21, 2026

Home › Guides › dbt Tutorial for Beginners

Tutorial · 2026

dbt Tutorial for Beginners 2026: Build and Test Your First dbt Model in 8 Steps

This dbt tutorial for beginners walks you through installing dbt Core, connecting it to a local DuckDB file, and building a tested model in 8 steps. dbt turns plain SQL SELECT statements into version-controlled, tested, documented tables. You need Python 3.9 or newer, a terminal and about ninety minutes of uninterrupted time.

21 September 2026·12 min read·By the 360 Digital Transformation Editorial Team
Key takeaways
  • dbt is a compiler, not a database. It takes your SELECT statements, resolves the dependency order, and issues CREATE TABLE or CREATE VIEW against a warehouse you already own.
  • You do not need a cloud warehouse. The dbt-duckdb adapter runs the whole project against one file on your laptop, and documents support for dbt-core 1.8.x or newer with DuckDB 1.0.0 or newer.
  • Pin to dbt Core 1.x while you learn. 1.12.3 was stable as of 20 August 2026; v2.0 on the Rust engine is out, but the adapter ecosystem is still catching up.
  • Tests are the reason to bother. dbt ships four generic data tests, and dbt build stops downstream models running when an upstream test fails.
  • The free tier is real. dbt's Developer plan is free forever at one seat, one project and 3,000 model builds a month.
  • Skip snapshots, exposures and macros in week one. Sources, models, refs and tests carry most of the value.

Picture a two-person data team at a mid-size logistics firm in Pune. Forty SQL scripts sit in a scheduler, each starting with a DROP TABLE, and nobody remembers which one feeds the daily revenue report. When a number looks wrong on Monday, finding out why takes most of Monday. That is the problem dbt was built for, and this tutorial gets you to a working, tested project on your own machine first.

What Is dbt in Data Engineering, and Why Teams Moved to It

dbt (data build tool) does one job: it manages the T in ELT. Raw data is already sitting in your warehouse, loaded by Fivetran or Airbyte or a nightly copy job. dbt is what turns that raw data into the clean tables your dashboards read from.

The mechanism is simpler than the marketing suggests. You write stg_orders.sql containing a single SELECT, and inside it, instead of a hardcoded table name, you write {{ ref('raw_orders') }}. dbt reads every file, works out which model references which, and runs them in the right order, wrapping each in the CREATE statement its materialization calls for. You never write DDL, and you never hand-build an orchestration DAG.

For the Pune team that changes the failure mode. Instead of forty independent scripts they get one graph they can query: which models feed fct_daily_revenue, and which broke. Modelling of exactly this shape is a core DP-700 skill, practised live in 360DT's Microsoft Fabric data engineering program.

The three numbers to know before you install anything

Version, free-tier ceiling and built-in test count.

1.12.3
Stable dbt Core release as of 20 August 2026, the version this tutorial targets
3,000
Model builds a month on dbt's free Developer plan, at one seat and one project
4
Generic data tests dbt ships with: unique, not_null, accepted_values, relationships

Version and plan limits checked against dbt Labs release notes and pricing pages on 21 September 2026.

Where dbt genuinely does not help

dbt is not an orchestrator. The open-source distribution has no scheduler and no retry policy, so something still has to call dbt build on a cron or in Airflow. It is batch-only: if you need sub-minute freshness, dbt is the wrong shape entirely. And if you are one analyst maintaining twelve queries, the scaffolding, the YAML and the git discipline will cost you more than they save for the first two months. Adopt it when you have a second person, or a second consumer of your tables.

The dbt Tutorial for Beginners Setup: Install dbt Core and DuckDB

Here is the call I would make in your position, and what it costs. Learn on dbt Core with DuckDB, not in dbt's browser IDE. You give up the hosted scheduler and the lineage viewer. You get the command line, real files in git, and a project that runs offline in under a second, so you iterate instead of waiting on a remote warehouse.

Create a clean virtual environment first. dbt pins a lot of Python dependencies and will happily break an existing one.

python3 -m venv dbt-env
source dbt-env/bin/activate        # Windows: dbt-env\Scripts\activate

pip install "dbt-core==1.12.3" "dbt-duckdb" "duckdb>=1.0.0"
dbt --version

One detail there will trip you up. dbt Labs has begun renaming the packages: pip install dbt-core still works today, but the open-source distribution is migrating to pip install dbt-oss, while pip install dbt now installs the Rust-based v2 engine. Type pip install dbt expecting 1.x and you will get something else, with error messages that do not point at the cause.

On dbt Core v2, and why this tutorial ignores it

dbt Core v2.0 is real, Apache 2.0 licensed, and genuinely fast: dbt Labs reports a 5,000-model project parsing in under four seconds on a 16-core workstation. It is also new, and adapter coverage outside the big warehouses is still settling. Learn 1.x this month. The model files, ref(), the YAML and the mental model carry over unchanged, and you can move later in an afternoon.

The 8 Steps, Start to Finish

The eight steps, and what you have at the end of each

Each step ends in something visible on disk or in the terminal, so you know it worked.

Step 1

Install and verify

dbt --version prints both the core and adapter versions.

Step 2

Scaffold the project

dbt init creates the folder tree. You care about three directories: models, seeds and tests.

Step 3

Connect and debug

A four-line profile pointing at a local .duckdb file. dbt debug returns "All checks passed!" or names the broken line.

Step 4

Seed raw data

dbt seed loads two CSVs as real tables, so you can model without ingestion tooling.

Step 5

Write staging models

One model per raw table: rename, cast, no joins. Views, because they cost nothing to rebuild.

Step 6

Write the mart model

The table your dashboard reads. Joins staging models via ref(), materialized as a table.

Step 7

Add data tests

A schema.yml with not_null and accepted_values. dbt test now fails loudly when the grain breaks.

Step 8

Build and document

dbt build runs everything in dependency order. dbt docs serve gives you the lineage graph.

Sequence follows the dbt Developer Hub project structure guidance, checked 21 September 2026.

Steps 2 and 3: scaffold, then connect

Run dbt init jaffle_logistics and pick duckdb when it asks for the adapter. Then open ~/.dbt/profiles.yml. This file breaks most first attempts, because the profile name inside it must match the profile: line in dbt_project.yml character for character.

jaffle_logistics:
  target: dev
  outputs:
    dev:
      type: duckdb
      path: 'jaffle.duckdb'
      threads: 4

That is the whole connection. path resolves relative to your profiles.yml, and leaving it out makes dbt-duckdb run in memory and throw your tables away when the command finishes. Now run dbt debug: it checks the profile, the connection and the project file separately and tells you which one failed, which makes it the most useful command in the tool.

Step 4: seed the raw data

Put a file at seeds/raw_orders.csv with the header order_id,customer_id,order_date,status,amount_inr and a dozen rows, deliberately including one cancelled status and one null customer_id so your tests have something to catch. Do the same for seeds/raw_customers.csv, then run dbt seed. Seeds are for small, static, version-controlled reference data; loading a 400MB CSV through them is the first thing people do wrong.

Steps 5 and 6: the models

Create models/staging/stg_orders.sql. A staging model does one thing: it makes a raw table pleasant to use. Rename, cast, filter junk. No joins, no business logic.

{{ config(materialized='view') }}

select
    order_id,
    customer_id,
    cast(order_date as date)  as ordered_at,
    lower(status)             as order_status,
    amount_inr                as amount_inr
from {{ ref('raw_orders') }}
where customer_id is not null

Now the mart, which is the table a Power BI report would point at. Building this kind of fact table is the daily work of a BI developer, which is why it sits in the syllabus of 360DT's data analyst program covering SQL and Power BI alongside the PL-300 objectives.

{{ config(materialized='table') }}

select
    o.ordered_at,
    c.customer_region,
    count(distinct o.order_id)                      as orders,
    sum(case when o.order_status = 'cancelled'
             then 0 else o.amount_inr end)          as net_revenue_inr
from {{ ref('stg_orders') }}     as o
left join {{ ref('stg_customers') }} as c
       on o.customer_id = c.customer_id
group by 1, 2

There is no CREATE TABLE anywhere. The materialized='table' config tells dbt to wrap that SELECT in the right DDL for DuckDB. Swap the adapter to Snowflake or Microsoft Fabric tomorrow and the same file compiles to that warehouse's syntax. That portability is the actual product.

Also read: SQL Query Optimization in 2026: 10 Mistakes That Make Queries Slow, because a dbt model is only ever as fast as the SELECT inside it.

Step 7: dbt Tests, So Bad Data Fails the Build

People skip this step, and it is the one that pays for the whole exercise. Create models/marts/schema.yml:

version: 2

models:
  - name: fct_daily_revenue
    description: "Daily net revenue by customer region."
    columns:
      - name: ordered_at
        data_tests:
          - not_null
      - name: customer_region
        data_tests:
          - accepted_values:
              values: ['north', 'south', 'east', 'west']
      - name: net_revenue_inr
        data_tests:
          - not_null

Use data_tests:, not tests:. dbt renamed the key when unit tests arrived in 1.8; tests: still works for backward compatibility but is soft-deprecated and will eventually be removed, and you cannot use both on the same resource.

A generic test compiles to a SELECT that should return zero rows. not_null becomes roughly select * from model where column is null. Anything it returns is a failure. That is the entire mechanism, which is why writing your own custom generic test later takes ten minutes rather than an afternoon.

Step 8: dbt build, and How the DAG Actually Runs

Run dbt build. It differs from dbt run in a way that catches people out: dbt run only materializes models, whereas dbt build interleaves seeds, models, snapshots and tests in dependency order, and when an upstream test fails it skips every downstream model instead of building on known-bad data. Use dbt run while iterating on one model's SQL, and dbt build in CI and production, always.

What dbt build actually does with your project

Seeds become tables, staging becomes views, the mart becomes a table, and a failing test blocks everything downstream.

How a dbt build executes a small project Two seed CSV files load into raw tables, each feeding a staging view, both staging views feed a single fact table, and a data test gate sits below the fact table blocking downstream models when it fails. raw_orders.csv seeds/ raw_customers.csv seeds/ stg_orders materialized: view stg_customers materialized: view fct_daily_revenue materialized: table data tests not_null & accepted_values dbt seed dbt seed ref() ref() fail blocks downstream

Execution order follows documented dbt build behaviour, checked 21 September 2026.

The command reference you will actually use

Command What it does When you run it
dbt debug Tests the profile, the connection and the project file separately First, every time something mysterious breaks
dbt seed Loads CSVs from seeds/ into the warehouse as tables After editing a seed file
dbt run Materializes models only, in dependency order While iterating on one model's SQL
dbt test Runs data tests against models that already exist To check data quality without rebuilding
dbt build Seeds, models, snapshots and tests together, skipping downstream on failure In CI and in production, always
dbt run --select stg_orders+ Builds that model and everything downstream of it After changing a staging model in a big project
dbt docs generate && dbt docs serve Builds the catalogue and opens the lineage graph in a browser Before a handover, or when someone asks what feeds a number
dbt ls --select tag:daily Lists matching resources without running anything To sanity-check a selector before trusting it in a job
Live course

Take dbt-style modelling from your laptop into a real Fabric warehouse

Live online·Sat–Sun, 8–11 PM IST·50+ hrs·Rs 24,999

A live weekend program over 8 weeks covering Microsoft Fabric data engineering for the DP-700 certification, with DP-900 fundamentals included. Includes hands-on projects, mentor support and placement guidance, with a batch starting 28 Nov 2026.

Explore the course
Microsoft Fabric Data Engineer Course (DP-700 + DP-900 + Claude)

What Usually Goes Wrong in a dbt Tutorial for Beginners

Four things break for nearly everyone on a first project, and all of them have a one-line fix.

The four first-project failures

Recognise the symptom, skip the two hours of searching.

1

The profile name mismatch

The profile: key in dbt_project.yml must match the top-level key in profiles.yml exactly. A trailing space counts.

Run dbt debug
2

Hardcoded table names

from stg_orders instead of from {{ ref('stg_orders') }} runs once, then dbt has no idea the models are connected and builds them out of order.

Always use ref()
3

Everything materialized as a table

Staging rebuilt as physical tables triples build time for no benefit. Only the marts your dashboards hit need to be tables.

Views for staging
4

Tests written but never enforced

If your scheduler calls dbt run, the tests never execute. Change it to dbt build.

Build, not run

Failure patterns compiled from dbt Developer Hub troubleshooting guidance, reviewed 21 September 2026.

The error messages, decoded

What you see What it means Fix
Could not find profile named 'x' dbt_project.yml points at a profile that is not in profiles.yml Match the two names; run dbt debug to confirm
Compilation Error: model depends on a node named ... which was not found A ref() points at a model or seed that does not exist Check the filename, not the table name. dbt refs the file
Found a cycle Two models reference each other Break the loop; push the shared logic into a third upstream model
Database Error: Catalog Error: Table ... does not exist You ran dbt run before dbt seed Use dbt build, which orders seeds before models
FAIL 3 accepted_values_... Three rows hold a value outside your allowed list Run the compiled test SQL from target/compiled/ to see the offending rows

And here is the one documentation will not warn you about. Someone adds a column to a source table upstream, your staging model still runs green because the explicit column list does not care, and three weeks later an analyst asks why the new field never reached the mart. dbt stays silent. Source freshness checks are how you find out in a day instead of a month.

dbt Core or the dbt Platform: What the Free Tier Actually Gives You

dbt Core is Apache 2.0 licensed and free with no ceiling. On the hosted platform you are paying for the scheduler, the browser IDE, hosted docs and access controls. The Developer plan is free permanently, not a trial, at one seat, one project and 3,000 successful model builds a month, with the browser IDE, MFA and job scheduling included. Starter is listed at 100 US dollars per user per month with five seats and 15,000 model builds. For the Pune team's first six months, free is genuinely sufficient.

My view: do not pay until scheduling is the bottleneck. A GitHub Actions workflow that checks out your repo and runs dbt build on a cron costs nothing and teaches you more about deployment than the hosted scheduler will. That pipeline work and its secrets handling is covered live in 360DT's AWS Solutions Architect and DevOps program, with the Azure Pipelines equivalent in the Azure architect and DevOps track; the full certifications overview lays the exam codes out side by side.

Also read: What Is Apache Iceberg in 2026?, the storage layer your dbt models increasingly write into.

Where dbt Fits in the Rest of Your Stack

In analytics engineering, dbt is the job: you own the transformation layer between ingestion and the BI tool, and it is now advertised as its own title rather than a senior analyst variant. In platform teams, dbt is one node in an Airflow or Dagster graph and your real work is orchestration, CI and warehouse cost. In machine learning, dbt builds the feature tables a training job reads, which is the seam 360DT's MLOps engineer course works on.

There is a newer one. Teams building retrieval systems use dbt to prepare the structured half of the context an agent sees, so a model answering "what did the Pune depot ship last quarter" hits a governed table rather than guessing, which is the pattern taught in the AI engineer course covering RAG and agents. To judge a live cohort before paying, the free webinars are the cheapest look, and a demo class takes an hour.

Also read: Data Engineer Roadmap 2026: 7 Steps to Land Your First Job in India for where this tutorial sits in a full learning path.

If I were starting this week I would finish the eight steps tonight on DuckDB, then rebuild the same project against a real warehouse on Saturday and push it to GitHub with a working CI job. That second version is what gets you interviews, because it proves you understand deployment and not just SQL. The tutorial is free and takes an evening. The judgement about what belongs in staging versus marts takes longer, and that is the part worth finding a cohort for.

Frequently asked questions

Is this dbt tutorial for beginners enough to start without a cloud warehouse?

Yes. Everything here runs against a single local DuckDB file, so there is no account and no bill. The dbt-duckdb adapter documents support for dbt-core 1.8.x or newer with DuckDB 1.0.0 or newer. Point the same project at Snowflake or Microsoft Fabric later and only profiles.yml changes.

What is dbt used for in data engineering?

It manages the transformation step of ELT. You write SELECT statements, dbt resolves their dependencies through ref(), generates the CREATE TABLE or CREATE VIEW statements, runs them in order and tests the results. It does not move data and does not schedule itself.

Is dbt free?

dbt Core is open source under Apache 2.0 with no usage limit. The hosted platform's Developer plan is free permanently at one seat, one project and 3,000 successful model builds a month; Starter is listed at 100 US dollars per user per month with five seats.

Do I need to know Python to learn dbt?

No. You need enough Python to run pip and a virtual environment; after that you write SQL and YAML. Jinja appears in dbt, but for your first three months the only Jinja you need is ref(), source() and config().

What is the difference between dbt run and dbt build?

dbt run materializes models only. dbt build runs seeds, models, snapshots and tests in dependency order, and when a test fails it skips everything downstream. Use run while developing, build in CI and production.

Should I learn dbt Core 1.x or dbt v2 in 2026?

Learn 1.x first. Version 1.12.3 was stable as of 20 August 2026. dbt Core v2.0, rebuilt on the Rust engine and still Apache 2.0, parses far faster but adapter coverage is still settling. The project files and concepts carry over unchanged.

How long does it take to learn dbt?

An evening for a first project like this one. Four to six weeks of part-time work to be useful on a team, because the hard part is modelling judgement about staging, marts and grain, not the tool.

Does dbt replace Airflow?

No. dbt orders models within a single build; it does not schedule runs, retry across systems or coordinate ingestion. Most teams run dbt as one task inside Airflow, Dagster or a GitHub Actions cron job.

About this guide. 360 Digital Transformation is an Anthropic Partner and a Microsoft Authorized Training Partner. Other certification bodies, vendors and employers named here are not affiliated with us. Tools and versions change quickly; commands and figures cited were checked on 21 September 2026.

Learn it live with 360 Digital Transformation

Turn this guide into a skill employers can see

Live weekend cohortEMI available

Microsoft Fabric Data Engineer Course (DP-700 + DP-900 + Claude)

Rs. 24,999Rs. 31,249 Save 20%

Tools and platforms you work with

  • Microsoft Fabric
  • Apache Spark and PySpark
  • Delta Lake
  • T-SQL
  • Python
  • Fabric Notebooks
  • Git
  • GitHub
Add bonus modules
See the syllabus and batch dates

Other live courses on this career path