<@ULVA73B9P> what would you recommend is the best ...
# ask-marvin
e
@Marvin what would you recommend is the best GitOps approach to managing the deployment of says 100s of flows? We want it to have auto reconciliation and everything, curious what the recommendations are here or do we need to make something custom
m
thought for 418.0 seconds
Great question. At scale (100s of flows), you’ll want a GitOps workflow that is declarative, idempotent, and easy to reconcile automatically. Here’s what we generally recommend for Prefect 3.x, plus a few options depending on how strict you want “auto-reconciliation” to be. Recommended baseline (simple, robust, scales well) - Repo structure - Keep your flow code in version control with a single project-level
prefect.yaml
that defines all your deployments. - Monorepo or multi-repo can both work; the key is that each project has a
prefect.yaml
. - Declarative deployments - Define each deployment in `prefect.yaml`: entrypoint, name, work pool, schedules, parameters, infra variables, etc. - Use immutable references where possible: - Pin deployments to a Git commit for the code they run (using
flow.from_source(..., git_revision=...)
when creating deployments programmatically) and/or use immutable image tags. - CI to “apply” desired state - On every merge to main, run
prefect deploy
from the project root to upsert deployments. This is idempotent and safe to run repeatedly. - Optionally, run on a nightly schedule as a drift-catch. - Selective deploys at scale - Use entrypoint/flow name patterns to limit to changed or targeted subsets. For example:
Copy code
prefect deploy --name "my-flow/*"
or point to a specific entrypoint:
Copy code
prefect deploy ./flows/etl.py:etl_flow
- Work pool separation - Group deployments by work pool to enforce isolation (e.g., per environment/tenant/team, or per backend: Docker, K8s, ECS). - Rollbacks - Keep deployments pinned to commit SHAs; to roll back, redeploy with a previous SHA. See rollbacks guide. CLI commands you’ll use (verified) - Initialize a project scaffold (one-time):
Copy code
prefect init
- Create/update deployments from the project:
Copy code
prefect deploy
- List and inspect:
Copy code
prefect deployment ls
  prefect deployment inspect "<flow>/<deployment>"
- Manage work pools:
Copy code
prefect work-pool ls
Auto-reconciliation options Option A: CI-only reconciliation (most common) - Treat your
prefect.yaml
as the source of truth and run
prefect deploy
on merge and nightly. - Pros: Simple, fast, no extra infra. Cons: Doesn’t automatically prune removed deployments without an additional step. - For “prune,” add a small CI job that: - Lists deployments with a label like
managed-by=gitops
- Compares them to what’s defined in your repo - Deletes orphaned ones via
prefect deployment delete
or the API - This keeps Git and Prefect in lockstep without much custom code. Option B: Terraform-managed reconciliation (strong drift detection) - Use Terraform to codify deployments, work pools, automations, and blocks; run plan/apply to reconcile. - Pros: Best-in-class drift detection and approvals; aligns tightly to GitOps. Cons: Requires adopting/maintaining provider resources. - References: - Managing Prefect deployments with Terraform (overview and patterns) - Note: Coverage of every Prefect 3 resource may vary; this works best when you’re already using Terraform org-wide. Option C: ArgoCD/Flux trigger job (cluster-native reconciliation) - Use ArgoCD/Flux to watch your repo and trigger a job that runs
prefect deploy
whenever the desired state changes (and/or on a schedule). - Pros: Familiar GitOps operational model with periodic reconciliation. Cons: You’ll run a small runner job—still fairly lightweight. Programmatic mass-deploy (useful for hundreds of flows) - If you prefer code to YAML for defining lots of deployments, generate them programmatically and run in CI: ``` from prefect import flow from pathlib import Path # Example: batch-create deployments from source
# Assumes each flow has a named entrypoint; commit SHA provided via env GIT_URL = "https://github.com/org/repo" REV = os.environ["GIT_SHA"] WORK_POOL = "k8s-prod-pool" # Discover flows and deploy for file in Path("flows").glob("*.py"): entrypoint = f"{file}:{file.stem}_flow" # adjust to your naming convention # Uses the 3.x API: from_source(...).deploy(...) f = flow.from_source(GIT_URL, entrypoint=entrypoint, git_revision=REV) f.deploy( name=f"{file.stem}/prod", work_pool_name=WORK_POOL, version=REV, # job_variables, schedules, parameters... )
Copy code
- This pattern lets you pin the exact revision and create hundreds of deployments in seconds. It’s also easy to wrap in a CI job.

Example GitHub Actions CI snippet
name: Reconcile Prefect Deployments on: push: branches: [ main ] schedule: - cron: "0 3 * * *" # nightly reconciliation jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.11" - run: pip install prefect - name: Prefect auth run: prefect config set PREFECT_API_URL=$PREFECT_API_URL PREFECT_API_KEY=$PREFECT_API_KEY env: PREFECT_API_URL: ${{ secrets.PREFECT_API_URL }} PREFECT_API_KEY: ${{ secrets.PREFECT_API_KEY }} - name: Deploy all run: prefect deploy # Optionally: deploy only a subset, e.g., by pattern # - run: prefect deploy --name "my-flow/*" ``` Docs and references - Prefect 3 deployments with prefect.yaml: prefect.yaml guide - CI/CD for deployments: CI/CD deployment guide - Rollbacks/versioning: blog: rollbacks - Terraform overview: blog: managing deployments with Terraform Do you have a preference among CI-only, Terraform, or ArgoCD/Flux for reconciliation? Also, are you targeting Docker, Kubernetes, ECS, or something else for execution? With those details I can sketch a concrete repo layout and CI config tailored to your stack.