Sabeer Zaman
04/02/2026, 6:00 PMMarvin
04/02/2026, 6:00 PMMarvin
04/02/2026, 6:09 PMprefect worker start --pool my-sidecar-pool --name app-1-sidecar
Make sure the sidecar has PREFECT_API_URL and PREFECT_API_KEY set for your Cloud workspace.
2) In your app, bind your flow to that pool and submit to it:
from prefect import flow
from prefect.flows import bind_flow_to_infrastructure
from prefect.workers.process import ProcessWorker
@flow
def my_job(x: int) -> int:
return x + 1
# one-time bind at import/startup
infra_flow = bind_flow_to_infrastructure(
my_job, work_pool="my-sidecar-pool", worker_cls=ProcessWorker
)
# inside your request handler
fut = infra_flow.submit_to_work_pool(x=42)
result = fut.result() # optional: wait for completion
Alternatively, you can submit directly via the API client if you prefer:
from prefect import get_client
async def submit():
async with get_client() as client:
fr = await client.create_flow_run(
flow=my_job,
work_pool_name="my-sidecar-pool",
parameters={"x": 42},
)
Key docs
- Workers (concepts): Workers
- Work pools (concepts): Work pools
- Submit flows to dynamic infrastructure (covers .submit_to_work_pool): Submit flows directly to dynamic infrastructure
- API client (create_flow_run): PrefectClient.create_flow_run
A few practical tips
- Ensure the sidecar container has the same code/dependencies as your app’s flow code; the Process worker will run flows as subprocesses inside that container.
- If you want each app instance to run only its own jobs, use a separate work queue per instance and target that queue on submission.
- For Docker/Kubernetes workers, install the appropriate extras (e.g., prefect[docker], prefect[kubernetes]) and use a Docker/K8s work pool instead of “process”.
If you share your runtime (Docker/K8s) and whether you want strict stickiness to each app instance, I can suggest an exact pool/queue layout and a sidecar manifest.Sabeer Zaman
04/02/2026, 6:12 PMMarvin
04/02/2026, 6:12 PMMarvin
04/02/2026, 6:14 PM.delay().
- Because they don’t use work pools, they do not count toward any “work pool” limits. You can run multiple background task worker sidecars without creating or consuming work pools.
- You still need PREFECT_API_URL and PREFECT_API_KEY in the sidecar so it can connect to your Cloud workspace.
Minimal example
- Sidecar (worker):
from prefect import task
from prefect.task_worker import serve
@task
def send_email(to, body):
...
if __name__ == "__main__":
serve(send_email, limit=4) # concurrency per worker
- Web server (submitting work to Cloud):
send_email.delay(to="<mailto:user@example.com|user@example.com>", body="Hello!")
Key differences vs. flow workers
- Background tasks: push-style via subscription; no work pools/queues; scale by running more task worker processes/pods and tuning limit=.
- Flow runs: pull-style via work pools and workers; submit with .submit_to_work_pool() or deployments.
Docs
- How to run background tasks: Run background tasks
- End-to-end web app + background tasks (sidecars/containers): Deploy a web app powered by background tasks
- Cloud rate limits (apply to both approaches): Rate limits
If you’re deciding between background tasks vs. flows + work pools for your sidecar pattern, I’m happy to help weigh the tradeoffs for your app (e.g., infra separation, scaling, retries, observability).