profiles.yml is the core file that defines dbt's runtime connections. Designing it so you can switch environments safely and reproducibly is critical for both developer productivity and incident prevention.
This article walks through the points the Analytics Engineer exam loves to test — profile lookup order, target resolution priority, adapter-specific keys, and env_var usage — with practical examples you can drop into real work.
dbt reads the entry in profiles.yml whose key matches the profile name in dbt_project.yml, then connects using the outputs of the selected target. The standard path for profiles.yml is under your user directory, but DBT_PROFILES_DIR can point dbt to a different location — useful when you want CI to read profiles.yml from the repo root.
The structure has target (the default execution environment name) and outputs (per-environment connection definitions) under the profile name. outputs holds adapter-specific keys such as Snowflake's account and warehouse, or Databricks' host and http_path. Jinja and env_var are stable features of profiles.yml, so avoid writing secrets directly.
Minimal profiles.yml skeleton (Snowflake example)
ja_lab:
target: dev
outputs:
dev:
type: snowflake
account: {{ env_var('SF_ACCOUNT') }}
user: {{ env_var('SF_USER') }}
password: {{ env_var('SF_PASSWORD') }}
role: ANALYST
database: ANALYTICS
warehouse: WH_XS
schema: dev
threads: 4
stg:
type: snowflake
account: {{ env_var('SF_ACCOUNT') }}
user: {{ env_var('SF_USER') }}
password: {{ env_var('SF_PASSWORD') }}
role: ANALYST
database: ANALYTICS
warehouse: WH_S
schema: stg
threads: 6
prod:
type: snowflake
account: {{ env_var('SF_ACCOUNT') }}
user: {{ env_var('SF_USER') }}
password: {{ env_var('SF_PASSWORD') }}
role: PROD_ROLE
database: ANALYTICS
warehouse: WH_M
schema: prod
threads: 8Target resolution has a priority order: the CLI's --target wins, then the DBT_TARGET environment variable, and finally the target in profiles.yml. The easiest workflow is to set --target explicitly in CI and temporarily set DBT_TARGET for local development.
Use short, collision-free environment names like dev/stg/prod. Combined with --profiles-dir, you can safely point at a project-specific profiles.yml even inside a monorepo.
Target resolution flow
Sample switching commands
# Run against stg temporarily
export DBT_TARGET=stg
dbt run
# Specify explicitly in CI
dbt build --target prod --profiles-dir .
# Verify (connection check)
dbt debug --target devDesign profiles.yml assuming it will live under version control, and reference every secret through env_var. dbt evaluates Jinja and substitutes env_var('KEY') values at runtime, so passwords and tokens stay out of the code while environment differences remain expressive.
In CI/CD, inject environment variables via each runner's secret feature. Databricks uses personal access tokens; Snowflake supports key-pair auth and OAuth in addition to passwords. Pick the method that fits your operational requirements and assign least-privilege roles per environment.
Excerpts of a safe profile written with env_var, plus environment variable setup
# profiles.yml (excerpt)
ja_lab:
target: dev
outputs:
dev:
type: snowflake
account: {{ env_var('SF_ACCOUNT') }}
user: {{ env_var('SF_USER') }}
password: {{ env_var('SF_PASSWORD') }}
role: {{ env_var('SF_ROLE', 'ANALYST') }}
database: ANALYTICS
warehouse: {{ env_var('SF_WAREHOUSE', 'WH_XS') }}
schema: dev
# Databricks example (token auth)
dev_dw:
type: databricks
catalog: hive_metastore
schema: dev
host: {{ env_var('DB_HOST') }}
http_path: {{ env_var('DB_HTTP_PATH') }}
token: {{ env_var('DB_TOKEN') }}
threads: 4
# Local environment variable setup (example)
export SF_ACCOUNT="xy12345.ap-southeast-1"
export SF_USER="analyst"
export SF_PASSWORD="..."
export DB_HOST="adb-123456789.11.azuredatabricks.net"
export DB_HTTP_PATH="/sql/1.0/warehouses/xxxx"
export DB_TOKEN="dapi..."Required keys and recommended auth methods differ by adapter. Deciding up front where to put environment differences — warehouse/role for Snowflake, http_path or catalog/schema for Databricks, host or database for Postgres — keeps profiles.yml lean.
On the exam, you are most often tested on each adapter's type name, its typical required keys, and how to switch environments.
| Adapter | Main required keys | Auth highlights | Typical environment diffs |
|---|---|---|---|
| Snowflake | account, user/password or key/oauth, role, database, warehouse, schema | Password, key-pair, or OAuth are all valid. Always declare role and warehouse explicitly | warehouse size/name, role, and schema (dev/stg/prod) |
| Databricks (SQL Warehouse) | host, http_path, token, catalog (optional), schema | Use a personal access token (PAT). http_path differs between Warehouse and Cluster | http_path (target switch), catalog/schema, threads |
| Postgres | host, port, dbname, user, password, schema | Simple user/password auth. Vary connection pooling and SSL settings per environment | host/port/dbname, schema, sslmode |
Minimal Databricks SQL Warehouse configuration
ja_lab:
target: dev_dw
outputs:
dev_dw:
type: databricks
schema: dev
host: {{ env_var('DB_HOST') }}
http_path: {{ env_var('DB_HTTP_PATH') }}
token: {{ env_var('DB_TOKEN') }}
threads: 4Combining YAML anchors with Jinja keeps environment differences to a minimum. Bundle the base definition under &base and let dev/stg/prod override only what changes. Driving schema, role, and warehouse from target.name or environment variables makes the file easier to manage.
Controlling execution parameters like threads and retry behavior through environment variables makes it easier to share the same profiles.yml between CI and local development.
Minimize environment diffs with anchors and Jinja
ja_lab:
target: dev
outputs:
base: &base
type: snowflake
account: {{ env_var('SF_ACCOUNT') }}
user: {{ env_var('SF_USER') }}
password: {{ env_var('SF_PASSWORD') }}
database: ANALYTICS
role: {{ env_var('SF_ROLE', 'ANALYST') }}
warehouse: {{ env_var('SF_WH', 'WH_S') }}
schema: analytics_{{ target.name }}
threads: {{ env_var('DBT_THREADS', 4) | int }}
dev:
<<: *base
stg:
<<: *base
warehouse: {{ env_var('SF_WH_STG', 'WH_M') }}
prod:
<<: *base
role: PROD_ROLE
warehouse: {{ env_var('SF_WH_PROD', 'WH_L') }}
threads: {{ env_var('DBT_THREADS_PROD', 8) | int }}Errors around profiles.yml are usually easy to root-cause but easy to introduce. Start with dbt debug and isolate the issue in this order: profile discovery, credentials, then permissions. On the exam, profile lookup, target resolution, and permission design are common topics.
Typical symptoms and remedies:
Checklist commands
# Profile discovery and connection check
dbt debug --profiles-dir . --target dev
# Specify the execution target explicitly
dbt run --target stg
# Run everything including tests
dbt build --target prodAnalytics Engineer
問題 1
On a local machine DBT_TARGET=prod is set, CI runs dbt build --profiles-dir . --target stg, and profiles.yml has target: dev. Which target is used in the end?
正解: A
Target resolution evaluates --target > DBT_TARGET > profiles.yml, so --target stg ends up being used.
Where should profiles.yml live, and when should I use DBT_PROFILES_DIR?
The default location is ~/.dbt/profiles.yml under your user directory (on Windows, %USERPROFILE%\.dbt\profiles.yml). If you want to store it at the repository root to share with CI, or switch between multiple profiles, point DBT_PROFILES_DIR at the directory you want (for example, the project root).
What is the best practice for switching warehouse and role per environment on Snowflake?
Split outputs in profiles.yml into dev/stg/prod and declare role and warehouse explicitly for each environment. Combining env_var with YAML anchors lets you manage only the diffs, which keeps operations clean. For example, use the ANALYST role for dev/stg and PROD_ROLE for prod.
How should I manage secrets in dbt Core CI/CD?
Reference env_var inside profiles.yml and inject the values from your CI's secret store (GitHub Actions secrets, GitLab CI masked variables, etc.). If you use a .env file, always exclude it from the repository and keep it limited to local development.
Practice with certification-focused question sets
無料で問題を解いてみるNicheeLab Editorial Team
NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.
dbt Models: SQL-Defined Transformation Units (2026)
Model fundamentals — SELECT-based definitions, naming, refs,...
dbt Analytics Engineering Exam: Complete Guide (2026)
Pass the AE Certification — scope, weighting, sample questio...
dbt Cloud vs dbt Core: Feature & Cost Comparison (2026)
Honest comparison of dbt Cloud vs. dbt Core — IDE, scheduler...
dbt Project Structure: models/seeds/macros Layout (2026)
Recommended dbt project layout — models, seeds, macros, snap...
dbt_project.yml Explained: Every Config (2026)
Every dbt_project.yml setting that matters — paths, vars, ma...