Prometheus Error Guide: 'not ready to serve traffic' — Fix Startup 503
Fix Prometheus 'not ready to serve traffic' 503 errors: diagnose slow WAL replay, TSDB startup, readiness probes, and rollout timing so queries resume cleanly.
- #prometheus
- #monitoring
- #troubleshooting
- #errors
Fixing errors like this? Get 500 free DevOps AI prompts
500 copy-paste AI prompts for the stack you actually run — one PDF, free.
Overview
Prometheus returns this body with an HTTP 503 from every endpoint — the UI, /api/v1/query, /federate — while it is still starting up and not yet ready to answer:
Prometheus is not ready to serve traffic. Call /-/ready when ready.
Grafana panels backed by this Prometheus show Bad Gateway or 503, and Kubernetes may restart the pod if the readiness/liveness probe times out. This is expected briefly on every start, but when it persists it usually means WAL replay or TSDB startup is taking far longer than the probe budget, creating a crash loop that never lets Prometheus finish coming up.
Symptoms
curl http://prometheus:9090/-/readyreturns503with the “not ready” body.- Queries and dashboards fail with
503/Bad Gatewayright after a restart or deploy. - Logs show
Replaying WAL,Loading WAL, orTSDB startednever being reached before a restart. - In Kubernetes, the pod cycles
Running→Restartingas the readiness probe fails repeatedly. prometheus_readyis0or the metric is unreachable during the window.
Common Root Causes
- Slow WAL replay — a large write-ahead log takes minutes to replay on startup, exceeding the readiness probe timeout.
- Readiness probe too strict —
initialDelaySeconds/failureThresholdtoo low for the data volume, so Kubernetes kills the pod mid-replay. - Huge head block / high series churn — startup must reconstruct a large in-memory head.
- Slow storage — the data volume (network disk) has low IOPS, dragging out replay and mmap.
- Corrupt or oversized WAL — replay stalls or repeatedly restarts on a bad segment.
- Cold start after unclean shutdown — an OOMKill or
SIGKILLleft a large WAL that must be fully replayed.
Diagnostic Workflow
Check readiness and watch the startup logs for the replay phase:
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:9090/-/ready
journalctl -u prometheus --since '10 min ago' | grep -iE 'wal|replay|tsdb|ready'
In Kubernetes, confirm whether the probe is killing the pod before it finishes:
kubectl -n monitoring describe pod prometheus-0 | grep -A5 -iE 'readiness|liveness|last state|restart'
Loosen the readiness probe so replay can complete (raise the failure budget, not the frequency):
readinessProbe:
httpGet: { path: /-/ready, port: web }
initialDelaySeconds: 30
periodSeconds: 10
failureThreshold: 60 # ~10 min of grace for large WAL replay
startupProbe:
httpGet: { path: /-/ready, port: web }
periodSeconds: 15
failureThreshold: 80
Once it is up, quantify replay cost so you can size probes correctly next time:
prometheus_tsdb_wal_replay_duration_seconds
prometheus_tsdb_head_series
rate(prometheus_tsdb_head_chunks_created_total[5m])
Example Root Cause Analysis
After an OOMKill, a Prometheus pod entered a crash loop, always logging Replaying WAL and then restarting. The readiness probe had failureThreshold: 6 at periodSeconds: 10 — only 60 seconds of grace — but the WAL for ~4M active series took roughly 7 minutes to replay on the network-backed volume.
Kubernetes killed the pod at 60s, every time, so replay never finished. Raising the readiness failureThreshold and adding a startupProbe with a generous budget let replay complete; prometheus_tsdb_wal_replay_duration_seconds recorded ~410s. The durable fix was also to reduce head series (cardinality controls) and move to a higher-IOPS disk so future replays finish in under two minutes.
Prevention Best Practices
- Give Prometheus a
startupProbewith a budget larger than your worst-case WAL replay time, so liveness/readiness never kill a healthy-but-replaying pod. - Track
prometheus_tsdb_wal_replay_duration_secondsand alert when it trends up — it predicts future startup pain. - Control head cardinality; fewer active series means faster replay and startup.
- Use storage with adequate IOPS for the data volume; replay is I/O bound.
- Prevent OOMKills (memory limits + cardinality control) so restarts aren’t forced with a large unclean WAL.
Quick Command Reference
# Readiness + startup logs
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:9090/-/ready
journalctl -u prometheus --since '10 min ago' | grep -iE 'wal|replay|ready'
# Kubernetes probe / restart inspection
kubectl -n monitoring describe pod prometheus-0 | grep -A5 -iE 'readiness|restart'
prometheus_tsdb_wal_replay_duration_seconds
prometheus_tsdb_head_series
Conclusion
“not ready to serve traffic” is normal for a few seconds at startup and a problem only when it persists — almost always because WAL replay outlasts a too-strict readiness probe, creating a crash loop. Give replay enough grace with a startupProbe, measure replay duration, and attack the root cause (cardinality, disk IOPS, OOMKills) so startups stay short.
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.