CertSafari
    DBT Architect· Lessons

    Domain 3 · Lesson 13/39

    Default schema and dataset for dbt environments

    Setting a default schema/dataset for environments

    12 min read
    2.56% of exam
    8 sources
    Published 13 Oct 2026
    Docs as of 12 Oct 2026

    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?

    Sources1234

    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.

    Where the default schema comes from in each context
    ContextWho sets the schemaTypical value
    Development environmentEach developer, in their own credentialsdbt_username
    Deployment environmentEnvironment settings, Deployment Credentials > schemaanalytics or production
    Automated CI jobDerived from the job ID and PR IDdbt_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.

    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?

    Sources325467

    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.

    dbt's default generate_schema_name logic: target schema alone, or target schema plus custom schemasql
    {% 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?

    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?

    Sources18

    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).

    Turning on dbt's built-in environment-aware schema macrosql
    -- 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.

    Results with generate_schema_name_for_env enabled, for a model whose custom schema is marketing
    EnvironmentTarget schemaResulting schema
    Production (target.name == 'prod')analytics_prodmarketing
    Developmentalice_devalice_dev
    CIdbt_cloud_pr_123_456dbt_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 %}

    Checkpoint 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?

    Sources17

    Exam traps

    Each one states something that sounds right. Open it to see what is actually true.

    1. 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. 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. 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. 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. 1.
      “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. 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. 3.
      “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. 4.
      “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. 5.
      “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. 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. 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. 8.
      “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

    Ready to test yourself?

    Practise the 9 questions on this subdomain.

    Spotted a mistake, or was something unclear? Tell us.