What you will be able to do
- Explain what the target schema is and where each dbt environment type gets its own
- Set a distinct default schema for development, CI and production so environments never overwrite each other
- Predict the schema a model lands in when a custom schema is configured
- Make schema naming environment-aware with generate_schema_name_for_env and a prod target name
Key concept
Target schema — The schema (a dataset, on BigQuery) that an environment tells dbt to build into. A model with no schema config of its own lands here, and giving each environment a different target schema is what keeps development, CI and production apart in one warehouse.
1.The default schema belongs to the environment
The environment, not the project code, decides where a model ends up. A dbt environment sets three things: the dbt version, the version of your code, and the warehouse connection information, including the target database/schema settings. A model with no schema configuration is built in that schema, which is called the target schema. When the same project runs in development, then CI, then production, only the environment changes, so the environment's schema is what separates the three runs.
The word "schema" is used for every warehouse. On BigQuery the matching object is a dataset, and dbt treats the two terms as the same thing. A question about the "default dataset" of a BigQuery environment is asking about the target schema. Developers who come from dbt Core will know it as the schema: parameter of a target in profiles.yml. In the dbt platform, each environment plays roughly the role that one entry in profiles.yml plays in Core.
You don't have to create the target schema in the warehouse first. dbt checks whether it exists and creates it when it doesn't. That needs the warehouse user to have permission to create schemas. If the user can't get that privilege, point the environment at an existing schema that the user is allowed to create relations in.
Checkpoint 1 of 7· Check yourself
A team on BigQuery wants production models to build in a different place from development models. Which environment setting are they changing?
On BigQuery the target schema is a dataset, and each environment carries its own value. Custom schemas only add to the target schema. They don't replace it.
“Note: on BigQuery, dataset is used interchangeably with schema.”Source: docs.getdbt.com
2.Where each environment type sets its schema
Development and deployment environments set the schema in different places, because one serves people and the other serves jobs. A project has a single development environment, which drives the Studio IDE and the dbt platform CLI. The target schema there is personal. Each developer enters it in their own credentials (account name, then Your profile, then Credentials) the first time they use the environment. The usual pattern is dbt_<username>, so each developer gets a sandbox, owns everything in it, and doesn't build on top of a colleague's tables.
A deployment environment has a single schema shared by every job in it, set under Deployment Credentials > schema. One mistake is easy to miss. A new deployment environment can start with the same schema the development environment already uses. Its jobs then build into that schema, and "production" sits in the same place as someone's dev work. Change the field to a dedicated name, such as production or analytics, before the first scheduled run. Name the production schema so end users can tell it's ready for analysis.
The schema field is only part of where a deployment environment builds. The deployment connection is set at the environment level and controls the database, schema and warehouse. The connection profile is a project-level setting assigned to the environment, and it controls how dbt authenticates. Some connection details can be overridden in the environment settings. On Snowflake, for example, these are Role, Database and Warehouse. For Postgres, Redshift, BigQuery and Spark that section doesn't appear, because all values come from the project's connection, and extended attributes are used to override them.
| Context | Who sets the schema | Typical value |
|---|---|---|
| Development environment | Each developer, in their own credentials | dbt_username |
| Deployment environment | Environment settings, Deployment Credentials > schema | analytics or production |
| Automated CI job | Derived from the job ID and PR ID | dbt_cloud_pr_<job_id>_<pr_id> |
Checkpoint 2 of 7· Match them up
Match each setting to what it controls for a deployment environment
Tap a term, then the definition that fits it.
The deployment connection decides where objects are built and the connection profile decides how dbt logs in. A job needs both. Developer credentials only affect the development environment.
“Where dbt builds objects in your warehouse (database, schema, and warehouse)”Source: docs.getdbt.com
Checkpoint 3 of 7· Exam question
A dbt Cloud developer named Priya opens the IDE for a Snowflake-connected project. No model has a custom schema config, and Priya has never touched her personal credentials for the Development environment. When she runs `dbt run` in the IDE, which schema do her models build into by default?
Correct answer: A — A schema named after her personal dbt Cloud username, such as `dbt_priya`, derived from the Development environment's default target schema behavior.
- A. This is correct: with no personal credential override, the Development environment resolves each developer's target schema to a per-user default such as `dbt_<username>`, keeping developers' builds isolated from one another.
- B. This is incorrect because deployment and development environments each carry their own connection settings; a Production environment's credentials do not supply the schema a developer's IDE session uses.
- C. This is incorrect because `generate_schema_name` only combines a default schema with a custom schema when one is configured on a model; with no custom schema config anywhere, the macro simply returns the environment's default.
- D. This is incorrect because IDE sessions in the Development environment do not defer to or read state from deployment job runs when resolving the default schema.
3.Custom schemas extend the default, they don't replace it
A schema config on a model, or +schema on a folder in dbt_project.yml, is added onto the environment's default. It doesn't replace it. The result is <target_schema>_<custom_schema>. Because the target schema is still part of the name, one config gives a different schema in every environment: alice_dev_marketing for Alice, dbt_cloud_pr_123_456_marketing for a CI run, analytics_prod_marketing in production.
Many people expect schema: marketing to build in marketing. The default is designed to avoid that. If dbt used only the custom schema, every developer and every CI run would build into the same marketing schema and overwrite each other's relations. The generate_schema_name macro below implements the default rule. If your project defines its own macro with that name, dbt uses yours instead. dbt ignores a generate_schema_name macro that comes from an installed package.
{% macro generate_schema_name(custom_schema_name, node) -%}
{%- set default_schema = target.schema -%}
{%- if custom_schema_name is none -%}
{{ default_schema }}
{%- else -%}
{{ default_schema }}_{{ custom_schema_name | trim }}
{%- endif -%}
{%- endmacro %}Snapshots are an exception. A snapshot with target_schema set doesn't follow the environment's schema, so it builds in the same place no matter which environment runs it. To get environment-aware snapshots on v1.9+ or the dbt platform, remove target_schema and use the schema config if you still want a custom schema.
Checkpoint 4 of 7· Check yourself
A developer's target schema is public, and a folder in dbt_project.yml sets +schema: silver. The project has no generate_schema_name macro. Where do those models build?
Without a custom macro, dbt combines the two as {target.schema}_{custom_schema_name}, so the target schema always comes first.
“For example, when target.schema is public and a model sets +schema: silver, dbt builds the model in public_silver, not silver.”Source: docs.getdbt.com
Checkpoint 5 of 7· Exam question
Several developers on a team want their IDE queries to build into one shared schema, `dbt_shared_dev`, instead of each getting a personal per-username schema. None of them has ever set a personal credential override. Where should an admin make this change so the shared behavior applies to everyone immediately?
Correct answer: B — Edit the default schema field on the Development environment's connection settings, which supplies the schema for any developer who has not set a personal override.
- A. This is incorrect for this scenario: editing every individual's personal credentials would work eventually, but it requires a separate change per developer and does not immediately apply to everyone from one place.
- B. This is correct: because none of the developers has a personal override, changing the Development environment's own default schema field takes effect for all of them at once.
- C. This is incorrect because a custom schema config changes what gets appended to the default schema via `generate_schema_name`, it does not replace or unify the underlying per-developer default itself.
- D. This is incorrect because the IDE is driven by the single Development environment for a project, and deployment environments govern scheduled jobs rather than IDE sessions.
4.Clean schema names in production only
A common goal is clean names like marketing or gold in production, while dev and CI stay isolated. The wrong way to get there is to delete {{ default_schema }} from the macro so it always returns the custom schema alone. That gives clean production names, but developers who set custom schemas then overwrite each other's models, and CI breaks too. The fix is to make the macro check which environment is running.
dbt includes a macro for this, generate_schema_name_for_env, but it's off by default. To turn it on, add a generate_schema_name macro to your project that calls it. In production, a model with a custom schema builds in that schema alone (marketing). Everywhere else, the custom schema is ignored and the model builds in the target schema (alice_dev, dbt_cloud_pr_123_456).
-- put this in macros/generate_schema_name.sql
{% macro generate_schema_name(custom_schema_name, node) -%}
{{ generate_schema_name_for_env(custom_schema_name, node) }}
{%- endmacro %}The macro decides it's in production by checking the target name, not the schema. The production job must therefore set its target name to prod. Otherwise every production model falls back to the target schema and the custom schemas never show up. You can also write your own macro that branches on an environment variable, for example env_var('DBT_ENV_TYPE','DEV') == 'PROD'. Another option builds the schema name from the current branch with the built-in DBT_CLOUD_GIT_BRANCH variable. That variable only exists in the Studio IDE, not in the dbt platform CLI, and developers on the same branch share a schema.
| Environment | Target schema | Resulting schema |
|---|---|---|
| Production (target.name == 'prod') | analytics_prod | marketing |
| Development | alice_dev | alice_dev |
| CI | dbt_cloud_pr_123_456 | dbt_cloud_pr_123_456 |
Checkpoint 6 of 7· Fill the gap
Which value does the built-in macro compare against 'prod' to decide it's in production?
{% macro generate_schema_name_for_env(custom_schema_name, node) -%}
{%- set default_schema = target.schema -%}
{%- if ? == 'prod' and custom_schema_name is not none -%}
{{ custom_schema_name | trim }}
{%- else -%}
{{ default_schema }}
{%- endif -%}
{%- endmacro %}The macro checks target.name, which is why a production job has to set its target name to prod. target.schema is the fallback value that gets returned, not the test.
Source: docs.getdbt.comCheckpoint 7 of 7· Exam question
An architect is setting up the Production deployment environment for a new dbt Cloud project on Redshift. They want every job that runs in this environment to write to the `analytics_prod` schema unless a model overrides it. Where should this default be configured?
Correct answer: A — In the Production environment's connection settings, inside the field that sets its default schema, which every job there inherits unless a model overrides it.
- A. This is correct: the deployment environment's own connection settings hold the default schema, and every job that runs against that environment inherits it unless a model-level custom schema config changes the outcome.
- B. This is incorrect because individual jobs do not each carry their own default schema declaration; jobs inherit connection and schema settings from the environment they run in.
- C. This is incorrect because dbt Cloud environments manage warehouse connection settings through the platform itself, not through a `profiles.yml` file checked into the repository.
- D. This is incorrect because default schema settings live on individual environments, not on a single project-wide page shared by every environment.
Exam traps
Each one states something that sounds right. Open it to see what is actually true.
1.A model configured with schema: marketing is built in a schema called marketing.Why is that wrong?
By default dbt adds the custom schema to the end of the environment's target schema, so the model builds in something like analytics_prod_marketing.
Covered in Custom schemas extend the default, they don't replace it
2.To get clean production schema names, edit generate_schema_name so it always returns the custom schema alone.Why is that wrong?
Without the target schema, developers and CI runs that set custom schemas write into the same schema and overwrite each other. Branch on the environment instead.
Covered in Clean schema names in production only
3.Enabling generate_schema_name_for_env is enough on its own to make production use the custom schema names.Why is that wrong?
The macro checks target.name, so the production job also has to set its target name to prod.
Covered in Clean schema names in production only
4.A generate_schema_name macro shipped in an installed package changes how your project names schemas.Why is that wrong?
Only a generate_schema_name macro defined in your own project replaces the default. dbt ignores package copies.
Covered in Custom schemas extend the default, they don't replace it
Sources
Every claim above is drawn from one of these pages, quoted as it was written on the date shown.
- 1.https://docs.getdbt.com/docs/build/custom-schemasOfficial docs
“By default, all dbt models are built in the schema specified in your environment (dbt platform) or profile's target (dbt v1).”
↩︎ The default schema belongs to the environment“If dbt ignored the target schema and only used the model's custom schema, every dbt user would create models in the same schema”
↩︎ Custom schemas extend the default, they don't replace it“Be careful. dbt will ignore any custom generate_schema_name macros included in installed packages.”
↩︎ Custom schemas extend the default, they don't replace it“dbt ships with a macro for this use case — called generate_schema_name_for_env — which is disabled by default.”
↩︎ Clean schema names in production only“When using this macro, you'll need to set the target name in your production job to prod.”
↩︎ Clean schema names in production only“However, dbt puts it in a schema like <target_schema>_marketing.”
↩︎ Exam trap 1“If you remove {{ default_schema }}, it causes developers to override each other's models if they create their own custom schemas.”
↩︎ Exam trap 2“When using this macro, you'll need to set the target name in your production job to prod.”
↩︎ Exam trap 3“Be careful. dbt will ignore any custom generate_schema_name macros included in installed packages.”
↩︎ Exam trap 4“dbt generates the schema name for a model by appending the custom schema to the target schema.”
↩︎ Prediction - 2.
“The warehouse connection information (including the target database/schema settings)”
↩︎ The default schema belongs to the environment“This allows you to set separate target information and maintain individual credentials to connect to your warehouse.”
↩︎ Where each environment type sets its schema - 3.https://docs.getdbt.com/faqs/Project/which-schemaOfficial docs
“Note: on BigQuery, dataset is used interchangeably with schema.”
↩︎ The default schema belongs to the environment“If you're developing in dbt, these are set for each user when you first use a development environment.”
↩︎ Where each environment type sets its schema - 4.https://docs.getdbt.com/docs/local/profiles.ymlOfficial docs
“If your user is unable to be granted the privilege to create schemas, your dbt runs should instead target an existing schema”
↩︎ The default schema belongs to the environment“should be named in a way that makes it clear that it is ready for end-users to use for analysis”
↩︎ Where each environment type sets its schema“The target schema represents the default schema that dbt will build objects into”
↩︎ Key concept - 5.https://docs.getdbt.com/guides/dbt-python-snowparkOfficial docs
“Navigate to Deployment Credentials > schema.”
↩︎ Where each environment type sets its schema“However, it is using the same default schema that we've been using as the schema for our development environment.”
↩︎ Where each environment type sets its schema - 6.
“Some details of that connection (databases/schemas/and so on.) can be overridden within this section of the dbt environment settings.”
↩︎ Where each environment type sets its schema“This section will not appear if you are using Bigquery, as all values are inferred from the project's connection.”
↩︎ Where each environment type sets its schema“Where dbt builds objects in your warehouse (database, schema, and warehouse)”
↩︎ Checkpoint - 7.
“In dbt, this is typically dbt_username for development and the default schema for deployment environments.”
↩︎ Where each environment type sets its schema“Note that for automated CI jobs, the schema name derives from the job number and PR number: dbt_cloud_pr_<job_id>_<pr_id>.”
↩︎ Where each environment type sets its schema“To allow the database/schema/object name to depend on the current branch, you can use the out-of-the-box DBT_CLOUD_GIT_BRANCH environment variable”
↩︎ Clean schema names in production only“The DBT_CLOUD_GIT_BRANCH variable is only available within the Studio IDE and not the dbt platform CLI.”
↩︎ Clean schema names in production only - 8.https://docs.getdbt.com/guides/debug-schema-namesOfficial docs
“Snapshots do not follow this behavior if target_schema is set.”
↩︎ Custom schemas extend the default, they don't replace it“For example, when target.schema is public and a model sets +schema: silver, dbt builds the model in public_silver, not silver.”
↩︎ Checkpoint