skip to content

Startup & Shutdown Lifecycle

Boot order from settings to socket bind, startup hooks and eager checks, readiness and liveness signals, and shutdown that drains in-flight requests. Asked because bad shutdown drops requests.

on this pageshow

questions

5

In a server-side web framework, what happens in what order between process start and the first accepted request?

level: juniorimportance: must knowfreq 70%

answer

  1. boot is a sequence, not one step
  2. each phase feeds the next
  3. settings, then graph, then routes
  4. bind the socket last
  5. ready is signalled after bind

basics

~20 s

Settings are read and validated first, then the object graph is built, then routes and middleware are registered, and only then is the listening socket bound. Binding last keeps traffic out until the application can serve it.

solid answer

~40 s

Boot runs in a fixed order because each phase consumes what the previous one produced. First the framework loads and validates **settings**; second it builds the **object graph** — the singletons, factories and pooled resources the handlers depend on; third it **registers routes and the middleware chain**, turning declarations into a matching structure; fourth it runs any **startup hooks**, which is where eager checks and cache warm-up belong; last it **binds the listening socket** and starts accepting. Binding last is the point of the whole ordering: a socket opened before the graph exists accepts connections the process cannot serve, so clients get errors instead of a clean refusal that a router can retry elsewhere. Readiness is signalled last of all, only once the bind has succeeded.

go deeper

for a junior

Memorise the sequence and be able to recite it: settings, object graph, routes and middleware, startup hooks, bind, ready. If you only remember one rule, remember that the listening socket is opened last.

for a middle

Explain why each phase depends on the previous one, and what a failure in each looks like to an operator. Be able to contrast eager graph resolution at boot with lazy resolution on first use.

for a senior

Talk about the deploy window: what a caller sees when an instance binds early, why a warm-up after the bind shows as a latency spike on every release, and how you keep boot failures loud instead of intermittent.

for a principal

Frame boot ordering as a contract with everything upstream. Decide how much verification belongs in the sequence at all, since every eager phase trades a faster failure signal for a longer, more fragile path to a serving process.

A server-side web framework does not begin serving the instant the process starts. Between process start and the first accepted request there is a **bootstrap sequence**, and its ordering is not a style choice: each phase produces something the next phase consumes, and the phase that makes the process *reachable* is deliberately last. ## The phases, in order 1. **Load and validate settings.** The framework assembles the effective configuration and binds it into typed settings objects. Everything later depends on it — a pool size, a listen port, a feature switch — so it has to exist before anything is constructed. 2. **Build the object graph.** The container (or hand-written wiring code) instantiates the singletons, factories and shared resources the handlers will use: data-access components, clients for other services, caches, serializers. This is where a missing registration or a wiring cycle surfaces. 3. **Register routes and the middleware chain.** Route declarations are compiled into a matching structure — typically a tree or table keyed by method and path template — and the middleware chain is assembled in declaration order. Doing this once at boot is what makes per-request matching cheap. 4. **Run startup hooks.** User code that must run after wiring and before traffic: eager checks, schema or migration verification, cache warm-up, background schedulers. 5. **Bind the listening socket and accept.** The process now occupies the port; connections are accepted and dispatched into the chain built in step 3. 6. **Signal readiness.** The readiness state flips to *ready* only after the bind succeeds, so whatever routes traffic sends the first request to a process that can serve it. ## Why binding comes last An open port is a promise. A router, a load balancer or a client retry loop treats a successful connection as “this instance can serve me”, and it treats a refused connection as “try another instance”. If the socket is bound before the graph is built, that promise is false: connections succeed and then fail, hang, or return a server error, and the caller has already spent its retry on this instance. Binding last converts a whole class of confusing partial-availability bugs into the simplest possible signal — the port simply is not there yet. ## What each phase fails on | Phase | Typical failure | How it should present | |---|---|---| | Settings | missing or unparseable value, failed validation | process exits at boot with the offending key named | | Object graph | unresolvable dependency, wiring cycle | process exits at boot, before any port is open | | Route registration | duplicate or conflicting declaration | boot-time error, not a surprise at request time | | Startup hooks | an eager check finds a broken dependency | boot failure, or a deliberate start-degraded decision | | Bind | port already in use, insufficient privilege | process exits; nothing was serving anyway | ## Where frameworks differ The phase list is near-universal; how strictly it is enforced is not. Some frameworks resolve the entire object graph eagerly at boot, so a wiring mistake is a boot crash; others resolve lazily on first use, so the same mistake becomes a failed request minutes later, and they usually offer an opt-in “verify the graph now” switch to recover the eager behaviour. Likewise some frameworks make the bind an explicit, final call in your own startup code, while others own the whole sequence and give you only hook points inside it. The consequence is the same either way: know which style you are on, because it decides whether a misconfiguration shows up in the deploy log or in a user's request. ## Symptoms when the order is broken - **Requests arrive before wiring finishes** — intermittent server errors only during the first seconds after a deploy, impossible to reproduce afterwards. - **Readiness true before the bind** — traffic is routed to a process whose port is still closed, producing connection errors the instance never logs. - **Work in a static initializer instead of a startup hook** — failures happen at an unpredictable point with no framework context and no clean way to abort the boot. - **Long warm-up after the bind** — the first requests pay for cache filling and connection establishment, showing as a latency spike on every deploy. - **Routes registered conditionally at request time** — the matching structure differs between instances, so behaviour depends on which one you hit. The practical takeaway for a candidate: describe the sequence as *settings → graph → routes → hooks → bind → ready*, and be able to say why the reachability step is deliberately at the end.

  • In development, a framework can restart or reload the application on a code change — what does that actually redo?
    It re-runs the same boot phases against a fresh object graph: settings are re-read, components are rebuilt, routes are re-registered. The listening socket is usually kept or rebound quickly so the developer's browser session survives. That is also why a reload hides state you thought was persistent, and why a hook with a slow eager check makes every edit painful.
  • Why is route registration done once at boot rather than resolved per request?
    Registration compiles declarations into a matching structure, so a request costs one lookup instead of re-reading declarations. It also lets conflicts — two declarations claiming the same method and path template — fail at boot rather than being discovered by whichever request happens to hit them.
  • What is the risk of doing work in static or module-level initialization instead of a startup hook?
    That code runs when the type or module is first touched, which is outside the framework's ordering. It can execute before settings are bound, it has no clean way to abort the boot with a useful message, and its failure surfaces as an initialization error far from the cause.

saying these in an interview costs you the question

  • Says the port is bound first so the instance looks available sooner
  • Thinks readiness can be reported before the socket is bound
  • Assumes settings are only read when a handler first needs them
  • Believes a wiring mistake can only ever surface as a failed request
  • Cannot name any phase between process start and the first request
open as a page

What is a startup hook in a web framework, and what belongs in an eager check that runs there?

level: middleimportance: must knowfreq 58%

basics

~20 s

A startup hook is a callback the framework runs after wiring and before it accepts traffic. Eager checks belong there - validate settings, resolve critical components, verify required resources - so a broken process fails at boot, not at the first request.

open as a page

A running web service is asked to stop while requests are in flight — how should its shutdown proceed?

level: seniorimportance: must knowfreq 64%

basics

~20 s

Flip readiness to false first and keep serving for a moment so routers stop sending work; then stop accepting new connections; then let in-flight requests finish under a deadline; then release resources in reverse startup order and exit.

open as a page

What should a web service's readiness signal report between the socket bind and the end of startup warm-up?

level: middleimportance: should knowfreq 46%

basics

~20 s

Not ready. An open port only means the process is listening. Readiness should flip true at the very end of startup, once warm-up and eager checks have finished, so nothing routes traffic to an instance that cannot serve it well.

open as a page

When a whole fleet must restart during a dependency outage, how should its startup sequence and readiness be designed?

level: principalimportance: should knowfreq 38%

basics

~20 s

Design the boot path to complete without its dependencies: verify settings and wiring eagerly, but retry reachability in the background while reporting not-ready. A service that exits when a dependency is down cannot rejoin on its own.

open as a page