Course outline

NestJS / Advanced: lifetime and distributed-work evidence / Lesson 17

Observability, health and bounded shutdown

Measure safe operation outcomes and coordinate readiness, drain and resource release through explicit lifecycle ownership.

About 4 min readContent reviewed
On this page

Lesson goals

  • Distinguish telemetry, liveness, readiness and business success.
  • Explain shutdown hooks without assuming a close call ends every task or process.

Collect stage evidence without copying private requests

Use safe controller/handler identifiers, result category, duration and bounded source counts rather than raw URLs, tokens or payloads. A successful HTTP status can coexist with a domain rejection if the API models that explicitly, so metrics need the application outcome too. Separate pool wait, handler work and downstream latency when diagnosis requires it. Concurrent spans overlap and inclusive parent spans contain child work; summing them can overstate elapsed time. Keep controlled correlation for detailed incidents instead of using high-cardinality user IDs as routine metric labels. Observability does not grant permission to retain every private input indefinitely.

Describe serving state and bounded probes

Health integrations can expose useful status, but choose what liveness and readiness mean for this deployment. A transient dependency outage need not imply that restarting a healthy process will fix it. Keep probes cheap, time-bounded and public-safe, and avoid dumping source configuration. The JSON note is a synthetic state contract, not a Terminus endpoint or an orchestrator setting. Readiness should stop admitting intended new work before dependencies close during drain. Verify ingress propagation separately; changing a local Boolean does not prove the upstream load balancer already stopped sending requests.

json Synthetic health and drain contract
{"states":["starting","serving","draining","stopped"],"readyOnlyIn":"serving","probe":"safe-bounded-summary","drain":"deadline-and-owned-cleanup","sourceSecrets":"never-in-health-body"}

The record configures no health integration and sends no probe. It states assumptions to verify independently.

Enable and own lifecycle behavior deliberately

Nest shutdown hooks are tied to explicit application close or opted-in signal handling. Register the intended behavior and verify the selected versionโ€™s hook order rather than relying on constructor order. Closing an application context does not necessarily terminate Node while intervals or other owned tasks remain active. Request-scoped and application-scoped resources also have different lifetimes. Stop admission, drain accepted work within a deadline, then release shared sources. Long-lived streams, message consumers and schedulers need their own coordinated policies so one subsystem does not continue producing work after another has closed its dependencies.

Test admission and completion as local invariants

The state model accepts one operation while serving, rejects new admission during drain and reaches stopped only after the accepted work count reaches zero. It sends no process signal and controls no real server. A real implementation needs exception-safe decrements, concurrent coordination and a forced-stop deadline. If that deadline expires during a write, preserve outcome uncertainty instead of reporting guaranteed rollback. The model is intentionally small so the desired ordering can be checked without operational side effects. It does not validate Nest hooks, Node signal behavior or actual source cleanup.

javascript Complete offline admission/drain model
const state={phase:"serving",active:0};
function accept() {if (state.phase !== "serving") return false;state.active++;return true;}
console.assert(accept()); state.phase="draining";
console.assert(!accept() && state.active === 1);
state.active--; if (state.active === 0) state.phase="stopped";
console.assert(state.phase === "stopped");

One accepted operation finishes and no new operation enters after drain. No application is closed.

Tie deployment claims to executed evidence

Review logger integration, health exposure, source budgets, signal support and worker shutdown together with release and rollback artifacts. Multiple instances do not share in-memory session or replay maps automatically. Verify the intended lifecycle using synthetic workloads in an authorized isolated environment, not by terminating configured services during authoring. This course parses the policy and runs only the state model; it does not instantiate Terminus, register hooks, send signals, measure latency or run a load test. The next reviewer should be able to tell exactly which guarantees remain untested before adapting the design to a real system.

Common errors and fixes

A probe exposes source credentials

Why it happens
Detailed diagnostics were returned as public health data.
How to fix it
Return bounded safe status and protect internal evidence.
Prevent it next time
Assert exact public health fields.

A closed app leaves background work running

Why it happens
Context close was assumed to end every timer and task.
How to fix it
Give each long-lived resource an explicit stop owner.
Prevent it next time
Verify resources and process lifetime separately.

New requests enter after source cleanup

Why it happens
Admission and readiness changed too late.
How to fix it
Coordinate admission, drain and cleanup in dependency order.
Prevent it next time
Test late arrivals and in-flight work.

Check your understanding

1. Does app.close necessarily terminate the Node process?

Show worked solution

No. It performs the application shutdown sequence, but active intervals or independently owned background tasks can keep the process alive. Identify their owners and stop them under the lifecycle contract. Verify actual behavior in an isolated authorized integration rather than treating a shutdown log line as proof of full resource release.

2. Why distinguish readiness from liveness?

Show worked solution

One asks whether the process is functioning, while the other asks whether it should receive work under the deployment contract. Restarting a healthy process may not repair a shared dependency outage. Define bounded checks and rollout behavior so health policy supports recovery instead of amplifying it through unnecessary restarts.

Key takeaways

  • Health and telemetry describe different facets of operation.
  • Graceful shutdown requires explicit bounded ownership beyond decorators.

Official references