Chaturmind
LearnDSASystem DesignDevOpsEngineering GrowthBlog
Start learning
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML
  • DevOps
  • Engineering Growth

Company

  • Blog
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.


← Spring Boot REST API Development

Spring Boot Basics

  • What is Spring Boot?
  • Dependency Injection
  • Building REST Controllers

Validation & Error Handling

  • Bean Validation with @Valid
  • Global Exception Handling

Spring Framework Internals

  • IoC Container Fundamentals
  • Bean Lifecycle In Detail
  • Component Scanning & Configuration
  • Auto-Configuration Mechanism
  • Spring AOP
  • @Transactional Deep Dive

Microservices Architecture

  • Monolith to Microservices Decomposition
  • API Gateway
  • Service Discovery
  • Inter-Service Communication Choices
  • Event-Driven Architecture Patterns
  • Messaging Technology Choices

Resilience Patterns

  • Configuration Management
  • Circuit Breaker Pattern
  • Retry & Backoff Strategies
  • Bulkhead & Rate Limiting
  • Timeout Strategy
  • Why Microservices Fail

Distributed Data & Consistency Patterns

  • Two-Phase Commit
  • Saga Pattern
  • Outbox Pattern
  • Eventual Consistency Design
  • CQRS Basics
  • CAP Theorem

Observability & Operations

  • Centralized Logging
  • Distributed Tracing
  • Metrics & Monitoring
  • Alerting Strategy
  • Health Checks

Payment Systems

  • Payment — Requirements
  • Payment — Core Flow
  • Payment — Idempotency Implementation
  • Payment — Failure Handling & Reconciliation
  • Payment — Security

Order Management System

  • OMS — Requirements
  • OMS — State Machine Design
Chaturmind
← Spring Boot REST API Development

Spring Boot Basics

  • What is Spring Boot?
  • Dependency Injection
  • Building REST Controllers

Validation & Error Handling

  • Bean Validation with @Valid
  • Global Exception Handling

Spring Framework Internals

  • IoC Container Fundamentals
  • Bean Lifecycle In Detail
  • Component Scanning & Configuration
  • Auto-Configuration Mechanism
  • Spring AOP
  • @Transactional Deep Dive

Microservices Architecture

  • Monolith to Microservices Decomposition
  • API Gateway
  • Service Discovery
  • Inter-Service Communication Choices
  • Event-Driven Architecture Patterns
  • Messaging Technology Choices

Resilience Patterns

  • Configuration Management
  • Circuit Breaker Pattern
  • Retry & Backoff Strategies
  • Bulkhead & Rate Limiting
  • Timeout Strategy
  • Why Microservices Fail

Distributed Data & Consistency Patterns

  • Two-Phase Commit
  • Saga Pattern
  • Outbox Pattern
  • Eventual Consistency Design
  • CQRS Basics
  • CAP Theorem

Observability & Operations

  • Centralized Logging
  • Distributed Tracing
  • Metrics & Monitoring
  • Alerting Strategy
  • Health Checks

Payment Systems

  • Payment — Requirements
  • Payment — Core Flow
  • Payment — Idempotency Implementation
  • Payment — Failure Handling & Reconciliation
  • Payment — Security

Order Management System

  • OMS — Requirements
  • OMS — State Machine Design
HomeLearnSpring BootSpring Boot REST API DevelopmentObservability & Operations
✓ FreeIntermediate· 6 min read

Health Checks

Liveness vs readiness precisely, Spring Boot Actuator health groups and custom HealthIndicators, and whether a dependency outage should make a service unready or degrade gracefully.

Published September 23, 2026


Health Checks

Liveness: is the process alive, or should it be restarted

A liveness check answers one narrow question: is this process fundamentally alive and responsive, or has it entered a broken state (deadlocked, hung) that only a restart can fix? A liveness check failing tells the orchestrator (Kubernetes, most commonly) to kill and restart the instance — it should be a minimal check (is the JVM even responding to a basic ping), not one that depends on external systems, since a liveness check failing due to a downstream dependency being down would cause the orchestrator to needlessly restart a perfectly healthy process, achieving nothing.

Readiness: can this instance currently serve traffic

A readiness check answers a different question: is this specific instance ready to receive new traffic right now? A readiness check failing tells the orchestrator/load balancer to remove this instance from rotation temporarily (not restart it) — appropriate during startup (before all beans/connections are initialized), during a graceful shutdown drain, or when a critical dependency is genuinely unreachable and this instance can't usefully serve requests at the moment.

This liveness/readiness distinction is exactly the gap in Why Microservices Fail's "health checks report green but customers report outages" scenario — a shallow check that only implements liveness (process is alive) tells you nothing about whether the instance can actually serve real requests; readiness is the check that's supposed to answer that, and its absence (or shallowness) is precisely the common root cause.

Spring Boot Actuator health groups and custom indicators

@Component
class DatabaseHealthIndicator implements HealthIndicator {
    public Health health() {
        try {
            jdbcTemplate.execute("SELECT 1"); // a real, minimal query against the actual dependency
            return Health.up().build();
        } catch (Exception e) {
            return Health.down(e).build();
        }
    }
}
management:
  endpoint:
    health:
      group:
        liveness:
          include: livenessState
        readiness:
          include: readinessState, db, diskSpace # readiness ADDITIONALLY checks real dependencies

Spring Boot Actuator supports health groups, letting /actuator/health/liveness and /actuator/health/readiness expose genuinely different checks — liveness stays minimal (just livenessState), readiness includes custom HealthIndicator implementations (like the database check above) that actually exercise the dependency paths real traffic needs. A HealthIndicator is the extension point for adding a check for any dependency (a message broker connection, an external API, disk space) that matters for whether this instance can genuinely serve traffic.

Should a dependency outage make the service unready, or degrade gracefully?

This is a genuine, case-by-case design decision, not a fixed rule:

  • Mark unready: appropriate when the dependency is essential — a service that literally cannot function without its primary database has no meaningful "degraded" mode; removing it from rotation (readiness failing) is the correct, honest response, letting the load balancer route traffic to healthier instances (or trigger broader alerting if ALL instances report unready).
  • Degrade gracefully: appropriate when the dependency is non-essential to the core function — a product page that can't reach a "customers also bought" recommendation service should still render the product itself (per PremiumGate-style graceful degradation covered earlier in Circuit Breaker Pattern's fallback discussion), not go fully unready and stop serving traffic entirely over a non-critical feature being unavailable.

Naming this distinction explicitly per dependency (not a blanket policy for every dependency a service has) is the mature answer — some dependencies genuinely warrant unready, others clearly warrant graceful degradation, and treating every dependency identically in either direction is a real design miss.

Follow-up questions this topic invites — and their answers

Q: What happens if a liveness check DOES depend on an external system and that system goes down? A: Every instance would simultaneously report unhealthy and get restarted by the orchestrator — potentially in a loop, if the external system stays down and the restarted instances immediately fail liveness again — a real, damaging failure mode, which is exactly why liveness checks are deliberately kept minimal and dependency-free, restricted purely to 'is this process itself functioning.'

Q: How does readiness interact with graceful shutdown? A: A service receiving a shutdown signal should immediately flip readiness to false (removing itself from the load balancer's rotation) BEFORE actually stopping — this drains in-flight traffic away first, avoiding requests being routed to an instance that's about to terminate, a standard and important part of a zero-downtime deployment process.

Q: Could a HealthIndicator itself become a performance problem if checked too frequently? A: Yes — a readiness check that runs an expensive query against a database on every single orchestrator health-check poll (which might happen every few seconds) adds real, avoidable load; a common mitigation is caching the health-check result for a short interval (a few seconds) rather than re-executing the full dependency check on every single poll.

Q: Is 'degrade gracefully' always the safer choice, given it avoids taking an instance out of rotation? A: No — degrading gracefully when a dependency is actually ESSENTIAL means serving requests that will fail anyway (or worse, produce silently wrong results), which is worse than honestly reporting unready and letting traffic route elsewhere; the choice needs to match whether the dependency is genuinely optional for that specific request path, not default to whichever choice looks less disruptive.

Previous

Alerting Strategy

Next

Payment — Requirements

AI Tutor

Lesson: Health Checks

Quick actions

AI responses can be inaccurate. Verify critical information.