Gunnar Oehmichen
10/22/2025, 11:43 AMMarvin
10/22/2025, 11:43 AMMarvin
10/22/2025, 11:53 AMprefect.yaml is the user-authored, source-of-truth project/deployment config used by prefect deploy (and by prefect deployment build/apply).
- .prefect/flows.json is not a user-facing config. It’s an internal/cache file created by Prefect tooling to remember discovered flows in your repo (e.g., to speed up interactive selection). It is not read to register deployments and you generally shouldn’t edit it. It’s safe to delete; it will be regenerated.
How they relate (and don’t)
- prefect.yaml
- Purpose: Defines your project’s deployments, including the flow entrypoints (path/to/file.py:flow_func), work pool/queue, parameters, schedules, and build/push/pull steps.
- Used by: prefect deploy in Prefect 2.x reads this file to create/update deployments in the API.
- Ownership: You edit and commit this file to version control.
- Docs: https://docs-2.prefect.io/latest/guides/prefect-deploy/
- .prefect/flows.json
- Purpose: A local cache Prefect creates to remember which flows it discovered in your codebase. This helps the CLI/tools quickly present available flows if you run commands interactively.
- Used by: Only the local tooling for convenience. It is not authoritative for deployments and is not sent to the API.
- Ownership: Not intended for manual edits, typically excluded from version control. Safe to delete; Prefect will recreate it.
Deploying flows via the CLI in Prefect 2.14
- Config-driven (recommended when you have a prefect.yaml):
- Define one or more deployments under the deployments: section in prefect.yaml with their entrypoint, work pool/queue, etc.
- Then run from the project root:
prefect deploy
- This reads prefect.yaml, runs any build/push steps, and registers the deployments.
- Ad-hoc (single deployment without relying on prefect.yaml):
- Build a deployment spec file:
prefect deployment build ./path/to/file.py:flow_func -n my-deployment -q my-queue -p my-work-pool
- Then apply it:
prefect deployment apply my-deployment.yaml
- This path is useful if you want a one-off deployment YAML you can review/commit.
Key takeaways
- prefect.yaml is authoritative and controls what gets deployed.
- .prefect/flows.json is a local cache; it does not affect what’s deployed.
- If you see both referencing flows, treat prefect.yaml as the truth. You can ignore or delete .prefect/flows.json if it ever looks stale.
References
- Prefect deploy guide (2.x): https://docs-2.prefect.io/latest/guides/prefect-deploy/
- Deployment concepts (2.x): https://docs-2.prefect.io/latest/concepts/deployments-block-based/
If you’re comfortable sharing, could you paste a small snippet of your .prefect/flows.json? I can confirm it matches the typical flow-discovery cache and point out anything unusual.Gunnar Oehmichen
10/22/2025, 1:46 PMprefect deploy path/to/file.py:flow_name when it is entered beforehand in the .yaml (user authored)?Marvin
10/22/2025, 1:47 PMMarvin
10/22/2025, 1:48 PMprefect deploy if you’ve already declared the deployment(s) in prefect.yaml. prefect deploy will read the deployments from that file and register them.
Why the CLI still accepts ENTRYPOINT and flags:
- Two modes are supported:
1) Config-driven (from prefect.yaml): run from the project root and Prefect deploys the deployments you’ve defined.
- Examples:
prefect deploy
prefect deploy -n 'my-flow/my-deployment' # deploy just one by name pattern
2) Ad‑hoc (from CLI): pass ENTRYPOINT and flags to create/override a deployment on the fly, even if it isn’t in prefect.yaml.
- Example:
prefect deploy ./path/to/file.py:flow_func -n my-deployment -p my-pool -q my-queue
This is handy for quick experiments or when you don’t want to commit a prefect.yaml change.
Precedence/merge behavior:
- When you run prefect deploy with no entrypoint, Prefect uses the deployments declared in prefect.yaml.
- CLI flags (like --name, --work-pool, --param, etc.) can override values defined in prefect.yaml for the deployments you select (e.g., with -n).
- If you provide an ENTRYPOINT, Prefect can create a deployment from that entrypoint using the CLI options you pass, instead of (or in addition to) what’s in prefect.yaml.
About `.prefect/flows.json`:
- That file is just a local cache the tooling uses to remember discovered flows. It’s not authoritative for deployments and doesn’t need to match prefect.yaml. You don’t need to edit it; it’s safe to delete.
Docs:
- Prefect 2.x deploy guide: https://docs-2.prefect.io/latest/guides/prefect-deploy/
Recommendation: If you’ve already authored your deployments in prefect.yaml, just run prefect deploy (optionally with -n to select). Use the `ENTRYPOINT`/flags form for quick ad‑hoc runs or when you want to override without editing the YAML.Gunnar Oehmichen
10/22/2025, 2:03 PM# sends commands from outside into the pseudo-terminal of the container: deploying the specified prefect-flows
# docker ps lists running docker containers and filters for the given name and executes the prefect-deployment within that specific container
docker-deploy:
# docker exec -it $$(docker ps -aqf "name=goal100-mastr-pipeline") prefect --no-prompt deploy src/mvp_test_flow.py:mvp_test_flow --pool goal100-work-pool --name mvp_test_flow
docker exec -it $$(docker ps -aqf "name=goal100-mastr-pipeline") prefect --no-prompt deploy src/download_update_flow.py:download_update_flow --pool goal100-work-pool --name download_update_flow
docker: docker-build docker-run docker-deploy
to include only docker exec -it $$(docker ps -aqf "name=goal100-mastr-pipeline") prefect --no-prompt deploy) ?Marvin
10/22/2025, 2:03 PMMarvin
10/22/2025, 2:07 PMprefect deploy call, but drop --no-prompt and make sure you either deploy “all” or explicitly select by name.
A few notes to tighten up your workflow in Prefect 2.14.16:
- If your prefect.yaml already contains the deployments (with entrypoint, work pool/queue, etc.), you do not need to pass entrypoints on the CLI. Just run prefect deploy from the project root.
- In non‑interactive/CI contexts (like docker exec), avoid prompts by selecting deployments explicitly. Two safe options:
- Deploy all from `prefect.yaml`:
prefect deploy --all
- Deploy specific ones by name pattern:
prefect deploy -n 'download_update_flow/*' -n 'mvp_test_flow/*'
In 2.14, --no-prompt is not a documented flag for prefect deploy, so don’t rely on it.
- Ensure the command runs in the project root inside the container (where prefect.yaml lives) and that the container has PREFECT_API_URL set to your (local or Coolify) Prefect API.
Given that, your Makefile can be simplified to one line, e.g.:
docker-deploy:
docker exec -it $$(docker ps -aqf "name=goal100-mastr-pipeline") bash -lc 'cd /app && prefect deploy --all'
- Replace /app with the project root path inside the container.
- If you only want to deploy certain ones, swap --all for -n patterns:
docker exec -it $$(docker ps -aqf "name=goal100-mastr-pipeline") bash -lc 'cd /app && prefect deploy -n "download_update_flow/*" -n "mvp_test_flow/*"'
Additional tips:
- Make sure a worker is running and connected to the same work pool(s) you set in prefect.yaml so the deployments are picked up.
- If your prefect.yaml has build/push steps, confirm they make sense inside the runtime container. If you’re already shipping the code in the image, keep build: and push: null so prefect deploy just registers deployments.
Docs: https://docs-2.prefect.io/latest/guides/prefect-deploy/
If you want, paste your prefect.yaml deployments section and I’ll sanity‑check the -n patterns you’d use.Gunnar Oehmichen
10/22/2025, 2:50 PMMarvin
10/22/2025, 2:50 PMMarvin
10/22/2025, 2:52 PMprefect deploy ./src/some_file.py:some_flow --name some_deployment --pool some-pool
that creates a deployment directly in the API without touching prefect.yaml. It will keep showing up in the UI until deleted or overwritten, even if it isn’t in your YAML.
- Or, you might just be seeing a Flow (under the Flows tab) rather than a Deployment. A Flow appears in the UI as soon as you run it once (even with my_flow() locally). That doesn’t require a deployment or an entry in prefect.yaml.
Next steps to confirm and clean up:
1) List deployments:
prefect deployments ls
Find the flow/deployment that “shouldn’t” be there.
2) Inspect it to see how it was created (entrypoint, storage, work pool, timestamps):
prefect deployments inspect 'flow-name/deployment-name'
3) If you don’t want it, delete it:
prefect deployments delete 'flow-name/deployment-name'
4) If it’s only a Flow (no deployment) that you’re seeing, that’s expected after any run. You can leave it, or stop running that flow in that workspace. (There isn’t a standard CLI to delete Flow objects; they’re created when runs happen.)
Also double‑check both your local and Coolify environments are pointed at the same API/workspace (PREFECT_API_URL). If they are, you’ll see the same objects in both UIs.
If you paste the output of:
- prefect deployments ls (just the line for the unexpected one), and
- prefect deployments inspect 'flow-name/deployment-name'
I can help confirm how it was created and the cleanest way to reconcile it with your prefect.yaml.Gunnar Oehmichen
10/22/2025, 3:01 PMMarvin
10/22/2025, 3:01 PMMarvin
10/22/2025, 3:02 PMprefect.yaml won’t appear in the UI until you actually register them with prefect deploy reading that YAML.
What to do
- Inside the container, run from the project root (where prefect.yaml lives) and deploy all YAML-defined deployments:
prefect deploy --all
Or, select specific ones by name pattern:
prefect deploy -n 'my-flow/my-deployment' -n 'other-flow/*'
- Verify what’s currently registered:
prefect deployments ls
If you see old ad‑hoc deployments you don’t want, remove them:
prefect deployments delete 'flow-name/deployment-name'
- Ensure the container points at the correct API/workspace:
- Self-hosted/Server: set PREFECT_API_URL in the container to your Coolify Prefect API
- Cloud: set PREFECT_API_KEY and workspace settings
If the API target differs between local and Coolify, the UIs will show different deployments.
Makefile simplification
- If you want to deploy everything in `prefect.yaml`:
docker-deploy:
docker exec -it $$(docker ps -aqf "name=goal100-mastr-pipeline") bash -lc 'cd /app && prefect deploy --all'
Replace /app with your project root inside the container.
- If you want only a subset, use `-n`:
docker exec -it $$(docker ps -aqf "name=goal100-mastr-pipeline") bash -lc 'cd /app && prefect deploy -n "download_update_flow/my-deployment" -n "mvp_test_flow/*"'
Tips
- Keep build: and push: as null in prefect.yaml if you’re already shipping code in the image; prefect deploy will just register deployments.
- If you’re unsure which names to pass to -n, share the deployments: section of your prefect.yaml and I’ll suggest the exact -n values.
Docs: https://docs-2.prefect.io/latest/guides/prefect-deploy/Gunnar Oehmichen
10/22/2025, 3:05 PMMarvin
10/22/2025, 3:05 PMMarvin
10/22/2025, 3:06 PMprefect deploy (or prefect deployment apply), Prefect sends that deployment specification to the API. The API persists it, and that’s what you see in the UI and what workers poll to pick up runs.
- Your local files (like prefect.yaml) are just the source/config describing what you want deployed. They are not the deployment themselves. Nothing shows up in the UI until you register it with the API.
- Because the deployment lives in the API:
- You can see it in the UI from any machine/environment pointed at the same workspace.
- Workers poll the API for deployments and schedules to create flow runs.
- You can delete/update deployments via CLI or UI without editing local files (though best practice is to keep prefect.yaml as the system of record and re-run prefect deploy).
A helpful mental model:
- prefect.yaml: your desired state (version-controlled spec).
- prefect deploy: syncs desired state to the API.
- API/UI: the actual, current state that workers read from and that you observe.
If you want to verify where you’re “saving” deployments, check the environment’s Prefect target:
- Cloud/Server URL and workspace: prefect config view shows PREFECT_API_URL and workspace context.
- If your local machine and Coolify container point to different `PREFECT_API_URL`s, you’ll see different deployments in their UIs.
To reconcile drift:
- Run prefect deployments ls to see what the API currently has.
- Delete any strays: prefect deployments delete 'flow-name/deployment-name'.
- Re-deploy from your `prefect.yaml`: prefect deploy --all (or -n selections).Gunnar Oehmichen
10/23/2025, 8:33 AMMarvin
10/23/2025, 8:33 AMMarvin
10/23/2025, 8:39 AMprefect_docker.deployments.steps.build_docker_image
- push (optional)
- Upload what you built in build: e.g., push the Docker image to a registry.
- Example step: prefect_docker.deployments.steps.push_docker_image
- pull (usually required)
- Prepare code and environment where the flow actually runs:
- Pull code from Git: prefect.deployments.steps.pull.git_clone
- Download an artifact from storage: prefect.deployments.steps.pull.pull_from_remote_storage (supports fsspec URLs like s3://, gs://, etc.)
- Set working directory: prefect.deployments.steps.pull.set_working_directory
- Install deps at runtime: prefect.deployments.steps.utility.pip_install_requirements
- Use a block at runtime: prefect.deployments.steps.pull.pull_with_block
Templating and step IDs
- Steps can have an id. Later steps can reference outputs from earlier ones using Jinja, e.g. {{ clone.directory }}.
- Environment variables: {{ $ENV_VAR }}
- Variables and block references can also be templated; block references in pull are resolved at runtime (safer for secrets).
Examples
1) Git-based deployment (no Docker)
- Your worker will clone the repo on every run (pull only).
name: my-project
prefect-version: ">=3.0.0"
pull:
- prefect.deployments.steps.pull.set_working_directory:
directory: /opt/prefect/flows
- id: clone
requires: gitpython
prefect.deployments.steps.pull.git_clone:
repository: <https://github.com/acme/prefect-flows.git>
branch: main
deployments:
- name: etl
entrypoint: flows/etl.py:etl
work_pool:
name: my-pool
2) Docker image deployment
- Build/push once at deploy time; worker just runs the image. You may still set a working directory in pull.
name: my-docker-project
prefect-version: ">=3.0.0"
build:
- id: image
requires: prefect-docker
prefect_docker.deployments.steps.build_docker_image:
image_name: <http://ghcr.io/acme/etl|ghcr.io/acme/etl>
tag: "{{ $GIT_COMMIT_SHA | default('latest') }}"
push:
- requires: prefect-docker
prefect_docker.deployments.steps.push_docker_image:
image_name: "{{ image.image_name }}"
tag: "{{ image.tag }}"
pull:
- prefect.deployments.steps.pull.set_working_directory:
directory: /opt/prefect/flows
deployments:
- name: etl
entrypoint: flows/etl.py:etl
work_pool:
name: my-docker-pool
job_variables:
image: "<http://ghcr.io/acme/etl:{{|ghcr.io/acme/etl:{{> $GIT_COMMIT_SHA | default('latest') }}"
3) Remote storage artifact (pull from S3)
- Worker downloads code at runtime from storage.
```
name: my-storage-project
prefect-version: ">=3.0.0"
pull:
- prefect.deployments.steps.pull.pull_from_remote_storage:
url: "s3://my-bucket/prefect-artifacts/flows-{{ $GIT_COMMIT_SHA }}.tar.gz"
- prefect.deployments.steps.pull.set_working_directory:Marvin
10/23/2025, 8:39 AMgit_clone, pull_from_remote_storage, set_working_directory, pull_with_block, pip_install_requirements, run_shell_script
- Build: prefect_docker.deployments.steps.build_docker_image, pip_install_requirements, run_shell_script
- Push: prefect_docker.deployments.steps.push_docker_image, run_shell_script
Differences from Prefect 2.x
- No prefect deployment build (use prefect deploy).
- No Deployment.build_from_flow() and no GitHub storage blocks. In 3.x, you use flow.from_source(...).deploy(...) or project-based prefect deploy, and you model packaging via build/push/pull steps.
- The pull section replaces the old “storage” attribute by explicitly defining how runtime environments fetch code.
If you can share your current prefect.yaml and how you want to ship your code (Docker image, Git clone each run, cloud storage, etc.), I can tailor the push/pull steps for your setup.Gunnar Oehmichen
10/23/2025, 8:52 AMMarvin
10/23/2025, 8:52 AMMarvin
10/23/2025, 8:53 AMprefect server stop
Clean/reset the local API database
- This drops and recreates all Prefect tables (you’ll lose flows, deployments, runs, work pools/queues, blocks, variables, automations, artifacts, etc.):
prefect server database reset -y
Start the server again (optional)
prefect server start
Does “clean the API” mean a full reset like above, or did you want to preserve some resources (e.g., blocks) and only clear runs? I can suggest more targeted commands if needed.Gunnar Oehmichen
10/23/2025, 9:01 AMprefect server start
• previously deployed flows still show up, why? How to remove those if they are not present in the prefect.yaml?Marvin
10/23/2025, 9:01 AMMarvin
10/23/2025, 9:03 AMprefect deployment ls
- Delete specific deployments:
prefect deployment delete <FLOW_NAME>/<DEPLOYMENT_NAME>
- Or delete them all:
prefect deployment delete --all
Note: In Prefect 2.x there isn’t a CLI to delete “flows” themselves; after deleting deployments they may still appear in the UI until there are no runs referencing them. To completely wipe all metadata, use Option B.
Option B: Reset the local API database (nuclear option)
- Stop the server if it’s running (Ctrl+C is fine, or):
prefect server stop
- Reset the DB:
prefect server database reset -y
- Start the server again:
prefect server start
This deletes everything in the API (deployments, flows, runs, schedules, blocks, variables, etc.).
Why .prefect/flows.json and prefect.yaml edits didn’t change the UI
- prefect.yaml only controls future prefect deploy actions; it does not remove resources already registered with the API.
- .prefect/flows.json is local project metadata and doesn’t affect what’s in the server database.
If you tell me whether you want to wipe everything or just remove a subset of deployments, I can give you exact commands tailored to your current list.Gunnar Oehmichen
10/23/2025, 9:14 AMMarvin
10/23/2025, 9:14 AMMarvin
10/23/2025, 9:18 AMprefect deploy entrypoint:flow) live in the API and Prefect doesn’t auto-generate a prefect.yaml from them.
You can, however, retrieve all the details and then copy them into a prefect.yaml yourself.
Step 1 — Find and inspect the deployment
- List deployments:
prefect deployment ls
- Inspect one to see all of its fields (name, entrypoint, parameters, tags, work pool/queue, schedule, etc.):
prefect deployment inspect "<FLOW_NAME>/<DEPLOYMENT_NAME>"
Step 2 — Map inspect output to prefect.yaml
Here’s a template you can fill in based on the inspect output:
name: my-project
prefect-version: ">=2.14.0"
deployments:
- name: <DEPLOYMENT_NAME> # from 'name'
entrypoint: <path/to/file.py:flow> # from 'entrypoint'
description: <DESCRIPTION> # from 'description' (optional)
parameters: # from 'parameters' (optional)
key: value
tags: # from 'tags' (optional)
- tag1
- tag2
work_pool:
name: <WORK_POOL_NAME> # from 'work_pool_name'
work_queue_name: <WORK_QUEUE_NAME> # from 'work_queue_name' (optional)
job_variables: # maps to worker job vars/infra_overrides (optional)
env: {}
# add other keys relevant for your worker, e.g. 'working_dir', 'stream_output', etc.
# Choose ONE schedule style if your deployment has a schedule
# For cron schedules:
schedule:
cron: "0 * * * *"
timezone: "UTC"
active: true
# For interval schedules:
# schedule:
# interval: "3600" # seconds
# timezone: "UTC"
# active: true
Notes and tips
- Not everything you see in inspect has a 1:1 field in prefect.yaml, but the important runtime items do:
- name -> deployments[].name
- entrypoint -> deployments[].entrypoint
- parameters -> deployments[].parameters
- tags -> deployments[].tags
- work_pool_name -> deployments[].work_pool.name
- work_queue_name -> deployments[].work_pool.work_queue_name
- schedules -> deployments[].schedule (use cron or interval as shown)
- infra_overrides / worker job config -> deployments[].job_variables
- If you were using a docker image or other packaging, you can also add optional build/push/pull steps in prefect.yaml (2.x supports this), but they are not required for local/standard setups.
- After you create prefect.yaml, you can redeploy with:
prefect deploy
- If you want to retire the old deployment, delete it:
prefect deployment delete "<FLOW_NAME>/<DEPLOYMENT_NAME>"
Docs for 2.x
- Deployments (2.x)
- Using prefect deploy (2.x)
If you share the output of prefect deployment inspect "<flow>/<deployment>", I can turn it into a ready-to-use prefect.yaml snippet for you.Gunnar Oehmichen
10/23/2025, 10:27 AMMarvin
10/23/2025, 10:27 AMMarvin
10/23/2025, 10:28 AMparameters, via the UI when triggering a run, or at runtime via CLI.
Parameter precedence
- CLI at run time: prefect deployment run <flow/deploy> -p key=value overrides everything
- Deployment YAML parameters overrides flow defaults
- Flow function defaults are used if neither of the above provides a value
Examples
1) All parameters have defaults — YAML can only define the schedule
# flows/etl.py
from prefect import flow
@flow
def etl(color: str = "blue", limit: int = 100):
...
# prefect.yaml (or deployment.yaml)
deployments:
- name: etl
entrypoint: flows/etl.py:etl
schedule:
cron: "0 * * * *"
timezone: "UTC"
Scheduled runs use color="blue", limit=100 unless you override them.
2) Required parameter — provide it in YAML or at run time
@flow
def etl(color: str, limit: int = 100):
...
deployments:
- name: etl
entrypoint: flows/etl.py:etl
parameters:
color: "green" # required because no default in code
schedule:
cron: "0 * * * *"
timezone: "UTC"
Or override at run time:
prefect deployment run etl/etl -p color='"red"'
Notes
- If you change the flow’s signature or defaults, redeploy so the API/UI schema reflects the update.
- Parameters provided in YAML or CLI must be JSON-serializable. Prefer simple types (str, int, float, bool, lists/dicts). If you need complex objects, pass a serializable representation.
If you want, share your flow signature and current YAML and I’ll confirm whether anything is missing for scheduled runs to work reliably.Gunnar Oehmichen
10/23/2025, 12:22 PM# pull section allows you to provide instructions for cloning this project in remote locations
pull:
- prefect.deployments.steps.set_working_directory:
directory: /Users/Name/Documents/project_repo
which is the local working directory. While the path on the server, in the containers coolify builds the path is just /prefect, so outside of the working directory, a persistent storage 'around' the containers. How and why?Marvin
10/23/2025, 12:22 PMMarvin
10/23/2025, 12:25 PMpull steps run on the worker at flow-run time. Your current config:
pull:
- prefect.deployments.steps.set_working_directory:
directory: /Users/Name/Documents/project_repo
will only work if the worker is running on that same machine and that exact path exists. It does not fetch code; it just “cd”s into that path. If the worker runs on a different host or under a different user, this will fail.
You have a few safer options:
Option 1: Clone the repo on each run (portable)
- Let the worker fetch the production branch and then set the working dir to the cloned path.
pull:
- id: clone
requires: gitpython
prefect.deployments.steps.git_clone:
repository: git@github.com:your-org/project_repo.git
branch: production
- prefect.deployments.steps.set_working_directory:
directory: "{{ clone.directory }}"
- Keep your entrypoint relative to the repo root (e.g., flows/my_flow.py:my_flow).
Option 2: Set the worker’s working directory via job variables (no pull step needed)
- If the worker is on the same machine and you want to use your local files, put the path in the deployment’s job variables instead of a pull step:
deployments:
- name: my-deploy
entrypoint: flows/my_flow.py:my_flow
work_pool:
name: process-pool
job_variables:
working_dir: /Users/Name/Documents/project_repo
- This makes the run start in that directory without an extra step. Still brittle across machines, but cleaner if truly local.
Option 3: Keep the pull step but avoid user-specific absolute paths
- Use an environment variable fallback:
pull:
- prefect.deployments.steps.set_working_directory:
directory: "{{ $PROJECT_ROOT | default('/opt/prefect/flows') }}"
- Set PROJECT_ROOT on each worker host.
Notes
- Your step path is fine in 2.14.16: prefect.deployments.steps.set_working_directory is the canonical form.
- If your entrypoint is relative, you must ensure the working directory at runtime matches the repo layout; otherwise, make entrypoint absolute (less common).
- If you also need dependencies, add a runtime install step:
- prefect.deployments.steps.pip_install_requirements:
requirements: requirements.txt
If you can confirm where your worker runs (same machine vs remote), I can recommend the best option and provide an exact prefect.yaml snippet for your setup.
Docs (2.x):
- Using prefect deploy (2.x)
- Deployments (2.x)Gunnar Oehmichen
10/23/2025, 12:30 PMMarvin
10/23/2025, 12:30 PMMarvin
10/23/2025, 12:35 PMentrypoint path you gave the deployment.
- This succeeds if:
- The code is already present on the same machine where the worker runs, and
- The entrypoint is either an absolute path or a path that’s valid relative to the worker’s working directory.
Recommended minimal setup for local, non-containerized runs
- Omit pull: entirely and set a working directory via job variables so your relative entrypoint always resolves:
deployments:
- name: my-deploy
entrypoint: flows/my_flow.py:my_flow
work_pool:
name: process-pool
job_variables:
working_dir: /Users/Name/Documents/project_repo
- Alternatively, use an absolute `entrypoint`:
deployments:
- name: my-deploy
entrypoint: /Users/Name/Documents/project_repo/flows/my_flow.py:my_flow
work_pool:
name: process-pool
- If you omit both pull and job_variables.working_dir, the worker must be started from your project directory so the relative entrypoint resolves.
When you should add a pull step
- If the worker is on a different machine, or you want consistency across restarts/users, add a pull step like git_clone to fetch the code at run time.
Docs (2.x):
- Using prefect deploy (2.x)
- Overriding job variables (working_dir, env, etc.)
If you share your current entrypoint and where your worker runs from, I can confirm the simplest working config.Gunnar Oehmichen
10/23/2025, 12:43 PMMarvin
10/23/2025, 12:43 PMMarvin
10/23/2025, 12:44 PMdeployments:
- name: my-deploy
entrypoint: /app/flows/my_flow.py:my_flow
work_pool:
name: docker-pool
job_variables:
image: <http://ghcr.io/acme/project:prod|ghcr.io/acme/project:prod>
working_dir: /app
2) Bind mount your local code into the container
- Mount the host repo into the container and set working_dir (or use an absolute entrypoint).
deployments:
- name: my-deploy
entrypoint: /app/flows/my_flow.py:my_flow
work_pool:
name: docker-pool
job_variables:
image: <http://ghcr.io/acme/base:latest|ghcr.io/acme/base:latest>
working_dir: /app
volumes:
- "/Users/Name/Documents/project_repo:/app:ro"
When you would add pull
- If the worker container shouldn’t depend on local mounts and you want it to fetch code on start (e.g., clone a Git repo), add a git_clone pull step and set working_dir accordingly.
If you can share which worker type you’re using (Docker/Kubernetes) and whether you bake the code into the image or mount it, I can provide an exact prefect.yaml snippet for your setup.Gunnar Oehmichen
10/23/2025, 12:46 PMMarvin
10/23/2025, 12:46 PMMarvin
10/23/2025, 12:46 PMpull: entirely
How to bake your project
- Create a Dockerfile that installs dependencies and copies your code into the image:
FROM python:3.11-slim
# Set a working directory inside the image
WORKDIR /app
# Install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy your project code into the image
COPY . /app
# (optional) Prefect config for your environment
# ENV PREFECT_API_URL=<http://prefect-server:4200/api>
- Build (and push if using a registry):
docker build -t <http://ghcr.io/acme/project:prod|ghcr.io/acme/project:prod> .
# docker push <http://ghcr.io/acme/project:prod|ghcr.io/acme/project:prod>
- Point your Prefect 2.14 deployment at that image and working directory:
deployments:
- name: my-deploy
entrypoint: /app/flows/my_flow.py:my_flow
work_pool:
name: docker-pool
job_variables:
image: <http://ghcr.io/acme/project:prod|ghcr.io/acme/project:prod>
working_dir: /app
Compare to other approaches
- Bind mount (not baked): Mount host code into the container at runtime via volumes job variable. Faster for dev, but couples runs to host paths.
- Pull steps: Have the container fetch code at runtime (git_clone, pull_from_*). Useful if you want to run “latest” without rebuilding the image, but adds runtime dependencies.
In your containerized setup, if the image already contains your code at the path your entrypoint uses, you can safely omit pull:.Gunnar Oehmichen
10/26/2025, 3:09 PMMarvin
10/26/2025, 3:09 PMMarvin
10/26/2025, 3:13 PMfrom prefect import flow
@flow
def my_flow(do_extra: bool = False):
if do_extra:
print("Doing the extra thing")
else:
print("Skipping the extra thing")
prefect.yaml with two deployments overriding the default differently:
name: my-project
prefect-version: ">=3.0.0"
deployments:
- name: prod
entrypoint: src/flow_name.py:my_flow
parameters:
do_extra: true # overrides the function default
work_pool:
name: default
- name: dry-run
entrypoint: src/flow_name.py:my_flow
parameters:
do_extra: false
work_pool:
name: default
Parameter precedence
- Highest: run-time overrides when you create a run (CLI, UI, or API)
- CLI example:
prefect deployment run my_flow/prod -p do_extra=false --watch
Note: values are parsed as JSON; use `true`/`false` not `"true"`/`"false"`.
- Next: deployment defaults from prefect.yaml (or from .deploy(parameters=...))
- Lowest: the flow function’s default in code
Best practices and caveats
- Use the flow’s default as a safe local default (what happens if someone runs the script directly).
- Use deployment parameters to encode environment- or schedule-specific behavior (e.g., “prod” turns on extra work, “dry-run” turns it off).
- Prefer clear deployment names that reflect the behavior (e.g., my_flow/prod vs my_flow/dry-run).
- Don’t quote booleans in YAML or they’ll become strings (`true`/`false`, not `"true"`/`"false"`).
- If you change parameters in prefect.yaml, re-run prefect deploy so the server gets the updated deployment.
- Parameters must match the flow’s signature; mismatches will error at run time.
- Job variables in the deployment are separate from flow parameters; don’t confuse them.
If you want, paste your prefect.yaml snippet and I’ll sanity-check the parameters section.Gunnar Oehmichen
10/31/2025, 10:45 AMprefect server database upgrade and prefect server database reset -y and what's with the -y flag?Marvin
10/31/2025, 10:45 AMMarvin
10/31/2025, 10:47 AMprefect server database upgrade --help
prefect server database reset --help
Examples:
# Safely migrate schema to latest
prefect server database upgrade -y
# Preview what would run without applying changes
prefect server database upgrade --dry-run
# Destructively wipe and recreate all Prefect tables
prefect server database reset -y
Notes:
- These commands apply to self-hosted Prefect Server (not Prefect Cloud’s managed DB).
- In production, prefer upgrade; avoid reset unless you intentionally want a clean slate.Gunnar Oehmichen
10/31/2025, 10:50 AMMarvin
10/31/2025, 10:50 AMMarvin
10/31/2025, 10:52 AMprefect server database upgrade
Prefect applies all the pending, ordered changes (called “migrations”) your current database needs to match the version of Prefect you’ve installed.
What is a “revision” and “head”?
- A “revision” is one step in the sequence of changes to the database layout. Each revision has an ID and builds on the previous one.
- “head” just means “the most recent revision that ships with your installed Prefect version.”
- Target revision (-r): You can stop at a specific revision if you need to (rare). By default, upgrade goes to “head,” which is what you almost always want.
When should you run “upgrade”?
- After you upgrade Prefect (the software) to a new version that includes schema changes, especially if you’ve disabled automatic migrations.
- Prefect Server can run migrations automatically on startup. This is controlled by the PREFECT_SERVER_DATABASE_MIGRATE_ON_START setting (defaults to on). If it’s off, you’ll need to run the upgrade command manually.
- Docs:
- Server CLI: database commands
- Settings reference (migrate on start)
What “reset” does
- “Reset” is the nuclear option:
prefect server database reset -y
It drops all Prefect tables and recreates them empty. This wipes everything (flows, runs, blocks, automations, work pools, artifacts, etc.). Use it only when you want a completely clean slate (e.g., local dev/testing).
What’s the -y flag?
- -y (short for --yes) skips the “Are you sure?” prompt. Good for automation, risky for destructive commands like reset.
Helpful tips
- Preview without changing anything:
prefect server database upgrade --dry-run
- On very large databases, upgrades may take time; you can increase the DB timeout if needed (e.g., PREFECT_API_DATABASE_TIMEOUT=600).
- More details:
- Database maintenance and migrations
- Database migration commands API
Summary
- Use “upgrade” to bring your database schema up to date with your installed Prefect—keeps your data intact.
- “Revision” = a single step in the schema change history; “head” = the latest step.
- “reset” destroys and recreates all tables—use sparingly.
- -y just answers “yes” to prompts so the command runs non-interactively.Gunnar Oehmichen
10/31/2025, 10:56 AMprefect server database upgrade ?Marvin
10/31/2025, 10:56 AMMarvin
10/31/2025, 10:58 AMprefect server database upgrade.
Why:
- Database “upgrades” only matter when the Prefect Server software introduces schema changes (new/changed tables/columns). If your server version hasn’t changed, the schema it needs is already in place.
- New deployments, schedules, parameters, etc. just write data into the existing schema and don’t need migrations.
When you would need an upgrade:
- You upgrade Prefect Server to a new version that includes schema changes. By default, Server will migrate automatically on startup; if you’ve disabled that, you’d run:
prefect server database upgrade -y
- You upgrade the Prefect Python client in your deployment environment significantly ahead of your server and it starts using features that require a newer server schema. In that case, upgrade your server (and let it migrate) or align client and server versions.
Notes and links:
- Auto-migrate on start is controlled by PREFECT_SERVER_DATABASE_MIGRATE_ON_START (defaults to True): https://docs-3.prefect.io/v3/api-ref/settings-ref
- Server database CLI docs: https://docs-3.prefect.io/v3/how-to-guides/self-hosted/server-cli
- Database maintenance and migrations: https://docs-3.prefect.io/v3/advanced/database-maintenance
And just to reiterate: prefect server database reset -y is destructive and only for wiping everything to start fresh—not needed for normal deployments.