Stefan
06/05/2026, 1:25 PMMarvin
06/05/2026, 1:25 PMMarvin
06/05/2026, 1:27 PMmy_flow.serve(...)
- my_flow.deploy(...)
- flow.from_source(...).deploy(...)
Not the old 2.x deployment builder APIs.
Example:
python
from prefect import flow
@flow
def my_flow():
print("hello")
if __name__ == "__main__":
my_flow.deploy(
name="my-deployment",
work_pool_name="my-pool",
)
If you don’t want a deployment and just want observability, you can run the flow normally and it’ll appear in the UI once executed.
Relevant docs:
- Deploy flows
- Serve flows locally
- Deployments concept
If you want, I can also explain the practical difference between just running a flow, serve(), and deploy() in one table.Stefan
06/05/2026, 1:29 PMfrom prefect import flow
from prefect_kubernetes.decorators import kubernetes
@kubernetes(
work_pool="my-kubernetes-pool",
namespace="custom-namespace"
)
@flow
def custom_namespace_flow():
pass
)Marvin
06/05/2026, 1:29 PMMarvin
06/05/2026, 1:31 PM@kubernetes(...) decorator is for submitting a flow directly to dynamic infrastructure without creating a deployment.
So the answer is:
No, those flows are not run from the UI unless you also create a deployment.
How it works:
- @kubernetes(...) wraps the flow as an infrastructure-bound flow
- when you call the flow in Python, Prefect submits that run to the specified work pool / infrastructure
- Prefect tracks the flow run in the UI
- but it does not create a deployment object
So you get:
- yes: observable flow runs in the UI
- no: deployment page / schedule / “run from UI” controls / automations based on a deployment
Using your example:
python
from prefect import flow
from prefect_kubernetes.decorators import kubernetes
@kubernetes(
work_pool="my-kubernetes-pool",
namespace="custom-namespace"
)
@flow
def custom_namespace_flow():
pass
This means:
- when custom_namespace_flow() is called from Python, Prefect submits it to Kubernetes using that work pool
- the namespace is passed as a job-variable override
- the run will be visible in Prefect
- but you still have not created a deployment
So if your question is:
“Can users click Run in the UI for this flow?”
Then the answer is not by default. For that, you need a deployment.
A useful mental model:
Infrastructure decorator:
- “run this flow on this infra when my Python code calls it”
Deployment:
- “register this flow as a managed runnable thing in Prefect so the UI/API/schedules/automations can launch it”
If you want both dynamic infra and UI-triggerable runs, use a deployment on a work pool instead.
Relevant docs:
- Submit flows directly to dynamic infrastructure
- Deployments
- Deploy flows
Rule of thumb
- use infrastructure decorators for programmatic ad hoc submission
- use deployments for UI/API-triggered, scheduled, or production-managed execution
If you want, I can show the equivalent deployment-based Kubernetes setup for that exact example so you can compare them side by side.Stefan
06/05/2026, 1:32 PMMarvin
06/05/2026, 1:32 PMMarvin
06/05/2026, 1:35 PMpython
@kubernetes(work_pool="my-kubernetes-pool")
@flow
def my_flow():
...
when you do:
python
my_flow()
your machine is used to submit the run, but the actual flow execution happens on Kubernetes.
So, more precisely:
Runs locally
- creating the flow run
- packaging/serializing the flow code
- contacting Prefect API
- submitting work to infrastructure
- waiting/monitoring the run in some modes
Runs remotely
- the actual flow function body
- tasks inside that flow
- anything your flow does at runtime
So no, this pattern is not “just running on your laptop”.
There are basically 3 use cases/patterns:
1. my_flow()
- submits the flow to remote infra
- blocks until it finishes
- useful when you want “run this on K8s, but I’m launching it from my machine/script”
2. my_flow.submit()
- also submits to remote infra
- returns immediately with a future
- useful for programmatically launching many remote runs from another flow/app
3. my_flow.submit_to_work_pool()
- submits a run for a worker to pick up
- best when your machine doesn’t have direct access to the infrastructure
- useful in CI/CD, control-plane style orchestration, or centralized worker setups
So the main use cases are:
Ad hoc remote execution
- “I’m on my laptop, but this job needs K8s resources / a GPU / big memory”
Programmatic orchestration
- one flow or app dynamically launches other flows onto different infrastructure
Infra selection per flow
- e.g. CPU jobs on one pool, GPU jobs on another, special namespace/node-pool for certain workloads
No deployment ceremony
- useful when you want remote execution without creating a deployment for every flow
Important caveat:
For my_flow() and my_flow.submit(), your machine usually still needs access/credentials to submit to that infrastructure.
So:
- your code does not execute locally
- but your machine may still need permission to launch the remote job
If you want the submission to also be decoupled from your machine, that’s when submit_to_work_pool() is more useful: a running worker handles the infra side.
A simple mental model:
Deployment = “Prefect UI/API can launch this”
Infrastructure decorator = “my Python code can launch this remotely”
So if your goal is:
- run from UI → use a deployment
- run remotely from code → infrastructure decorator is a good fit
Docs:
- Submit flows directly to dynamic infrastructure
- Deployments
If you want, I can give you a concrete end-to-end example showing what happens step by step for my_flow(), my_flow.submit(), and my_flow.submit_to_work_pool().