Jashaul
10/21/2025, 8:32 PMMarvin
10/21/2025, 8:32 PMMarvin
10/21/2025, 8:40 PMPREFECT_API_URL set on your worker pods?
- Are you using Ingress/TLS for Server? Any custom certs?
- Do you have NetworkPolicies between namespaces?
- Can you share a few lines from the worker logs around the restart? e.g. name resolution errors, connect timeouts, SSL errors, or 401s?
- Roughly how many runs are triggered at once and what’s your work pool concurrency?
Core checks and fixes
1) Verify connectivity from worker pod to Server
- From a worker pod:
# DNS resolution
getent hosts prefect-server.prefect.svc.cluster.local
# API health (cluster-internal service)
curl -sS -m 5 <http://prefect-server.prefect.svc.cluster.local:4200/api/health>
# If using ingress/TLS from inside cluster
curl -sS -m 10 -v <https://your.domain.tld/api/health>
- If the first two fail, prefer using the cluster service FQDN for PREFECT_API_URL instead of the Ingress hostname (unless you require TLS and external routing in-cluster).
- If TLS is involved and you use a custom CA, mount it and point workers to it with PREFECT_API_SSL_CERT_FILE. As a last resort for testing only, you can use PREFECT_API_TLS_INSECURE_SKIP_VERIFY=true.
Relevant docs:
- Self-hosted (Server) guide
- Settings reference
2) Ensure the worker knows the correct API URL
- For in-cluster Server, a common value is:
PREFECT_API_URL=<http://prefect-server.prefect.svc.cluster.local:4200/api>
- For Ingress/TLS:
PREFECT_API_URL=<https://your.domain.tld/api>
Make sure the value is reachable from the worker pod.
3) Add worker healthchecks and sane Kubernetes probes
- Start workers with a healthcheck webserver and probe that endpoint instead of killing the container on transient API hiccups.
- Healthcheck endpoint: /health (HTTP 200 = healthy; 503 = temporarily unhealthy)
- Default port: 8080 (configurable via PREFECT_WORKER_WEBSERVER_PORT)
- Docs: Worker healthchecks
Example container command and probes (adjust to your manifest/Helm):
args:
- prefect
- worker
- start
- -p
- my-work-pool
- --with-healthcheck
env:
- name: PREFECT_API_URL
value: <http://prefect-server.prefect.svc.cluster.local:4200/api>
- name: PREFECT_LOGGING_LEVEL
value: DEBUG
- name: PREFECT_API_REQUEST_TIMEOUT
value: "120"
- name: PREFECT_WORKER_WEBSERVER_PORT
value: "8080"
ports:
- name: health
containerPort: 8080
readinessProbe:
httpGet:
path: /health
port: health
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 6
livenessProbe:
httpGet:
path: /health
port: health
initialDelaySeconds: 60
periodSeconds: 20
timeoutSeconds: 5
failureThreshold: 6
startupProbe:
httpGet:
path: /health
port: health
periodSeconds: 10
failureThreshold: 18
Note: The healthcheck threshold is tied to polling cadence; by default a worker becomes “unhealthy” only after a long lapse, minimizing false restarts.
4) Control concurrency to avoid API/DB overload during spikes
- Set a work pool concurrency limit to prevent thundering herds:
prefect work-pool set-concurrency-limit "my-work-pool" 50
- Consider multiple smaller worker replicas and a per-pod limit (so 1 pod doesn’t try to claim too many runs at once).
- Docs: Work pools
5) Scale and harden Prefect Server
- Run multiple Server replicas behind a ClusterIP/Service.
- Ensure Postgres is healthy; consider PgBouncer if connections spike.Marvin
10/21/2025, 8:40 PMPREFECT_SERVER_DATABASE_TIMEOUT=60
- Allocate sufficient CPU/memory for Server; watch for OOMKills.
- Helm guidance: Server Helm
6) Network policies and DNS
- If using NetworkPolicies, allow worker egress to Server service on 4200/TCP.
- Verify CoreDNS stability; consider bumping PREFECT_API_REQUEST_TIMEOUT to handle slower API/DNS responses during surges.
7) Logging and observability on workers
- Enable debug logging to confirm what’s failing:
PREFECT_LOGGING_LEVEL=DEBUG
- Look for:
- httpx.ConnectError or ConnectTimeout
- Name or service not known (DNS)
- SSL: CERTIFICATE_VERIFY_FAILED (custom CA/TLS)
- 401 Unauthorized (if you’ve enabled auth on self-hosted server)
8) Kubernetes resources
- Check worker pod limits; during large bursts, low memory limits can cause OOMKills before logs flush.
- Set requests to avoid eviction and limits high enough for the polling loop + infra launches.
Useful docs roundup
- Kubernetes worker how-to
- Worker healthchecks
- Self-hosted (Server) guide
- All Prefect settings
Next steps
If you can share:
- Worker logs around the restart
- Worker Deployment/Helm values for env/probes
- Your PREFECT_API_URL and whether you use Ingress/TLS
- Any NetworkPolicies between worker and server namespaces
- Approximate run burst size and current work pool concurrency
…I can tailor exact values (timeouts, probes, concurrency, resource requests) and provide a drop-in manifest/values.yaml tuned for your scale.Jashaul
10/21/2025, 8:52 PMMarvin
10/21/2025, 8:52 PMMarvin
10/21/2025, 8:52 PMJashaul
10/21/2025, 8:53 PMMarvin
10/21/2025, 8:53 PMMarvin
10/21/2025, 8:57 PMkopf warning you see is a side-effect of the worker shutting down due to that error; the root problem is on the Prefect Server side (not the worker networking).
Most likely causes for a 500 on read_deployment
- Server overload during a surge of runs (CPU/memory starved API pod)
- Postgres issues (statement timeouts, connection pool saturation, slow queries on large tables)
- A problematic/corrupted deployment record that triggers a serialization or DB error when read
- Version mismatch between your workers/SDK and Server (less common but possible)
Immediate next steps to isolate
1) Check the Server pod logs at the exact time of the 500 to see the stacktrace
# Find server pod
kubectl get pods -n <server-namespace> -l <http://app.kubernetes.io/name=prefect-server|app.kubernetes.io/name=prefect-server>
# Tail logs around the failure time
kubectl logs -n <server-namespace> <prefect-server-pod-name> --tail=200 -f
This should show the exception that produced the 500 (e.g., DB timeout, validation error, etc.). If you can paste that here, I can pinpoint the fix.
2) Verify the deployment is readable outside the worker
- Try fetching it directly from inside the cluster:
curl -sS -v <http://prefect-server.prefect.svc.cluster.local:4200/api/deployments/37a36818-c460-4e67-abe5-4d45f443b12a>
- From your workstation/CI:
prefect deployment inspect "<flow-name>/<deployment-name>"
If the CLI also fails, it confirms a server-side issue with that deployment endpoint.
3) If the 500 is only for some deployments
- Recreate the problematic deployment and test:
- Re-deploy with flow.from_source(...).deploy(...) to a new name, then schedule a run to see if the worker can read it.
- If a specific record is broken, this is a fast unblock.
Stabilization steps for load spikes
- Put a concurrency limit on your work pool to stop thundering herds while you investigate:
prefect work-pool set-concurrency-limit "my-work-pool" 50
- Run multiple server replicas and give the API pod more resources.
- Ensure Postgres is sized properly and healthy. If you see DB timeouts in server logs, increase the server’s database timeout and consider PgBouncer. If your DB is large, consider retention and routine VACUUM/ANALYZE.
- Increase SDK request timeout on workers during load:
PREFECT_API_REQUEST_TIMEOUT=120
Harden worker pods to avoid crashloops on transient hiccups
- Start workers with healthchecks and probe the local endpoint:
args:
- prefect
- worker
- start
- -p
- my-work-pool
- --with-healthcheck
env:
- name: PREFECT_API_URL
value: <http://prefect-server.prefect.svc.cluster.local:4200/api>
- name: PREFECT_API_REQUEST_TIMEOUT
value: "120"
- name: PREFECT_LOGGING_LEVEL
value: DEBUG
ports:
- name: health
containerPort: 8080
livenessProbe:
httpGet: { path: /health, port: health }
initialDelaySeconds: 60
readinessProbe:
httpGet: { path: /health, port: health }
initialDelaySeconds: 30
startupProbe:
httpGet: { path: /health, port: health }
periodSeconds: 10
failureThreshold: 18
This prevents restarts when the API briefly struggles.
Helpful docs
- Worker healthchecks: Worker healthchecks
- Kubernetes worker guide: Kubernetes worker how-to
- Self-hosted Server and Helm: Self-hosted guide, Server Helm
- Settings reference: Settings reference
- Work pools: Work pools
To help further, could you share:Marvin
10/21/2025, 8:57 PM