<@ULVA73B9P> Can you tell me how i can setup dbt c...
# ask-marvin
h
@Marvin Can you tell me how i can setup dbt core with prefect cloud (hobby plan), what are the recommended practices to setup a dbt core project with prefect cloud, i have setup a dbt core project locally now, so what will be the next steps
m
Error: unhandled errors in a TaskGroup (1 sub-exception)
Sorry, I encountered an error while processing your request. Please try again.
h
@Marvin Can you tell me how i can setup dbt core with prefect cloud (hobby plan), what are the recommended practices to setup a dbt core project with prefect cloud, i have setup a dbt core project locally now, so what will be the next steps
m
thought for 457.5 seconds
Great question — and nice work getting your dbt Core project running locally. Here’s a concise path to run it reliably with Prefect Cloud (Hobby), plus recommended practices. I’ll assume Prefect 3.x. High-level plan 1) Install and connect to Prefect Cloud 2) Wrap your dbt project in a Prefect flow using Prefect’s dbt integration 3) Decide how you’ll provide credentials/profiles (profiles.yml, Prefect blocks, or programmatic) 4) Choose a work pool type (quickstart: Process; production: Docker/K8s) 5) Create a deployment and start a worker 6) Run/schedule from Prefect Cloud Docs you’ll want handy: - dbt integration: Prefect + dbt - Deployments: Deployments (3.x) - Work pools & workers: Work pools and workers Step 1 — Install + login to Prefect Cloud - Install Prefect with the dbt extra and your dbt adapter(s):
Copy code
pip install "prefect[dbt]" dbt-duckdb   # or dbt-snowflake / dbt-bigquery / dbt-postgres, etc.
prefect block register -m prefect_dbt
- Log in to Cloud (Hobby) and select your workspace:
Copy code
prefect cloud login --key <PREFECT_API_KEY> --workspace <account>/<workspace>
Step 2 — Add a flow that runs dbt (recommended: PrefectDbtRunner) Create a small flow in your repo (e.g., flows/dbt_build.py). PrefectDbtRunner gives you node-level visibility and assets automatically.
Copy code
from prefect import flow
from prefect_dbt import PrefectDbtRunner, PrefectDbtSettings

@flow(name="dbt-build")
def dbt_build():
    settings = PrefectDbtSettings(
        project_dir="./dbt_project",      # path to your dbt project (contains dbt_project.yml)
        profiles_dir="~/.dbt"             # or point to a repo-local .dbt dir
    )
    runner = PrefectDbtRunner(settings=settings, raise_on_failure=True)
    runner.invoke(["build"])              # you can pass ["run"], ["test"], etc.

if __name__ == "__main__":
    dbt_build()
Notes: - You can also rely on env vars:
DBT_PROJECT_DIR
,
DBT_PROFILES_DIR
,
DBT_LOG_LEVEL
— the runner picks them up. - Selection/vars example:
runner.invoke(["run", "--select", "tag:daily", "--vars", "{'run_date':'2026-03-01'}"])
Step 3 — Provide dbt credentials cleanly Pick one (or mix) of these patterns: - Existing profiles.yml: set
profiles_dir
or
DBT_PROFILES_DIR
and keep secrets via env vars (e.g.,
{{ env_var('SNOWFLAKE_PASSWORD') }}
) loaded from Prefect Secret blocks. - Prefect block templating inside profiles.yml (lets you reference Prefect blocks/variables): - Example in docs: Prefect + dbt (profiles.yml templating with
{{ prefect.blocks.* }}
and
{{ prefect.variables.* }}
). - Programmatic profiles with DbtCliProfile (handy for Snowflake/BigQuery). See examples in the dbt docs page above. Step 4 — Choose a work pool - Quickstart (local dev): Process pool + worker on your machine that has your repo and dbt deps. - Production: Docker or Kubernetes pool so runs are isolated and reproducible (image includes Prefect, dbt, and your adapter). Create a work pool:
Copy code
# Process (quickstart)
prefect work-pool create my-process-pool --type process

# Or Docker (recommended for prod)
prefect work-pool create my-docker-pool --type docker
Step 5a — Quickstart deploy (process worker, no Docker) This is the fastest way to see runs in Cloud. Option A: Use prefect deploy + prefect.yaml - Add a minimal prefect.yaml at repo root:
Copy code
name: dbt-workflows
prefect-version: ">=3.0.0"

deployments:
  - name: dbt-build-dev
    entrypoint: flows/dbt_build.py:dbt_build
    work_pool:
      name: my-process-pool
- Deploy:
Copy code
prefect deploy
- Start a worker on your dev machine:
Copy code
prefect worker start -p my-process-pool
Option B: Deploy from source in code (useful with GitHub) ``` from prefect import flow from prefect_dbt import PrefectDbtRunner, PrefectDbtSettings @flow
def dbt_build(): PrefectDbtRunner( settings=PrefectDbtSettings(project_dir="./dbt_project", profiles_dir="~/.dbt") ).invoke(["build"]) if name == "__main__": flow.from_source( source="https://github.com/your-org/your-repo.git", entrypoint="flows/dbt_build.py:dbt_build", ).deploy( name="dbt-build-dev", work_pool_name="my-process-pool", )
Copy code
Step 5b — Production deploy (Docker worker)
- Build an image that includes Prefect, dbt, and your adapter(s):
# Dockerfile FROM python:3.11-slim WORKDIR /app RUN pip install "prefect[dbt]" dbt-snowflake # pick your adapter(s) COPY . /app ENV DBT_PROFILES_DIR=/app/.dbt CMD ["python", "flows/dbt_build.py"]
Copy code
- Use a prefect.yaml with build/push steps (prefect-docker) and your deployment:
name: dbt-workflows prefect-version: ">=3.0.0" build: - prefect_docker.deployments.steps.build_docker_image: id: build-image requires: prefect-docker>=0.7.1 image_name: your-registry/dbt-flows tag: latest dockerfile: Dockerfile push: - prefect_docker.deployments.steps.push_docker_image: requires: prefect-docker>=0.7.1 image_name: "{{ build-image.image_name }}" tag: "{{ build-image.tag }}" deployments: - name: dbt-build-prod entrypoint: flows/dbt_build.py:dbt_build work_pool: name: my-docker-pool job_variables: image: "{{ build-image.image }}" env: DBT_PROJECT_DIR: /app/dbt_project DBT_PROFILES_DIR: /app/.dbt
Copy code
- Deploy and start a Docker worker:
prefect deploy -n dbt-build-prod prefect worker start -p my-docker-pool
Copy code
Step 6 — Run or schedule from Cloud
- In Prefect Cloud, find your deployment (Deployments page), click “Run” or add a schedule.
- View logs and per-dbt-node task states in the flow run UI. dbt models and seeds also show up as Prefect assets.

Recommended practices for dbt + Prefect
- Prefer PrefectDbtRunner over shelling out — it gives node-level tasks, better logs, and asset lineage.
- Keep secrets out of repo:
  - Use Prefect Secret blocks and/or profiles.yml env vars.
  - Or use profiles.yml templating with Prefect blocks/variables.
- For production, use Docker/K8s workers so your dbt adapter versions are pinned and repeatable.
- Use `prefect deploy` (3.x) or `flow.from_source(...).deploy(...)` — do not use removed 2.x commands like `Deployment.build_from_flow()` or `prefect deployment build`.
- If using CI, on Hobby you’ll use a user API key in your pipeline (no service accounts). Store it as a CI secret and set `PREFECT_API_KEY`/`PREFECT_API_URL` in your job.
- Tag your deployment (e.g., `env:dev`, `env:prod`) and mirror that in dbt selectors.

Common tweaks you might need
- Selecting a subset:
runner.invoke(["run", "--select", "tag:daily+"])
Copy code
- Passing vars:
runner.invoke(["run", "--vars", "{'run_date':'2026-03-01'}"])
Copy code
- Using env for dbt:
# set once in job env (Docker/K8s) or in your flow before invoking DBT_PROJECT_DIR=/app/dbt_project DBT_PROFILES_DIR=/app/.dbt ``` Useful links - Prefect + dbt integration (installation, runner, profiles) - Deployments (3.x) - Work pools and workers Questions to tailor next steps for you - Which adapter are you using (e.g., DuckDB, Snowflake, BigQuery)? - Do you prefer to start with a Process worker on your dev machine, or go straight to a Docker/K8s worker? - Do you have a repo where we can deploy from Git (recommended), or do you want to deploy from your local working copy first? If you share those details, I’ll give you a targeted snippet (profiles.yml templating or Dockerfile/job variables) for your exact setup.
h
@Marvin I have stored the secret in gcp credentials block as a service account info, now how will it be loaded when getting the secerets using prefect and load and how dbt will get that. le_analytics_dbt: target: dev outputs: dev: type: bigquery method: service-account-json keyfile_json: "type": "service_account" "project_id": "{{ env_var('DBT_BQ_PROJECT_ID') }}" "private_key_id": "{{ env_var('DBT_BQ_PRIVATE_KEY_ID') }}" "private_key": "{{ env_var('DBT_BQ_PRIVATE_KEY') }}" "client_email": "{{ env_var('DBT_BQ_CLIENT_EMAIL') }}" "client_id": "{{ env_var('DBT_BQ_CLIENT_ID') }}" "auth_uri": "{{ env_var('DBT_BQ_AUTH_URI') }}" "token_uri": "{{ env_var('DBT_BQ_TOKEN_URI') }}" "auth_provider_x509_cert_url": "{{ env_var('DBT_BQ_AUTH_PROVIDER_X509_CERT_URL') }}" "client_x509_cert_url": "{{ env_var('DBT_BQ_CLIENT_X509_CERT_URL') }}" project: "{{ env_var('DBT_BQ_PROJECT_ID') }}" dataset: "{{ env_var('DBT_BQ_DEV_DATASET') }}" location: "{{ env_var('DBT_BQ_LOCATION') }}" threads: 4 I have stored using this code: from prefect_gcp import GcpCredentials # replace this PLACEHOLDER dict with your own service account info service_account_info = { "type": "service_account", "project_id": "PROJECT_ID", "private_key_id": "KEY_ID", "private_key": "-----BEGIN PRIVATE KEY-----\nPRIVATE_KEY\n-----END PRIVATE KEY-----\n", "client_email": "SERVICE_ACCOUNT_EMAIL", "client_id": "CLIENT_ID", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://accounts.google.com/o/oauth2/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/SERVICE_ACCOUNT_EMAIL" } GcpCredentials( service_account_info=service_account_info ).save("CREDENTIALS-BLOCK-NAME") now on the flow how can i pass the creds to dbt on load or how will it pick?
m
thought for 168.1 seconds
Great setup. Since you’ve saved your GCP service account JSON in a Prefect GcpCredentials block, you have two clean ways to feed it to dbt: A) Keep your current profiles.yml with env_var and set env vars from the block (works with PrefectDbtRunner) - dbt will resolve your
{{ env_var('...') }}
keys if those environment variables are set at runtime. - In your flow, load the GcpCredentials block, export its fields to the env vars your profiles.yml expects, then invoke dbt. Example:
Copy code
from prefect import flow
from prefect_dbt import PrefectDbtRunner, PrefectDbtSettings
from prefect_gcp import GcpCredentials
import os

def export_bq_env_from_block(block_name: str):
    creds = GcpCredentials.load(block_name)
    info = creds.service_account_info  # dict of your service account JSON

    # Map service account JSON fields to the env vars used in your profiles.yml
    os.environ["DBT_BQ_PROJECT_ID"] = info["project_id"]
    os.environ["DBT_BQ_PRIVATE_KEY_ID"] = info["private_key_id"]
    os.environ["DBT_BQ_PRIVATE_KEY"] = info["private_key"]
    os.environ["DBT_BQ_CLIENT_EMAIL"] = info["client_email"]
    os.environ["DBT_BQ_CLIENT_ID"] = info["client_id"]
    os.environ["DBT_BQ_AUTH_URI"] = info["auth_uri"]
    os.environ["DBT_BQ_TOKEN_URI"] = info["token_uri"]
    os.environ["DBT_BQ_AUTH_PROVIDER_X509_CERT_URL"] = info["auth_provider_x509_cert_url"]
    os.environ["DBT_BQ_CLIENT_X509_CERT_URL"] = info["client_x509_cert_url"]

    # Also set dataset/location (these are not in the SA JSON)
    # Prefer pulling from Prefect Variables or your deployment env
    # Example:
    # os.environ["DBT_BQ_DEV_DATASET"] = "your_dataset"
    # os.environ["DBT_BQ_LOCATION"] = "US"

@flow
def dbt_build():
    export_bq_env_from_block("CREDENTIALS-BLOCK-NAME")

    settings = PrefectDbtSettings(
        project_dir="./dbt_project",
        profiles_dir="~/.dbt"  # or repo-local .dbt
    )
    PrefectDbtRunner(settings=settings, raise_on_failure=True).invoke(["build"])

if __name__ == "__main__":
    dbt_build()
Notes: - The
private_key
string from Google usually includes literal
\n
. You should pass it as-is to the env var; dbt/Google auth handles it correctly. - In deployments (Docker/K8s), you can either: - Run the same “export” code at runtime (as above), or - Pre-set those env vars via job variables if you’re not loading a block at runtime. The block approach is usually simpler and safer. B) Let Prefect generate profiles.yml from your GcpCredentials block (no env vars needed) - Use the dbt CLI wrappers with a programmatic profile. This plugs your GcpCredentials block directly into dbt’s BigQuery profile, and Prefect writes a profiles.yml for the run. Example:
Copy code
from prefect import flow
from prefect_gcp import GcpCredentials
from prefect_dbt.cli.configs import BigQueryTargetConfigs
from prefect_dbt.cli.credentials import DbtCliProfile
from prefect_dbt.cli.commands import run_dbt_build

@flow
def dbt_build():
    gcp = GcpCredentials.load("CREDENTIALS-BLOCK-NAME")

    target = BigQueryTargetConfigs(
        schema="your_dev_dataset",     # BigQuery dataset
        project="your-gcp-project",    # or omit if set in the block
        credentials=gcp,
        # extras={"location": "US"}    # optional: set region and other BQ options
    )

    profile = DbtCliProfile(
        name="le_analytics_dbt",
        target="dev",
        target_configs=target,
    )

    # overwrite_profiles=True tells Prefect to write a profiles.yml for this run
    run_dbt_build(
        project_dir="./dbt_project",
        dbt_cli_profile=profile,
        overwrite_profiles=True,
        create_summary_artifact=True
    )

if __name__ == "__main__":
    dbt_build()
When to pick which - Use A (env vars + PrefectDbtRunner) if you want dbt node-level task visibility and asset lineage with the recommended runner, and you’re happy keeping your current profiles.yml shape. Just set env vars from the block before invoking.
- Use B (DbtCliProfile + BigQueryTargetConfigs) if you prefer not to manage env vars. This is very clean for BigQuery and works great with the dbt CLI tasks (
run_dbt_build
,
run_dbt_run
, etc.). A couple of extra tips - Keep dataset and location outside of the service account JSON (as you already do). You can set them via env vars, Prefect Variables, or
extras={"location": "US"}
in BigQueryTargetConfigs. - For production, prefer a Docker/K8s worker and bake dbt + adapters into the image. Then either: - Load the GcpCredentials block at runtime (code above) and export env vars, or - Use the DbtCliProfile path to avoid env vars entirely. Reference: Prefect + dbt integration guide If you tell me your preferred approach (Runner vs CLI tasks) and where your profiles.yml lives, I can tailor the snippet to your exact repo and deployment type.
h
@Marvin I am on a hobbly plan of prefect cloud, in windows i cant create a worker pool in windows, so i have foudn another method, flow.serve that runs in the terminal and we can manage thru prefect UI, so is there any way i can run that serve in windows bakcground 24/7 (
m
Error: unhandled errors in a TaskGroup (1 sub-exception)
Sorry, I encountered an error while processing your request. Please try again.
h
@Marvin I am on a hobbly plan of prefect cloud, in windows i cant create a worker pool in windows, so i have foudn another method, flow.serve that runs in the terminal and we can manage thru prefect UI, so is there any way i can run that serve in windows bakcground 24/7 (
m
thought for 217.8 seconds
Yes — you can keep
flow.serve
running 24/7 on Windows. Since
serve()
is a long‑running, blocking process, the trick is to run it as a background service that auto-starts and restarts on failure. Here are reliable options: 1) Windows service with NSSM (recommended) - Why: simple, robust auto-restart, runs without a user session. - Steps: - Install NSSM from nssm.cc. - Create your flow file, e.g. `C:\flows\my_flow.py`:
Copy code
from prefect import flow

    @flow
    def my_flow():
        print("Hello from Windows!")

    if __name__ == "__main__":
        # interval schedule example
        my_flow.serve(
            name="windows-service-deployment",
            interval=3600,
            pause_on_shutdown=False  # keeps schedule active across restarts
        )
- Register a service (run an elevated PowerShell or CMD): - Easiest via GUI: - Run:
nssm install PrefectServe
- Path: point to your Prefect CLI executable, e.g.
C:\path\to\venv\Scripts\prefect.exe
- Arguments:
flow serve C:\flows\my_flow.py:my_flow -n windows-service-deployment
- Startup directory:
C:\flows
- (Optional) Set stdout/stderr log files on the “I/O” tab for logging. - On “Environment” tab, add: -
PREFECT_API_URL=<https://api.prefect.cloud/api/accounts/<ACCOUNT-ID>/workspaces/<WORKSPACE-ID>>
-
PREFECT_API_KEY=<YOUR-API-KEY>
- Save, then start:
nssm start PrefectServe
- Or via command line:
Copy code
nssm install PrefectServe "C:\path\to\venv\Scripts\prefect.exe" "flow serve C:\flows\my_flow.py:my_flow -n windows-service-deployment"
      nssm set PrefectServe AppDirectory "C:\flows"
      nssm set PrefectServe AppEnvironmentExtra "PREFECT_API_URL=<https://api.prefect.cloud/api/accounts/<ACCOUNT-ID>/workspaces/<WORKSPACE-ID>>"
      nssm set PrefectServe AppEnvironmentExtra "PREFECT_API_KEY=<YOUR-API-KEY>"
      nssm set PrefectServe AppRestartDelay 5000
      nssm start PrefectServe
- Notes: - Using the CLI (
prefect flow serve ...
) is equivalent to calling
my_flow.serve()
in your script. - If you prefer to run the Python file directly, set the NSSM Path to
C:\Python312\python.exe
and Arguments to
C:\flows\my_flow.py
. 2) Windows Task Scheduler (built-in) - Good if you don’t want third-party tools, but less robust for true “service”-style uptime. - Create a small batch wrapper to set env and run your script:
Copy code
@echo off
  set PREFECT_API_URL=<https://api.prefect.cloud/api/accounts/<ACCOUNT-ID>/workspaces/<WORKSPACE-ID>>
  set PREFECT_API_KEY=<YOUR-API-KEY>
  set PYTHONIOENCODING=UTF-8
  cd /d C:\flows
  C:\Python312\python.exe C:\flows\my_flow.py
- In Task Scheduler: - Create Task → Triggers: “At startup” - General: “Run whether user is logged on or not” - Action: “Start a program” → point to the batch file - Settings: enable restart on failure, and “If the task is already running, do not start a new instance” 3) Docker (optional alternative) - Run your flow in a container with
restart: always
. Useful if you already use Docker Desktop on Windows. Important notes -
serve()
is blocking: it must run as a dedicated, long‑running process/service. - For Prefect Cloud, set
PREFECT_API_URL
and
PREFECT_API_KEY
in the service’s environment. - If you stop the serve process, schedules pause by default. Use
pause_on_shutdown=False
to keep them active through restarts. You can also use the CLI directly (verified):
Copy code
prefect flow serve --help
prefect flow serve ".\my_flow.py:my_flow" --name "windows-service-deployment" --interval 3600
Docs you may find helpful - Run flows in local processes (serve): Run flows in local processes - Connect to Prefect Cloud: Connect to Cloud
- CLI reference (flow serve): CLI: flow If you’d like, tell me: - Do you prefer NSSM, Task Scheduler, or Docker? - Where is your Python/Prefect installed (system vs venv)? I can give you exact commands tailored to your paths.