Skip to main content

Implementing Liveness and Readiness Probes for Zero-Downtime Deploys

Configure liveness, readiness, and startup probes in Kubernetes to eliminate downtime during rolling deployments and protect production traffic from unhealthy pods.

52 Terms

Overview and What You Will Learn

Without probes, Kubernetes has no way to know whether your application is actually healthy — it only knows if the container process is running. A Node.js API that is running but stuck in an infinite loop, a Spring Boot service that started but cannot connect to its database, or a pod that is ready to receive traffic before its cache is warmed — all of these appear healthy to Kubernetes without probes. This lab walks you through configuring all three probe types to achieve genuinely zero-downtime rolling deployments.

By the end of this guide you will be able to:

  • Configure liveness probes to detect and automatically restart deadlocked or hung containers
  • Configure readiness probes to gate traffic until the application is genuinely ready to serve requests
  • Configure startup probes to protect slow-starting applications from premature liveness kills
  • Design probe endpoints in your application that accurately reflect health state
  • Tune probe timing parameters to balance responsiveness against false-positive restarts

Why This Matters in Production

During a Swiggy deployment at peak dinner hour, a new API version rolled out across 20 pods. The new version had a subtle bug — it started successfully, passed the liveness probe, but the readiness probe was not configured. Kubernetes sent live traffic to pods that had not finished loading their restaurant menu cache — resulting in 8 seconds of 500 errors for every user whose request hit an unready pod before the cache warmed up.

A correctly configured readiness probe would have held all traffic on the old pods until every new pod's cache was fully loaded — zero errors, zero user impact. Probes are the single most impactful configuration for achieving true zero-downtime deployments.

Core Principles

The three probe types and their distinct purposes: STARTUP PROBE LIVENESS PROBE READINESS PROBE ───────────── ────────────── ─────────────── "Has the app finished "Is the app still "Is the app ready starting up?" alive and not hung?" to receive traffic?"

Runs ONCE at startup Runs continuously Runs continuously until it succeeds throughout pod life throughout pod life

On failure → On failure → On failure → kubelet waits and kubelet RESTARTS pod REMOVED from retries (backoff) the container Service endpoints (no restart)

Disables liveness Triggers after Independent of probe while running startup probe liveness probe succeeds

The probe execution order for a new pod: Pod starts │ ▼ startupProbe runs (liveness disabled during this phase) │ ├─► Fails → kubelet waits periodSeconds → retries │ (up to failureThreshold × periodSeconds total) │ └─► Succeeds → startup complete │ ▼ livenessProbe + readinessProbe both begin running in parallel │ │ ▼ ▼ Failure → restart Failure → removed from container Service endpoints

Detailed Step-by-Step Practical Lab

Step 1 — Understand Probe Mechanisms

Kubernetes supports three probe mechanisms — choose based on what your application exposes:

YAML
# Kubernetes makes an HTTP GET to the specified path and port
# Success: HTTP status 200-399
# Failure: HTTP status 400+ or connection refused or timeout
livenessProbe:
httpGet:
path: /healthz # Your health check endpoint
port: 8080
httpHeaders:
- name: Custom-Header
value: kubernetes-probe
# Mechanism 2 — TCP Socket (for non-HTTP services like databases, message queues)
# Kubernetes attempts to open a TCP connection to the port
# Success: connection established
# Failure: connection refused or timeout
livenessProbe:
tcpSocket:
port: 5432 # PostgreSQL port — if TCP accepts, pod is alive
# Mechanism 3 — Exec Command (run a command inside the container)
# Success: command exits with code 0
# Failure: command exits with non-zero code or times out
livenessProbe:
exec:
command:
- pg_isready # PostgreSQL readiness check binary
- -U
- postgres
- -d
- zerodha_trading
Step 2 — Configure a Complete Probe Suite for a Node.js API
YAML
# deployment-api-probes.yaml — full probe configuration for Swiggy order API
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-api
namespace: production
spec:
replicas: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 2 # Allow 2 extra pods during update
maxUnavailable: 0 # Never take a pod down before a new one is ready
# This is what makes rolling updates truly zero-downtime
selector:
matchLabels:
app: order-api
template:
metadata:
labels:
app: order-api
spec:
containers:
- name: order-api
image: registry.swiggy.in/order-api:v6.2.1
ports:
- containerPort: 8080
resources:
requests:
cpu: "250m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"
# STARTUP PROBE — protects slow-starting apps from liveness kills
# Total startup budget: 30 attempts × 10s = 300s (5 minutes maximum)
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 30 # Allow up to 5 minutes for startup
periodSeconds: 10 # Check every 10 seconds
successThreshold: 1 # One success is enough
# LIVENESS PROBE — detects hung or deadlocked application
# Only runs AFTER startupProbe succeeds
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 0 # startupProbe handles the delay — set to 0
periodSeconds: 15 # Check every 15 seconds
timeoutSeconds: 5 # Fail if no response within 5 seconds
failureThreshold: 3 # Restart after 3 consecutive failures (45s)
successThreshold: 1
# READINESS PROBE — gates traffic until app is truly ready
readinessProbe:
httpGet:
path: /ready
port: 8080 # Different endpoint from liveness
initialDelaySeconds: 5
periodSeconds: 5 # Check every 5 seconds — faster than liveness
timeoutSeconds: 3
failureThreshold: 3 # Remove from endpoints after 3 failures (15s)
successThreshold: 2 # Require 2 consecutive successes before adding back
Remember

Use maxUnavailable: 0 combined with maxSurge: 1 or higher for zero-downtime deployments. This forces Kubernetes to bring up new pods and wait for them to pass readiness before terminating old ones. Without this, Kubernetes may terminate old pods while new ones are still starting.

Step 3 — Implement Correct Health Endpoints in Your Application

The probe endpoint must accurately reflect the application's actual health — not just return 200 unconditionally:

JAVASCRIPT
// health.js — Node.js health endpoints for Swiggy order API
const express = require('express');
const router = express.Router();
// LIVENESS endpoint — am I alive and not deadlocked?
// Should only check things that would require a restart to fix
router.get('/healthz', async (req, res) => {
try {
// Check if the event loop is responsive (not deadlocked)
// Check if critical in-process state is valid
const memUsage = process.memoryUsage();
const heapUsedPercent = memUsage.heapUsed / memUsage.heapTotal;
if (heapUsedPercent > 0.95) {
// Heap is 95%+ full — restart before OOMKill hits
return res.status(503).json({
reason: 'heap_pressure',
heapUsedPercent
});
}
res.status(200).json({ status: 'alive', uptime: process.uptime() });
} catch (err) {
res.status(503).json({ status: 'unhealthy', error: err.message });
}
});
// READINESS endpoint — am I ready to serve traffic?
// Check all dependencies the application needs to function
router.get('/ready', async (req, res) => {
const checks = {};
try {
// Check database connectivity
await db.query('SELECT 1');
checks.database = 'ok';
} catch (err) {
checks.database = 'failed';
}
try {
// Check Redis connectivity
await redis.ping();
checks.redis = 'ok';
} catch (err) {
checks.redis = 'failed';
}
try {
// Check that restaurant menu cache is warmed (Swiggy-specific)
const cacheReady = await menuCache.isWarm();
checks.menuCache = cacheReady ? 'ok' : 'warming';
} catch (err) {
checks.menuCache = 'failed';
}
const allReady = Object.values(checks).every(v => v === 'ok');
res.status(allReady ? 200 : 503).json({
checks
});
});
module.exports = router;
Security

Never expose sensitive information in health endpoints — database connection strings, internal IPs, or stack traces. Health endpoints are often public-facing. Return only status strings and boolean indicators, never raw error objects.

Step 4 — Configure Probes for a Spring Boot Service

Spring Boot has built-in Actuator health endpoints that map perfectly to Kubernetes probes:

YAML
# application.yaml — Spring Boot Actuator probe configuration
management:
endpoint:
health:
probes:
enabled: true # Enable /actuator/health/liveness and /readiness
show-details: never # Never expose internals in health response
endpoints:
web:
exposure:
include: health, info, prometheus
health:
livenessstate:
enabled: true
readinessstate:
enabled: true
db:
enabled: true # Check database connectivity for readiness
redis:
enabled: true # Check Redis for readiness
YAML
# deployment-springboot.yaml — probe config for Razorpay payments service (Spring Boot)
startupProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
failureThreshold: 60 # Spring Boot with heavy migrations needs up to 10 minutes
periodSeconds: 10
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
periodSeconds: 15
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
successThreshold: 1
Tip

Spring Boot's /actuator/health/liveness only checks the application state (not external dependencies), while /actuator/health/readiness checks all configured health indicators including database and Redis. This separation maps perfectly to the Kubernetes liveness/readiness model.

Step 5 — Configure Probes for TCP Services (Databases, Kafka)
YAML
# StatefulSet probes for PostgreSQL using exec mechanism
livenessProbe:
exec:
command:
- pg_isready
- -U
- postgres
- -h
- localhost
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 6 # Allow 6 failures (60s) before restart — DB restarts are slow
readinessProbe:
exec:
command:
- pg_isready
- -U
- postgres
- -h
- localhost
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3

Resources

Velero vs etcd Snapshot: Not a Real Choice

Velero vs etcd Snapshot: Not a Real Choice

Velero and etcd snapshots protect different layers of a cluster, not the same thing. Here's what each covers and why production DR needs both.

5 min read•Aug 2026
Istio Ambient vs Linkerd in 2026

Istio Ambient vs Linkerd in 2026

Istio Ambient killed the sidecar-tax argument. The real 2026 decision is waypoint topology and Buoyant's licensing shift, not features vs simplicity.

5 min read•Aug 2026
Nginx Ingress vs Traefik vs Gateway API in 2026

Nginx Ingress vs Traefik vs Gateway API in 2026

Ingress-nginx retired in March 2026. Here's how Traefik and the Gateway API actually compare as replacements — and why "just swap it" is the wrong frame.

5 min read•Aug 2026
OPA Gatekeeper vs Kyverno: Policy Engine in 2026

OPA Gatekeeper vs Kyverno: Policy Engine in 2026

OPA Gatekeeper vs Kyverno compared for 2026 - Rego vs YAML, mutation maturity, operational overhead, and which policy engine fits your cluster.

5 min read•Aug 2026
Helm vs Kustomize in 2026: Templating vs Patching

Helm vs Kustomize in 2026: Templating vs Patching

Helm vs Kustomize compared for 2026 - templating vs patching, Helm 4's new features, and why most production teams end up running both.

5 min read•Aug 2026
Prometheus vs Datadog vs New Relic: Real Costs

Prometheus vs Datadog vs New Relic: Real Costs

Prometheus, Datadog, and New Relic compared for 2026 - real pricing at scale, hidden cost drivers, and which fits a Kubernetes-heavy stack.

5 min read•Aug 2026
Cluster Autoscaler vs Karpenter for EKS in 2026

Cluster Autoscaler vs Karpenter for EKS in 2026

Cluster Autoscaler vs Karpenter compared for EKS in 2026 - provisioning speed, bin-packing, cloud support, and when each is the right default.

5 min read•Aug 2026
GKE vs EKS vs AKS in 2026: Which Fits Your Team?

GKE vs EKS vs AKS in 2026: Which Fits Your Team?

GKE, EKS, and AKS compared for 2026 - control plane pricing, Autopilot vs Karpenter vs Node Auto Provisioning, and which platform actually fits your team.

5 min read•Aug 2026
K3s vs K8s vs MicroK8s in 2026

K3s vs K8s vs MicroK8s in 2026

K3s, full Kubernetes, and MicroK8s compared for 2026 - resource footprint, production readiness, and which fits edge, homelab, or cloud workloads.

5 min read•Aug 2026
Canary Deployments with Argo Rollouts & Flagger

Canary Deployments with Argo Rollouts & Flagger

Ship to 5% of users first and auto-rollback in minutes — a hands-on guide to canary deployments with Argo Rollouts and Flagger on Kubernetes.

5 min read•Jun 2026
OpenTelemetry Explained: Metrics, Logs, Traces

OpenTelemetry Explained: Metrics, Logs, Traces

OpenTelemetry unifies metrics, logs, and traces under one open standard — how it works, what it replaces, and how to instrument a service in 20 minutes.

5 min read•Jun 2026
Kubernetes Cost Optimization Without Breaking SLOs

Kubernetes Cost Optimization Without Breaking SLOs

Average Kubernetes CPU utilization across production clusters is 8%. Here is the complete 2026 playbook for cutting cloud spend without touching your SLOs.

5 min read•Jun 2026
ArgoCD vs FluxCD: GitOps for Kubernetes in 2026

ArgoCD vs FluxCD: GitOps for Kubernetes in 2026

ArgoCD and FluxCD are the two dominant GitOps engines for Kubernetes in 2026 — this breakdown tells you exactly which one to pick and why.

10 min read•Jun 2026

Explore More in Kubernetes Workload Management

All 6 Topics

Frequently Asked Questions

Is Implementing Liveness and Readiness Probes for Zero-Downtime Deploys free to learn on DevOps Network?

Yes - this topic, like everything on DevOps Network, is 100% free with no paywall or sign-up gate.

What does the Implementing Liveness and Readiness Probes for Zero-Downtime Deploys topic cover?

Configure liveness, readiness, and startup probes in Kubernetes to eliminate downtime during rolling deployments and protect production traffic from unhealthy pods.