Migrate from dbt Core to dbt Projects on Snowflake¶
This is a step-by-step guide for teams moving from standard dbt Core to dbt Projects on Snowflake. The goal is to take the dbt Core project you run today (in your local IDE, kicked off by an orchestrator such as Airflow) and get it running natively inside Snowflake, with as little change as possible. Most of your project files stay exactly the same.
This guide is written for admins who are comfortable copying and pasting SQL. Every step shows the SQL you can run, and where it helps, the equivalent clicks in Snowsight.
What changes (and what doesn’t)¶
Good news first: your models/, seeds/, macros/, tests/, dbt_project.yml, and
packages.yml files don’t need to change. dbt is still dbt.
Here’s the short list of what’s different when dbt runs inside Snowflake:
| Topic | dbt Core today | dbt Projects on Snowflake |
|---|---|---|
| Where you edit and run | Local IDE + terminal | Snowflake Workspaces (a web IDE in Snowsight) or Cortex Code Desktop |
| What kicks off runs | Third-party orchestrator such as Airflow | Snowflake tasks (scheduled SQL) |
| Connection / auth | profiles.yml with account, user, password | profiles.yml in the project root, no account, user, or password needed |
| dbt engine | Whatever you installed | Pick a Snowflake-managed runtime, for example 1.10.15 (dbt Core) or 2.0.0-preview (dbt Fusion). No installs. |
Getting packages (dbt deps) | Runs locally | Runs in Snowflake using an external access integration |
| Deploying | n/a | A dbt project object (a versioned snapshot of your code in Snowflake) |
The six steps this guide walks through:
- Set up Workspaces (and pick the dbt runtime)
- (Optional) Set up PrivateLink to your Git server
- Connect a Git repository with OAuth2
- Move your
profiles.ymlinto the project root - Create an external access integration so dbt can read its packages
- Deploy the project and schedule it with a task
Related docs:
- dbt Projects on Snowflake overview
- Tutorial: Get started with dbt Projects on Snowflake
- Access control for dbt Projects
Step 1: Set up Workspaces¶
Workspaces are a web-based IDE inside Snowsight. They’re the easiest way to get a dbt Core
project running on Snowflake: you can edit files, run dbt compile / dbt run / dbt build,
see the DAG, and deploy, all from the browser. No local install required.
Related docs:
Pick the dbt runtime version¶
Snowflake runs your project on a managed dbt runtime. The version you choose decides the engine:
a 1.x version runs dbt Core (Python), a 2.x version runs dbt Fusion (Rust). Pin to whichever
version your team already has experience with.
You can set the default for the whole account so nobody has to specify it every time. This also sets the initial runtime version that Workspaces use:
To see what versions are available at any time:
You can always override the version on an individual project later (shown in step 6).
If you ever need to move other dbt Core projects to Fusion, see Migrate to dbt Fusion.
Related docs: Supported dbt Core versions
Things to know before you start¶
A few things that trip people up with Workspaces:
- Workspaces are personal by default. Each user’s workspace lives in their own personal database and isn’t shared. If you want several people to collaborate in the same workspace, create a shared workspace in a regular database and schema instead. See Workspaces overview.
- 20,000 file limit per dbt project object. This counts everything in the project directory,
including the
target/,dbt_packages/, andlogs/folders that dbt generates. Large projects with big package trees can bump into this. Contact your account representative if your team has a project larger than this threshold. profiles.ymlis required in each project folder (covered in step 4).- Public repos are read-only. If you connect a public Git repo, you can pull but you can’t commit and push back from the workspace. For your real project, connect it as a private repo with OAuth2 (step 3).
- Fusion runs
dbt depsautomatically. When you’re on Fusion and yourpackages.ymllists packages but there’s nodbt_packagesfolder yet, Fusion quietly runsdbt depsduringdbt compile/dbt run, which needs internet access. Workspaces make this painless: create the external access integration once (step 5), select it the first time, and it stays pre-selected for every command that might need it, so you don’t have to think about it again.
Step 2: (Optional) Set up PrivateLink to your Git server¶
Note
Skip this entire step and go to step 3 unless your Git server is reachable only over PrivateLink (no public internet access). Most teams connect to their Git provider over the public internet and don’t need this step.
PrivateLink is a dedicated private network connection between Snowflake and your Git server, so Git traffic never crosses the public internet. Setting it up is a one-time admin task that must be done before you connect your repository in step 3, and it only works when Snowflake and your Git server are in the same cloud and region. Note that OAuth2 doesn’t work over PrivateLink, so on this path you authenticate with a token instead.
-
On your cloud provider, create a private link service that accepts requests from Snowflake (see the walkthrough linked below).
-
In Snowflake, provision the outbound private endpoint with your private link service ID and your Git server’s domain (AWS example shown; Azure and Google Cloud use their own service ID format):
-
Accept the endpoint on your cloud provider, then check its status:
-
Create the API integration with
USE_PRIVATELINK_ENDPOINT = TRUEand token-based authentication (a secret holding a personal access token). AddTLS_TRUSTED_CERTIFICATESif your server uses a self-signed certificate:For most providers,
USERNAMEis your actual Git username. For Bitbucket, setUSERNAMEliterally to the stringx-token-auth(a Bitbucket convention) and put your token inPASSWORD:After you finish this step, skip the OAuth options in step 3 and go straight to Create the Git-connected workspace. When you create the workspace, select Personal access token as the authentication method and point it at this secret.
Related docs:
Step 3: Connect your Git repository with OAuth2¶
Workspaces sync to a branch in your Git repo, so you keep your normal Git workflow (branches, commits, pull requests). The cleanest sign-in experience for interactive development is OAuth2: your team signs in to the Git provider once and Snowflake handles the rest, no tokens to paste or rotate.
Note
If you don’t intend to use Workspaces in your initial onboarding to dbt Projects on Snowflake, you can skip this section. Your team can still use the Snowflake CLI (shown in step 6) to deploy dbt project objects and schedule them.
The setup is two parts: an admin creates an API integration that tells Snowflake how to talk to your Git provider, and each user signs in with OAuth when they create a Git-connected workspace.
Tip
If you completed step 2 (PrivateLink), you already created your token-based API integration. Skip the OAuth options below and go straight to Create the Git-connected workspace.
Redirect URI (required for all providers except GitHub)¶
Most OAuth2 providers ask for a redirect URI (also called a callback URL) when you register an OAuth application. This is a fixed Snowflake URL based on your account’s region — it is not generated by the API integration. The pattern is:
For example, an account in AWS US West (Oregon) uses:
You set this URL as the callback when you create the OAuth app, and the provider then gives you the client ID and client secret that you plug into the API integration. The GitHub option below skips this — the Snowflake GitHub App handles the redirect URI for you.
To let Snowflake build the whole URL for you, run this and copy the result:
Create the API integration for your Git provider¶
Pick your Git provider to see the setup steps:
GitHub is the simplest case. Snowflake publishes a pre-built OAuth app (the Snowflake GitHub App), so you don’t register your own OAuth application or redirect URI. The admin just creates an API integration that points at it:
On first sign-in, GitHub asks an org admin to authorize the snowflakedb app; after that,
everyone in the account can use it.
The Snowflake GitHub App is at github.com/apps/snowflakedb.
For GitLab, you register an OAuth application on the GitLab side, then create an API integration in Snowflake with the OAuth2 details. (OAuth for providers other than GitHub is currently in preview, but fully usable.)
Register an OAuth application in GitLab, setting its callback URL to the Snowflake redirect URI
described above. Request these scopes: read_api, read_repository, and write_repository.
GitLab gives you a client ID and client secret to use next.
Then create the API integration (run as an admin role). The endpoints below are for GitLab.com; for a self-managed GitLab, swap in your own host:
Azure DevOps uses the same generic OAuth2 flow as GitLab. Register an OAuth application in Azure DevOps, setting its callback URL to the Snowflake redirect URI described above, then create the API integration with Azure DevOps’s endpoints and scopes. Because those values are provider-specific (and Microsoft is shifting toward Microsoft Entra ID), get the exact current values from the Snowflake quickstart for Azure DevOps OAuth.
Register an OAuth consumer in Bitbucket under Workspace settings > OAuth consumers with
the Write repository permission, and set its callback URL to the Snowflake redirect URI
described above. The consumer’s Key and Secret are your OAUTH_CLIENT_ID and
OAUTH_CLIENT_SECRET.
For a full step-by-step with screenshots, see the Connect Snowflake to Bitbucket with OAuth2 quickstart.
Note
Bitbucket behind outbound PrivateLink? OAuth2 is not supported over an outbound private link to a Git provider. Skip this option and use the token-based PrivateLink step (step 2) instead. This option is for Bitbucket Cloud reached over the public internet.
For any other provider that supports OAuth2 (a self-managed Git server, and so on), use the generic template. Register an OAuth application with your provider, setting its callback URL to the Snowflake redirect URI described above, then fill in your provider’s endpoints, client credentials, and scopes:
For provider-specific values, see the Set up OAuth for Git integration by provider article.
Create the Git-connected workspace¶
Once the API integration exists, anyone with USAGE on it can create a workspace from the repo:
- Sign in to Snowsight.
- In the navigation menu, select Projects > Workspaces.
- In the Workspaces menu, select From Git repository.
- Paste the repository URL (for example,
https://github.com/my-org/analyticsorhttps://gitlab.com/my-group/analytics). - Give the workspace a name.
- Under API Integration, select
git_api_integration. - For the authentication method, select OAuth2, then Sign in and authorize Snowflake to access the repository. Grant read access to metadata and read/write access to code so you can pull and push.
- Select Create.
Snowflake clones the repo and opens the workspace with your dbt project files ready to edit.
Related docs:
Step 4: Move your profiles.yml into the project root¶
In dbt Core, your profiles.yml usually lives outside the project (in ~/.dbt/) and holds your
account, user, and password. On Snowflake, you bring that file into the root of the dbt project
folder, and you get to drop the sensitive bits.
Why it’s simpler: the project already runs inside Snowflake, under the signed-in user and account.
So dbt doesn’t need an account, a user, or a password. The account and user keys can be
left as empty or placeholder strings (dbt still expects the keys to exist), and there’s no password
field at all.
Here’s a profiles.yml you can drop in. It defines a dev and a prod target:
There’s no password, no authenticator, no key-pair path. That’s the point: nothing secret
lives in the file.
Once profiles.yml is in the project root with at least one valid target, each target shows up in
the Profile picker in the workspace toolbar. Pick a profile, pick a command (compile, run,
build), and run it.
Related docs: Workspaces for dbt Projects on Snowflake
Step 5: Create an external access integration for dbt packages¶
If your project uses packages in packages.yml (for example, dbt-labs/dbt_utils), dbt needs
to reach out to the internet to download them when it runs dbt deps. Snowflake blocks outbound
network access by default, so you give dbt a narrow, allowlisted path with an external access
integration.
This matters extra for Fusion: as noted in the gotchas, Fusion auto-runs dbt deps during
compile/run when packages are declared but not yet downloaded. Without external access, that
step fails with a network error. Setting this up once avoids that.
Run the following as an admin role:
To populate packages in the workspace, select Deps from the command list, choose your external
access integration, and run it. This creates the dbt_packages folder and a package-lock.yml.
If your team pulls packages from other hosts (a private Git package server, for example), add those
hostnames to the VALUE_LIST.
Related docs:
Step 6: Deploy the project and schedule it with a task¶
Once the project runs cleanly in the workspace, you “ship” it by creating a dbt project object. Think of this as a versioned, read-only snapshot of your code that lives in a Snowflake database and schema. You then schedule it with a task (this replaces the Airflow job).
Deploy as a dbt project object¶
Using SQL. CREATE DBT PROJECT copies your code in and creates version 1. Point FROM at the
workspace version of the project. Attach the external access integration from step 5 so Fusion can
run dbt deps during compile, and pin the Fusion runtime:
Note
The FROM URL points at your workspace’s live version. The example uses a personal workspace
(the default), whose path is USER$.PUBLIC."<workspace_name>". If you use a shared workspace,
replace USER$.PUBLIC with the database and schema that contain the object (for example,
prod_db.analytics."<workspace_name>"). The trailing segment (my_dbt_project) is the dbt
project folder inside the workspace. The easiest way to get this exactly right is to deploy from
the UI once and copy the CREATE DBT PROJECT SQL it prints.
Confirm it exists:
To push later code changes, add a new version instead of replacing the object:
Using the UI. In the workspace, select Connect > Deploy dbt project, choose the target
database and schema, choose Create dbt project, give it a name, optionally set a default target
and the external access integration, then select Deploy. The Output tab shows the exact
CREATE DBT PROJECT SQL it ran, so the UI and SQL paths produce the same thing.
Graduate to CI/CD. Deploying by hand is the right way to get going. Longer term, we recommend
managing updates to the dbt project object through a CI/CD pipeline using the Snowflake CLI’s
snow dbt commands, driven by a GitHub Action or GitLab pipeline. The shape is short and clean:
on a pull request, deploy a copy to dev and test it; on merge, deploy the new version to production.
For the full setup (auth, secrets, workflow files), see CI/CD integrations on dbt Projects on Snowflake and the CI/CD tutorial.
Related docs:
Schedule it with a task¶
A task runs the EXECUTE DBT PROJECT command on a schedule. This is the piece that replaces
Airflow. Two rules to remember:
- The task must be in the same database and schema as the dbt project object.
- Tasks that run dbt must use a user-managed warehouse (serverless tasks aren’t supported).
A daily run against the prod target:
You can chain a test run right after the run finishes:
Tasks are created in a suspended state. Resume them to start the schedule (resume the child first, then the root):
You can also run a single execution by hand at any time:
Using the UI. From the dbt project menu, select Create schedule, set the frequency,
operation (run), profile, and any flags (for example, --select customer_metrics). Snowflake
creates the same CREATE TASK for you.
Related docs: