9.3.3.4 Depends Readiness Limits
A focused guide to Depends Readiness Limits, connecting core concepts with practical Docker and container operations.
Depends readiness limits describe the ways even a well-configured, health-condition-based depends_on relationship can still fall short of guaranteeing full readiness, since a health check passing at one moment doesn't guarantee continued availability, and not every kind of readiness can be fully captured by a simple health check.
A Health Check Passing Doesn't Guarantee Continued Availability
A dependency reported as healthy at the moment a dependent service starts could still become unavailable shortly afterward — due to a crash, a network blip, or simply being restarted — a scenario depends_on alone has no ongoing mechanism to address.
services:
api:
depends_on:
db:
condition: service_healthy
db:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
This condition only governs api's initial startup — it provides no protection against db becoming unavailable at some later point during api's ongoing operation.
Why Some Forms of Readiness Are Difficult to Capture in a Simple Check
A health check that confirms a process is responding doesn't necessarily confirm every aspect of genuine readiness — a database might report healthy while still completing a lengthy startup migration, for instance, depending on exactly what the health check actually verifies.
docker compose exec db pg_isready
This confirms the database is accepting connections, but says nothing about whether application-level migrations or other initialization steps have actually completed.
Why Application-Level Resilience Remains Necessary
Because depends_on only addresses initial startup sequencing, not ongoing availability, an application's own retry and reconnection logic for its actual dependency connections remains an essential complement, handling availability issues that arise after the initial startup sequence has already completed.
for attempt in range(5):
try:
connect_to_database()
break
except ConnectionError:
time.sleep(2)
Why Understanding Depends Readiness Limits Matters
Recognizing exactly what depends_on does and doesn't guarantee — initial startup sequencing, not ongoing availability — clarifies why robust applications still need their own resilience logic, rather than relying entirely on Compose's startup coordination to handle every dependency-related failure scenario.