Crux Read real handler, middleware, streaming, and deadline-propagation snippets, predict the lifecycle failure, and pick the highest-leverage fix a senior would make first.
Your altitude — climbing toward senior
ZeroJuniorMiddleSenior
You are at senior altitude — in orbit
◷ 14 min
Lifecycle bugs are diagnosed in the code on the hot path and in the order things are wired. Read each snippet, predict where it fails in production, and choose the fix a senior engineer reaches for first.
Goal
Practise the loop you run in every lifecycle incident: read the wiring or the hot path, predict the stop that breaks, and reach for the highest-leverage fix — order, backpressure, serialization, or a propagated deadline.
Snippet 1 — the middleware chain
const app = express();app.use(express.json()); // body parser, no size limitapp.post("/admin/wipe", wipeHandler); // <-- registered hereapp.use(rateLimit({ max: 100 })); // rate limiterapp.use(requireAuth); // auth: 401 if no valid tokenapp.use(errorHandler); // catches downstream throws
Quiz
Completed
Which problems does this registration order create, and what is the fix?
Heads-up Express runs middleware in registration order, and a route that responds short-circuits the rest. Anything registered after the route never runs for that route — so auth, rate limit, and the error handler are all bypassed here.
Heads-up Per-user limiting is a refinement, but the load-bearing bug is that the route is registered before all three protective layers, so none of them run for it at all. Ordering relative to the route is the defect.
Heads-up Express error handlers are matched by their 4-arg signature and must be registered LAST (outermost in the onion) to catch throws from everything downstream. Putting it first means nothing downstream has run yet, so it catches nothing.
Snippet 2 — the streaming export
function exportCSV(rows, res) { res.setHeader("Transfer-Encoding", "chunked"); for (const row of rows) { res.write(toCSVLine(row)); // return value ignored } res.end();}
Quiz
Completed
This passes every test but OOMs in production under one slow client. What is the bug and the correct rewrite?
Heads-up Chunked is correct for a streamed body of unknown total size; setting Content-Length would force buffering the whole export first. The bug is ignoring the write() backpressure signal, not the framing.
Heads-up res.end() runs after the loop completes, so it does not truncate. The defect is that the loop never honours write() returning false, so memory grows unbounded under a slow consumer.
Heads-up Raising the heap only delays the OOM; the growth is unbounded because production is decoupled from the client's read rate. Honouring backpressure keeps memory flat at ~the high-water mark regardless of allocation.
As the orders table grows, this endpoint degrades and occasionally stalls all other requests. Which two lifecycle stops are at fault, and what is the fix?
Heads-up An unbounded SELECT is itself a Handle-stage problem: it pulls more rows as the table grows, which is what then feeds the oversized serialization. Both stops compound; capping the query is the upstream fix.
Heads-up Table size has no effect on the accept queue, which bounds pending connections. The degradation tracks result-set size, which points at the query (Handle) and serialization (Serialize), not connection acceptance.
Heads-up 204 means no body, which would break the endpoint's contract — clients need the orders. The fix is to bound and paginate the body, not to drop it; the status code is correct for a successful read.
Snippet 4 — the deadline that is not propagated
async function getProfile(userId) { // each client sets its own fixed 1s timeout; nothing is passed down const user = await usersClient.get(userId, { timeoutMs: 1000 }); const prefs = await prefsClient.get(userId, { timeoutMs: 1000 }); const feed = await feedClient.get(userId, { timeoutMs: 1000 }); return { user, prefs, feed };}
Quiz
Completed
The entry point promises a 1 s SLA, but this function can take ~3 s when downstreams are slow. Why, and what is the correct shape?
Heads-up Fixed per-hop timeouts do not compose. Sequential calls each consuming up to 1 s sum to ~3 s; isolated timeouts cannot enforce a request-wide budget — only a propagated deadline can.
Heads-up Static splitting wastes budget — a fast first call should leave more time for later ones. A propagated deadline with min(local, remaining) adapts to actual elapsed time instead of a fixed 1/N split.
Heads-up Concurrency caps the total at the slowest single call (~1 s), which helps — but without a propagated deadline a slow hop can still hang past the budget, and fan-out then exposes tail amplification. You need both concurrency and a deadline.
Recap
Every lifecycle incident is read in the wiring or the hot path: middleware registered after a route never runs, so order is a security boundary; a write() loop that ignores the false return OOMs under slow clients, so use pipeline(); an unbounded query plus generic JSON.stringify blocks the loop, so paginate and use a schema serializer; and fixed per-hop timeouts do not compose, so propagate a deadline with min(local, remaining). Diagnose the stop, apply the highest-leverage fix, then verify under the same load.