FFastero

Connect any database. Ask in plain English.

Try free
Back to blog

Blog article

dbt vs Dataform: Which SQL Transformation Tool for Your Warehouse?

dbt is the industry standard for SQL transformations with a massive ecosystem and multi-warehouse support. Dataform is free and native inside BigQuery. Your warehouse strategy determines which one makes sense.

Fastero Dev TeamFastero Dev Team
2026-08-06
dbtdataformsql-transformationsdata-engineeringbigquerydata-warehouse
dbt vs Dataform: Which SQL Transformation Tool for Your Warehouse?

dbt is the default choice for SQL transformations in 2026 — it runs against every major warehouse, has thousands of community packages, and an entire certification ecosystem built around it. Dataform is Google's alternative, acquired in 2020 and baked directly into BigQuery's console at no extra cost. If your warehouse is BigQuery and only BigQuery, Dataform is genuinely hard to argue against. If you run Snowflake, Redshift, Postgres, or any multi-warehouse setup, dbt is the only serious option.

How do they approach the same problem differently?

Both tools solve the same core problem: turning raw warehouse tables into clean, tested, documented models using SQL. But they took different design paths to get there.

dbt uses Jinja templating. Your SQL files are actually Jinja templates that compile into raw SQL before execution. This gives you macros, control flow, environment variables, and the ability to write reusable transformation logic that works across models.

-- dbt: models/daily_revenue.sql
SELECT
  date_trunc('day', orders.created_at) AS order_date,
  {{ target.schema }}.customers.segment,
  SUM(orders.amount) AS revenue
FROM {{ ref('stg_orders') }} AS orders
JOIN {{ ref('stg_customers') }} AS customers
  ON orders.customer_id = customers.id
WHERE orders.created_at >= '{{ var("start_date") }}'
GROUP BY 1, 2

Dataform uses SQLX — SQL with JavaScript blocks. Instead of Jinja, you get ${ref()} for references and inline JavaScript for dynamic logic. The JavaScript runs at compile time, same as Jinja, but the syntax feels more natural if you're already comfortable with template literals.

-- Dataform: definitions/daily_revenue.sqlx
config {
  type: "table",
  schema: "analytics",
  description: "Daily revenue by customer segment"
}
 
SELECT
  DATE_TRUNC(orders.created_at, DAY) AS order_date,
  customers.segment,
  SUM(orders.amount) AS revenue
FROM ${ref("stg_orders")} AS orders
JOIN ${ref("stg_customers")} AS customers
  ON orders.customer_id = customers.id
WHERE orders.created_at >= CURRENT_DATE - 30
GROUP BY 1, 2

The Jinja vs JavaScript question is less important than it seems. Both compile to SQL. Both support reusable logic. Jinja has a larger library of existing macros (dbt-utils alone has 60+). JavaScript is arguably more readable if you have never seen Jinja before. Pick your preference — this should not be your deciding factor.

Where does each tool sit in the data stack?

                        ┌──────────────────┐
                        │   Orchestration   │
                        │ Airflow / Dagster │
                        └────────┬─────────┘
                                 │ triggers
          ┌──────────────────────┴──────────────────────┐
          │                                             │
   ┌──────┴──────┐                             ┌───────┴───────┐
   │  dbt Core / │                             │   Dataform    │
   │  dbt Cloud  │                             │  (BigQuery)   │
   │             │                             │               │
   │ Snowflake   │                             │  Built into   │
   │ BigQuery    │                             │  BQ console   │
   │ Redshift    │                             │               │
   │ Postgres    │                             │  Free tier    │
   │ Databricks  │                             │               │
   └──────┬──────┘                             └───────┬───────┘
          │                                            │
          └──────────────┬─────────────────────────────┘
                         │ transformed tables
                  ┌──────┴──────┐
                  │  Downstream  │
                  │  BI / Alerts │
                  │  Fastero     │
                  │  Looker      │
                  │  Metabase    │
                  └─────────────┘

Both sit in the "T" of ELT. Raw data lands in the warehouse via an ingestion tool (Fivetran, Airbyte, custom scripts), then dbt or Dataform transforms it into analytics-ready models. Downstream tools — dashboards, alerts, reverse ETL — consume those models.

Fastero

Connect your database. Ask questions. Get dashboards.

Postgres, BigQuery, Snowflake, and 10+ sources — live-connected, AI-powered, no dashboard builder learning curve.

Try free →

What about testing and documentation?

dbt's testing framework is mature and widely adopted. Schema tests (not_null, unique, accepted_values, relationships) live in YAML files alongside your models. Custom tests are just SQL queries that return failing rows. dbt also generates a documentation site from your YAML descriptions and column-level metadata, complete with a DAG visualization.

Dataform has assertions — SQL queries that must return zero rows to pass. Functionally similar to dbt's custom tests, but without the declarative schema-test shorthand. You write each assertion as a standalone SQLX file. Documentation lives in config blocks within each SQLX file and in a description field, but there is no auto-generated docs site comparable to dbt's.

The gap here is real. dbt's dbt docs generate produces a browsable, searchable catalog of every model, source, test, and column description in your project. Dataform shows documentation in the BigQuery console, which is fine for small projects but lacks the discoverability of a standalone docs site.

How different is the ecosystem?

This is where dbt's ten-year head start shows. The numbers:

  • dbt packages hub: 4,000+ community packages. dbt-utils, dbt-expectations, dbt-date, dbt-audit-helper — odds are someone already built the macro you need.
  • Dataform packages: A handful. Google maintains some official ones. Community contributions exist but the ecosystem is thin.

dbt also has a certification program, an annual conference (Coalesce), a Slack community with 80,000+ members, and more Stack Overflow answers than you will ever need. If you hit a problem, someone has hit it before you.

Dataform's community is effectively a subset of the BigQuery community. Google's documentation is solid but not deep. When you hit an edge case, you are more likely to find yourself reading source code than a blog post.

What does each one cost?

dbt Core dbt Cloud Dataform
License Open source (Apache 2.0) Commercial Free (BigQuery feature)
Hosting Self-managed Managed Managed (inside BQ)
Price $0 ~$100/seat/mo (Team), custom (Enterprise) $0
Warehouses Snowflake, BigQuery, Redshift, Postgres, Databricks, Spark, DuckDB Same as Core BigQuery only
Scheduling External (cron, Airflow, Dagster) Built-in Built-in (BQ Scheduled Queries)
CI/CD GitHub Actions / your own Built-in slim CI Built-in (GitHub/GitLab)
IDE VS Code + dbt extension dbt Cloud IDE (browser) BigQuery console
Version control Git (any provider) Git (GitHub, GitLab, ADO) Git (GitHub, GitLab)
Semantic layer dbt Metrics (built-in) dbt Semantic Layer (Managed) None

The cost story is straightforward. If you are on BigQuery, Dataform is included — zero additional cost. dbt Core is also free, but you need to host and orchestrate it yourself. dbt Cloud adds scheduling, CI, an IDE, and the managed semantic layer, starting around $100 per developer per month.

For small BigQuery teams, Dataform's $0 price tag is compelling. You open the BigQuery console, click into Dataform, connect a repo, and start writing models. No CLI to install, no infrastructure to manage, no separate billing line item.

How do they handle the semantic layer?

dbt introduced its semantic layer — originally dbt Metrics, now powered by MetricFlow — to define business metrics once and expose them to any downstream tool. You define metrics in YAML, and the semantic layer compiles them into SQL on the fly for whatever BI tool or API consumer is asking. It is ambitious and increasingly well-supported, with integrations into Hex, Mode, Lightdash, and others.

Dataform has no semantic layer. Your metric definitions live wherever your downstream tools put them — in Looker's LookML files, in your BI tool's measure definitions, or in a spreadsheet someone forgot to update.

This matters more than it sounds. Without a semantic layer, "monthly recurring revenue" can mean three different things in three different dashboards. dbt's approach — define it once, reference it everywhere — solves a real problem. Tools like Fastero can import dbt metric definitions directly into their own semantic layer, so your metrics stay consistent from warehouse to dashboard to alert.

How does each tool fit with orchestration?

dbt Core needs an external orchestrator. Most teams use Airflow, Dagster, or Prefect to schedule and trigger dbt runs. Dagster has particularly deep dbt integration — it can treat each dbt model as a Dagster asset, giving you lineage and freshness tracking across your entire pipeline, not just the dbt portion.

dbt Cloud handles scheduling internally. You define jobs, set cron schedules, and dbt Cloud runs them. For teams that don't want to own an orchestrator, this is the simplest path.

Dataform has built-in scheduling via BigQuery's scheduled queries infrastructure. You configure run schedules in the Dataform UI or via Terraform. It works, but it is basic — no complex dependency logic across non-Dataform jobs, no conditional branching, no multi-step workflows that mix SQL transformations with Python scripts or API calls.

So which one should you pick?

         What warehouse(s) do you use?
         ├── BigQuery only
         │   ├── Small team, few models? → Dataform
         │   ├── Need semantic layer? → dbt
         │   └── Need rich ecosystem / packages? → dbt
         ├── Snowflake, Redshift, or Databricks
         │   └── dbt (Dataform is not an option)
         └── Multiple warehouses
             └── dbt (only tool that spans them)

Pick Dataform if you are a BigQuery-only team with fewer than ~100 models, you want zero extra tooling cost, and you don't need a semantic layer or deep community package support. The native BigQuery integration is genuinely smooth — no CLI install, no separate infrastructure, and Google maintains it.

Pick dbt if you use any warehouse other than BigQuery, you need the ecosystem (packages, community, certifications), you want a semantic layer for consistent metric definitions, or you are building a data platform that needs to work across multiple warehouses. The upfront setup cost is higher, but the ceiling is much higher too.

One more thing. Whichever tool you pick, the transformed tables it produces are what your downstream tools consume. Fastero connects to the warehouse directly — it reads from the models dbt or Dataform built, then lets you build dashboards, set up automated SQL alerts, and run natural-language queries against those clean, tested tables. It also imports dbt metric definitions so your semantic layer carries through from transformation to analysis.

FAQ

Is Dataform really free? Yes. Dataform is a built-in feature of BigQuery and has no separate pricing. You pay for BigQuery compute when Dataform runs your transformations, but there is no Dataform license fee. Google has kept it free since the acquisition in 2020.

Can I use Dataform with Snowflake or Redshift? No. Dataform originally supported multiple warehouses when it was an independent company, but Google dropped non-BigQuery support after the acquisition. If you need Snowflake or Redshift, dbt is your option.

Is dbt Core hard to set up? Not especially. You install it via pip, create a profiles.yml with your warehouse credentials, and run dbt init to scaffold a project. The first model can be running in under an hour. The complexity comes later — managing environments, setting up CI, orchestrating scheduled runs — which is what dbt Cloud sells.

Can I migrate from Dataform to dbt? Yes, and it is not as painful as you might expect. SQLX and Jinja-templated SQL are structurally similar. The main work is converting ${ref()} to {{ ref() }}, translating config blocks to schema.yml entries, and rewriting any JavaScript-based macros in Jinja. There are community migration scripts that handle the mechanical parts.

Does dbt replace a data warehouse? No. dbt runs inside your warehouse. It submits SQL to Snowflake, BigQuery, or whichever warehouse you use — it does not store or process data itself. You still need a warehouse, and you still pay for the compute dbt's queries consume.

What is the dbt semantic layer? It is a feature (powered by MetricFlow) that lets you define business metrics — like revenue, churn rate, or average order value — in YAML alongside your models. Downstream tools can query these definitions through an API instead of re-implementing metric logic independently. It ships with dbt Cloud and is available in open-source form via MetricFlow.


Try Fastero free — connect to your warehouse, query your dbt or Dataform models with natural language, and build dashboards in minutes. No credit card required.

Ready to try it yourself?

Connect your database, ask questions in plain English, and get live dashboards — in under 2 minutes. No credit card required.