dbt Seeds: What They Are, When to Use Them, and dbt seed Examples
Learn how to use dbt seeds to turn small CSV files into reliable, version-controlled tables in your warehouse. Clear use cases, configs, and examples.
On this page · 24 sections
- What is a dbt seed?
- But what makes seeds so useful?
- Typical seed use cases
- Seeds vs alternatives
- Project layout and seed configuration
- How to run seeds
- using dbt's seed with leading zeros and data checks
- End-to-end example: a tiny seed that saves a big join
- Seeds with sources, exposures, and structure
- FAQ
- What is a dbt seed?
- What are dbt seed files?
- Is dbt the same as Databricks?
- What is dbt and why is it used?
- Can I store my seeds in a directory other than the seeds directory in my project?
- Can I use seeds to load raw data?
- Do hooks run with seeds?
- How do I build one seed at a time?
- How do I preserve leading zeros in a seed?
- Practical tips
- From zero to loaded
- A note on counts, types, and governance
- Quick glossary
- Primary sources and further reading
- Topic
- dbt for Analytics Engineers
- Category
- dbt
Quick answer: a dbt seed is a CSV file in your project's seeds/ folder that dbt seed loads into a warehouse table. You reference it like a model, with ref('country_codes'). Use seeds for small, rarely changing lookup data that belongs in version control, such as country codes, mapping tables, or test fixtures. Do not use them to load raw source data or anything large; that belongs in your ingestion tool.
What is a dbt seed?
A dbt seed is a small, static table built from a CSV and materialized by dbt. Seeds are ideal for stable reference data you want stored directly in the data warehouse and managed in Git with your dbt project. Because a seed is static, there’s no external ingestion job or flaky upstream API—just the CSV and dbt.
In short: seeds are CSV files under version control that dbt loads into your warehouse as tables. You reference a seed with ref('seed_name') like any other model, and it participates in your lineage and downstream builds.
But what makes seeds so useful?
- Speed and reliability: A small seed avoids an extra upstream pipeline for tiny reference data.
- Governance: The seed is version controlled alongside dbt code, so reviews catch risky changes.
- Portability: Seeds run the same in dev and prod. No environment-specific scripts.
- Simplicity: No extra connectors to load csv files; dbt handles it.
Typical seed use cases
- Country codes and region mappings (ISO2/ISO3, EU membership flags).
- Currency symbols and rounding rules.
- Legacy ID to canonical ID mappings after a system migration.
- Feature flags for analytics-only toggles.
- Data quality exceptions lists (e.g., SKUs intentionally excluded from metrics).
If you’re evaluating seeds and sources together, prefer a seed when the data is static, tiny, and curated by your team; prefer a source when it originates in an operational system. For a deeper primer on references, see dbt ref() vs source(): Model-to-Table References Explained.
Seeds vs alternatives
| Option | Best for | Pros | Cons |
|---|---|---|---|
| dbt seed | Small, static reference tables | Version controlled, simple, easy to ref() |
Not meant for large datasets; full replace on run |
| Source table | Operational or raw data | Upstream ownership, scalable ingestion | Requires ingestion pipeline and monitoring |
| Hardcoded SQL/Jinja | Tiny lists embedded in a model | No files; fast to prototype | Hard to review, awkward diffs, duplicated across models |
Project layout and seed configuration
Place seeds under the seeds/ directory by default. You can nest folders to organize by domain.
my_dbt_project/
models/
seeds/
geography/
country_codes.csv
commerce/
sku_exclusions.csv
dbt_project.yml
Configure seeds in dbt_project.yml. Here’s a practical seed configuration that sets schema, quoting, and column types:
name: my_dbt_project
version: 1.0.0
profile: default
# Store seeds somewhere else? Customize the path.
seed-paths: ["seeds", "shared/reference_data"]
seeds:
+schema: reference
+quote_columns: true
geography:
country_codes:
+column_types: # preserve types and leading zeros
iso2: string
iso3: string
country_name: string
eu_member: boolean
That seed configuration ensures a consistent schema and protects formatting-sensitive fields. To preserve leading zeros in codes like "00123", specify string in column_types or quote values in the CSV.
How to run seeds
From your project root, run:
dbt seed
The run creates or replaces each seed table under the configured schema. The dbt seed command loads all eligible files; to build one seed at a time, select it explicitly:
# By name
dbt seed --select country_codes
# By path
dbt seed --select path:seeds/geography/country_codes.csv
Because a seed is static, dbt fully reloads it each time. If you need incremental behavior, a model is a better fit.
using dbt's seed with leading zeros and data checks
For CSVs with padded numeric strings, set +column_types to string and write a quick test to catch accidental numeric casts:
# tests/assert_iso2_format.sql
select *
from {{ ref('country_codes') }}
where length(iso2) != 2 or iso2 != upper(iso2)
Attach that to the seed in YAML:
version: 2
seeds:
- name: country_codes
description: ISO mappings for countries
tests:
- not_null:
column_name: iso2
- unique:
column_name: iso2
- assert_iso2_format
End-to-end example: a tiny seed that saves a big join
Your orders table has 40M rows. You need a reliable region field per order. Instead of joining to a raw data API snapshot with inconsistent keys, create a small country_codes seed and join locally.
-- models/fct_orders.sql
with base as (
select * from {{ ref('stg_orders') }} -- staged from raw data
),
geo as (
select * from {{ ref('country_codes') }} -- the seed
)
select
b.order_id,
b.country_iso2,
g.region,
b.order_total
from base b
left join geo g
on b.country_iso2 = g.iso2;
That seed makes the transformation deterministic, avoids flakey upstream merges, and keeps the dataset logic close to your dbt models. Because the seed is version controlled, reviewers can audit changes that affect downstream models.
Seeds with sources, exposures, and structure
For a mental model of seeds and sources: seeds are curated reference data you author; sources are external tables you declare. Use the ref/source patterns consistently; see dbt ref() vs source(): Model-to-Table References Explained.
If you publish key semantic assets built atop a seed, document them with exposures; the dbt Exposures: Exposure Lineage, Selectors — dbt Developer Hub guide shows how to capture downstream dashboards and notebooks.
For recommended folders and naming across your dbt project, skim dbt Project Structure: Staging, Intermediate, and Marts Done Right. If you need a full calendar, prefer a generated model over a seed; see dbt Date Spine: Build a Calendar Hub Table.
FAQ
What is a dbt seed?
A seed is a CSV turned into a table by dbt. It’s static, small, and ideal for reference data your team curates.
What are dbt seed files?
A seed file is a CSV file placed under your project’s seed paths that dbt loads into your data warehouse as a table when you run dbt seed.
Is dbt the same as Databricks?
No. dbt is a framework for SQL-first data transformation and modeling; Databricks is a lakehouse platform. Many teams use dbt on Databricks, but they are different tools. For understanding dbt, start at the dbt topic hub.
What is dbt and why is it used?
dbt lets analytics engineers use dbt to manage SQL models, tests, documentation, and deployments as code. It standardizes data transformation in the warehouse and integrates with your data pipeline for reliable, reviewable builds.
Can I store my seeds in a directory other than the seeds directory in my project?
Yes. Set seed-paths in dbt_project.yml to any list of folders. You can also nest subdirectories for domain separation.
Can I use seeds to load raw data?
Generally no. Seeds are for small, static reference data. For large or fast-changing raw data, declare a source and ingest via your warehouse or EL tools. Then join the source to a seed when you only need a tiny curated mapping.
Do hooks run with seeds?
Model pre-hook/post-hook configs don’t run for seeds. Project-level on-run-start/on-run-end do run for a seed invocation, so you can log or set session vars if needed.
How do I build one seed at a time?
Use selection syntax: dbt seed --select country_codes or dbt seed --select path:seeds/geography/country_codes.csv.
How do I preserve leading zeros in a seed?
Set the seed’s +column_types to string (or your warehouse’s text type) for those columns, or quote the values in the CSV. Tests can enforce formatting.
Practical tips
- Size: Keep each seed small. If a seed grows into thousands of lines that change weekly, move it to an external table.
- Review process: Because a seed is version-controlled, treat it like code. Reviews should verify semantic changes, not just diffs.
- Quoting: Quote values in the CSV when whitespace or leading zeros matter, and match with explicit types.
- Naming: Use clear, singular names for each seed. Name columns to match join keys used in downstream models.
- Schema: Put seeds in a dedicated schema (e.g.,
reference) so they’re easy to find and govern.
From zero to loaded
To load the seed and make it available for downstream work, put a CSV under your seed path, configure types, and run dbt seed to load into your data warehouse. After that, the data in your data warehouse includes a small, curated table that’s easy to join to and reason about. This is the simplest way to manage static data in your data without an external job, and it fits cleanly into any data pipeline.
A note on counts, types, and governance
Because seeds are static, treat them as documentation-backed contracts. Define column types, add tests, and audit changes. If your seed data starts to drift from reference data into general-purpose facts, migrate it to a proper ingested table to keep your pipeline sustainable.
Quick glossary
- Seed: A CSV-backed, static table built by dbt.
- Seed data: Curated mappings or lists committed with code.
- Seed file: The on-disk CSV for a seed.
- dbt seed: The CLI action that builds seeds.
- Dataset: Any collection of related records; seeds are tiny datasets.
If you’re ready to use dbt seeds in a real project, remember: seeds are csv files, scoped and deliberate. They shine when they’re small, stable, and clearly owned. For more on lineage and publishing analytics built on seeds, revisit the exposures guide on the dbt developer hub.
Keep learning: explore the dbt topic hub, and practice with our free graded exercises at /practice.
Primary sources and further reading
The implementation details and product behavior in this guide were checked against these primary references:
- Add Seeds to your DAG — dbt Labs
- About dbt seed command — dbt Labs
- dbt
dbt Project Structure: Staging, Intermediate, and Marts Done Right
A proven dbt project structure you can copy today: clear folders, schema mapping in dbt_project.yml, and tight naming conventions. Includes SQL, YAML, and real-world tips.
- dbt
dbt Tests: dbt test, Data Test, and Unit Test Guide
A practitioner’s guide to dbt tests. Learn generic (schema), singular, and custom tests; how to run dbt tests; what happens when a test fails; and how to scale, package, and govern them.
- dbt
What is dbt (Data Build Tool)? A Simple Explanation for Data Teams
Explore dbt, the Data Build Tool that transforms raw data into structured insights using SQL. Understand its role in modern data workflows and ELT processes.
