Slackbot
11/06/2025, 11:34 AMMarvin
11/06/2025, 11:34 AMMarvin
11/06/2025, 11:41 AMprefect work-pool create my-process-pool --type process
2) Run a worker inside your cluster (you can use the Prefect worker Helm chart or your own Deployment) to poll this pool:
prefect worker start -p my-process-pool --name k8s-process-worker-1
Example Deployment snippet:
apiVersion: apps/v1
kind: Deployment
metadata:
name: prefect-process-worker
spec:
replicas: 1
selector:
matchLabels:
app: prefect-process-worker
template:
metadata:
labels:
app: prefect-process-worker
spec:
containers:
- name: worker
image: prefecthq/prefect:3-latest
args: ["prefect","worker","start","-p","my-process-pool","--name","k8s-process-worker-1"]
env:
- name: PREFECT_API_URL
value: "<http://prefect-server-api.prefect.svc.cluster.local:4200/api>"
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "1"
memory: "512Mi"
3) Point your deployments to the Process pool (no per-run pod creation). For example, in Python:
from prefect import flow
@flow
def my_flow():
...
if __name__ == "__main__":
my_flow.deploy(
name="prod",
work_pool_name="my-process-pool",
)
- Docs:
- Prefect docs
- Work pools and workers: https://docs.prefect.io/latest/concepts/work-pools-workers/
- Process infrastructure: https://docs.prefect.io/latest/deploy/infrastructure/process/
Option B — Keep Kubernetes jobs, but make each pod smaller
- Use a smaller base image (e.g., a Python slim image + install Prefect at build time) and minimize layers.
- Lower memory requests/limits in your Kubernetes work pool’s base job template.
- Get the default template to edit:
prefect work-pool get-default-base-job-template --type kubernetes > k8s-template.json
- Update your work pool with the edited template, then set leaner job_variables on deployments (image, env, resources).
- This reduces per-pod memory but you’ll still incur one pod per run.
- Docs:
- Kubernetes deployment/infrastructure: https://docs.prefect.io/latest/deploy/infrastructure/kubernetes/
Option C — Fewer flow runs: batch many HTTP calls per run
- If you currently kick off one flow run per HTTP call, consider running one flow that triggers many requests concurrently.
- Use a task runner to fan out I/O-bound calls:
```
from prefect import flow, task
from prefect.task_runners import ThreadPoolTaskRunner
import httpx
@task
def fetch(url: str) -> int:
r = httpx.get(url, timeout=60.0)
return r.status_code
@flow(task_runner=ThreadPoolTaskRunner(max_workers=32))
def batch_fetch(urls: list[str]):Marvin
11/06/2025, 11:41 AM- Control global or per-endpoint concurrency with Prefect concurrency limits (tag your tasks and create limits):
# tag your task with tags=["external-api"]
prefect concurrency-limit create external-api 10
```
- Docs:
- Task runners: https://docs.prefect.io/latest/concepts/task-runners/
- Concurrency limits: https://docs.prefect.io/latest/concepts/concurrency/
- CLI reference (concurrency): https://docs.prefect.io/latest/reference/cli/
Quick recommendations based on your description
- If isolation and per-run images are not required: switch to a Process work pool with a single long‑lived worker pod (Option A). This is the biggest win for your use case and usually cuts RAM overhead per run to near-zero beyond the worker’s baseline.
- If you must keep per-run K8s jobs: trim the image and resource requests/limits (Option B), and consider batching to reduce the number of runs (Option C).
A couple of sanity checks we ran on the CLI
- Work pool create/help:
- prefect work-pool create --help (supports --type kubernetes|docker|process)
- Concurrency limit commands:
- prefect concurrency-limit --help (supports create/ls/inspect/delete/reset)
Questions to help us steer you to the best setup
- Are you okay trading per-run pod isolation for much lower overhead (i.e., run a Process worker in one pod)?
- Roughly how many runs per hour/day and how long does each HTTP request take?
- Do you need per-run custom container images?
- Are you on Prefect 3.x? (I’ve assumed 3.x here.)
If you share those constraints, I can provide a concrete Helm values.yaml (for a Process worker) or a tuned Kubernetes job template for your current pool.