<@ULVA73B9P> how do the cool kids do environment s...
# ask-marvin
a
@Marvin how do the cool kids do environment synchronization in Prefect? If I have a production set up and I want to reproduce issues in lower environments, is it common to have a process that synchronizes the Prefect Postgres DB? How do people generally achieve this?
m
âś… thought for 630.6 seconds
n
curious to see what marvin will come up with tho
a
neat! Thanks!
m
Short answer: don’t sync/copy your Prefect Postgres DB between environments. The “cool kids” treat Prefect as code and keep environments isolated. Copying the DB is risky and brittle because block secrets are symmetrically encrypted with an environment-specific key; cloning prod → lower env either: - fails to decrypt secrets (different key), or - worse, if the key comes along, exposes your production credentials in non-prod. Recommended pattern in Prefect 3.x - Isolate environments - Prefect Cloud: one workspace per env (dev/stg/prod). - Self-hosted: separate server instances and separate Postgres DBs; use a different PREFECT_SERVER_ENCRYPTION_KEY in each env. - Docs: Security &amp; encryption, Blocks &amp; secrets, Settings &amp; profiles. - Deployments as code (promote via CI/CD) - Keep deployment definitions in git via
prefect.yaml
or
flow.from_source(...).deploy(...)
. - Pin code and containers (commit SHA, image digest) so staging can reproduce the exact prod code. - Docs: Deployments, prefect.yaml, CI/CD. - Secrets/blocks per environment - Create blocks with environment-specific credentials in each workspace. Reference them by name in deployments—don’t try to export/import secret values. - Docs: Blocks. How to reproduce production issues safely 1) Run the same code/image as prod - Pin your container to a digest/commit in your deployment so you can run the exact artifact in staging. Example (prefect.yaml fragment)
Copy code
deployments:
  - name: my-deployment
    entrypoint: flows/etl.py:flow
    work_pool:
      name: prod-pool
      job_variables:
        image: "my-registry/my-image@sha256:abc123..."  # pin digest
2) Reuse the same parameters - Inspect the prod run’s parameters and job variables, then re-run in staging with those inputs. View params/logs from a production run
Copy code
prefect flow-run inspect <PROD_RUN_ID>
prefect flow-run logs <PROD_RUN_ID>
Re-run in staging (switch profile first)
Copy code
prefect profile use staging
prefect deployment run -n "<FLOW_NAME>/<DEPLOYMENT_NAME>" \
  --param key1=value1 --param key2=value2 \
  --job-variable image="my-registry/my-image@sha256:abc123..."
3) Programmatic “replay” (copy prod params → staging)
Copy code
from prefect import get_client
import asyncio

async def replay_prod_run_in_staging(prod_run_id: str, staging_deployment_name: str):
    # Read prod params
    async with get_client() as prod_client:
        prod_run = await prod_client.read_flow_run(prod_run_id)
        params = prod_run.parameters

    # Switch your profile/env to staging before running this part
    async with get_client() as stg_client:
        # find the staging deployment
        deployments = await stg_client.read_deployments(
            deployment_filter={"name": {"equals": staging_deployment_name}}
        )
        dep = deployments[0]
        # run with prod params
        run = await stg_client.create_flow_run_from_deployment(dep.id, parameters=params)
        print("Staging replay run id:", run.id)

asyncio.run(replay_prod_run_in_staging("<PROD_RUN_ID>", "<FLOW>/<DEPLOYMENT>"))
4) Data reproduction - If the failure is data-driven, create a sanitized snapshot (e.g., S3 object) and pass the same identifiers as parameters in staging. Keep non-sensitive config in Variables; credentials in Blocks. - Docs: Variables. What to avoid - Copying/syncing the Prefect DB between environments - Breaks secret decryption or leaks prod creds. - Pulls schedules, IDs, historical logs, and other state you don’t want in lower envs.
- Docs: Security &amp; encryption (encryption key behavior), Database maintenance. A minimal, repeatable setup - One workspace per env (Cloud) or one server+DB per env (self-hosted). - Distinct PREFECT_API_URL/API keys per env; save as CLI profiles:
Copy code
prefect profile create dev
prefect profile create staging
prefect profile create prod
- Deployments defined in code and promoted via CI/CD: - dev branch → dev workspace - staging branch → staging workspace - main → prod - Blocks (secrets) created per env; same names, different values. - For reproductions: use pinned images + prod params; run in staging. If you share a bit more about your setup, I can tailor examples: - Prefect Cloud or self-hosted? - What infra do your workers use (Docker/K8s/ECS/etc.)? - Do you prefer
prefect.yaml
or
flow.from_source(...).deploy(...)
for deployments?