Lesson 10 · Senior containers & local dev

Readiness, healthchecks, and startup order

The senior version of depends_on: what failures you are actually preventing, and why one gate can be smarter than twenty-five little guesses.

Your win: explain why started is not ready, what wait-for-it-service is really protecting against, and how to reason about readiness gates without cargo-culting them.

In plain English Plain English: a container can be alive long before it is useful, and local stacks fail when you confuse those two states.

The easy answer vs the useful answer

The easy answer is: “use healthchecks.” The useful answer is: “use a health signal that matches the failure you are trying to avoid.” That is the senior shift in this lesson.

If a dependency has started but cannot actually serve requests yet, the stack still breaks. So the real topic is not startup order in the abstract. It is startup order tied to concrete failure modes.

The senior rule A readiness gate is only good if you can name the failure it is preventing.

Why startup races feel random when they are not

Most local-boot failures are not “Docker is flaky.” They are dependency timing failures: Postgres has not accepted connections yet, Unleash is not healthy yet, or another service assumes an endpoint exists before it actually does.

Once you learn to see those as dependency races, the whole topic becomes calmer. You stop staring at “container is up” and start asking “is the dependency genuinely usable yet?”

Why this repo uses one gate container

Instead of putting bespoke readiness logic on every application service, the repo centralizes infra readiness in wait-for-it-service. That gate checks DB and Unleash health, and the application services wait on that one shared signal before starting.

The design is not magical. It is just legible. One place defines the infra-ready contract, and the rest of the service stack can depend on it.

Anchor — where to look local/docker-compose.service.macos.yaml defines wait-for-it-service and the condition: service_healthy dependency chain. local/docker-compose.infra.yaml shows the DB and other infra-side health signals that make the gate meaningful.
Why this is a good interview topic Interviewers often ask about healthchecks as if the answer were a command snippet. The stronger answer is to explain the race, the readiness signal, and why “started” is too weak for the dependency you care about.
Common mistake Copying healthchecks mechanically without asking whether they represent real readiness or only a process that happens to be alive.
Read this next

Compose startup order docs

This is the official explanation of the started-vs-ready distinction. Read it, then come back and notice how the repo turns that general rule into one concrete gate pattern.

Docker — Control startup order
local/docker-compose.service.macos.yaml

Check yourself (from memory)

Q1. The best reason to add a readiness gate is…

Good readiness checks are tied to concrete failure modes, not aesthetics.
What is the senior way to justify a readiness gate?
recall, then click to reveal
Name the exact dependency race or false-start failure it prevents, then show that the health signal actually corresponds to usable readiness.
Want me to walk through which failures wait-for-it-service catches — and which it does not? Ask me.

Sources. Compose startup-order docs; in-repo compose files.