Shutdown Check

Search documentation

Find a page or section

Read a result in the terminal or export the same data as JSON and JUnit.

Every shutdown-check run produces one result with a verdict, diagnostic code, message, timeline, duration, and captured service output. Choose text for people, JSON for scripts, or JUnit XML for CI reports.

Choose an output format

FormatCommand optionDestinationBest for
TextdefaultstdoutLocal debugging and CI logs
JSON--jsonstdoutScripts and structured logs
JUnit XML--junit FILEfileCI test-report interfaces
Exit codealwaysprocessPassing or failing the caller

You can write JUnit while printing either text or JSON:

npx shutdown-check test --json --junit shutdown-result.xml

Read the text output

A passing result contains a verdict and timeline:

PASS SC000: Graceful shutdown verified
 
Timeline:
  +    5 ms  process launched — pid=67911
  +  113 ms  service ready — HTTP 200
  +  113 ms  work request sent — #1 GET /slow
  +  113 ms  work request sent — #2 GET /slow
  +  114 ms  work confirmed active — 2 response(s) sent headers; bodies still in progress
  +  114 ms  signal sent — SIGTERM
  +  115 ms  readiness withdrawn — HTTP 503
  +  115 ms  new request rejected — HTTP 503
  + 2117 ms  work request finished — #1 HTTP 200
  + 2117 ms  work request finished — #2 HTTP 200
  + 2120 ms  process exited — code=0, signal=none
  + 2121 ms  shutdown verified — work completed and service exited before deadline

The number after + is milliseconds since the run began. Read the lines in order to see what happened before and after SIGTERM.

A failure ends with check failed:

FAIL SC201: In-flight request was interrupted: aborted
 
Timeline:
  +    6 ms  process launched — pid=73692
  +  112 ms  service ready — HTTP 200
  +  113 ms  work request sent — #1 GET /slow
  +  113 ms  work confirmed active — 1 response(s) sent headers; bodies still in progress
  +  113 ms  signal sent — SIGTERM
  +  116 ms  process exited — code=null, signal=SIGTERM
  +  116 ms  work request finished — #1 aborted
  +  116 ms  check failed — SC201: In-flight request was interrupted: aborted

Open the page for the code—in this case SC201—to see causes and fixes.

Service stdout and stderr

On a failed check, text output adds the last 8 KiB of each non-empty service stream:

Service stderr (last 8 KiB):
Error: database close timed out
 
Service stdout (last 8 KiB):
SIGTERM received
closing HTTP server

Earlier output is discarded when a stream grows beyond 8 KiB. Keep shutdown logs concise and write important state near the failure.

The service output is captured, not streamed live. It appears after the result so the timeline remains readable.

Timeline events

EventMeaning
process launchedThe configured command started
service readyThe readiness route returned its expected status
work request sentA workload request was opened
work confirmed activeThe selected start barrier passed
signal sentThe first SIGTERM was delivered
signal repeatedThe optional second SIGTERM was delivered
readiness withdrawnThe readiness route stopped reporting ready
new request rejectedNew work returned an allowed status or connection refusal
work request finishedA workload response completed or failed
process exitedThe launched process stopped
shutdown verifiedEvery configured check passed
check failedThe run ended with the displayed diagnostic code

An event appears only when that part of the config runs. For example, readiness withdrawn is absent unless shutdown.readinessWithdrawal is enabled.

JSON output

Run:

npx shutdown-check test --json

The command prints one JSON object. A shortened passing example:

{
  "pass": true,
  "code": "SC000",
  "message": "Graceful shutdown verified",
  "startedAt": "2026-09-23T10:00:00.000Z",
  "durationMs": 2121,
  "timeline": [
    { "ms": 5, "event": "process launched", "detail": "pid=67911" },
    { "ms": 114, "event": "signal sent", "detail": "SIGTERM" },
    {
      "ms": 2121,
      "event": "shutdown verified",
      "detail": "work completed and service exited before deadline"
    }
  ],
  "stdout": "",
  "stderr": ""
}
OptionTypeDefaultDescription
pass*boolean—true only for SC000.
code*string—The diagnostic code: SC000 on a pass, the first failure otherwise.
message*string—What happened, in one sentence, with the values observed.
timeline*TimelineEvent[]—Every step of the check in order, with milliseconds since it started.
stdout*string—The last 8 KiB the service wrote to stdout.
stderr*string—The last 8 KiB the service wrote to stderr.

The timeline array contains:

OptionTypeDefaultDescription
ms*number—Milliseconds since the check started, rounded.
event*string—What happened: "process launched", "service ready", "signal sent", "work request finished", "process exited" and so on.
detailstring—The values behind it, such as "HTTP 503" or "code=0, signal=none".

JSON uses the same exit codes as text. A failure still exits with 1, so a shell step may need to preserve stdout before reacting to the exit.

JUnit report

Run:

npx shutdown-check test --junit reports/shutdown.xml

The parent directory must exist. shutdown-check writes one test suite with one test case:

  • a pass has no failure element;
  • a failed shutdown adds the diagnostic code and message as the failure;
  • the timeline is included in system output;
  • captured service stdout and stderr are included when available;
  • the suite time uses the run duration.

The default suite name is shutdown-check. From the Node API, pass a second argument to junitXml(result, name) to choose another name.

The report is written before the CLI prints text or JSON. A normal check failure therefore still produces the file. A setup or config error produces no report because no CheckResult exists.

Exit codes

Exit codeMeaning
0passed
1shutdown check failed
2setup/configuration error
CodeMeaningOutput available
0The configured shutdown contract passedText/JSON and optional JUnit
1The test ran and returned a failing SC codeText/JSON and optional JUnit
2Arguments, setup, or config stopped the runError on stderr; no JUnit result

CI should fail on any nonzero code. Treat 2 as a broken test setup and 1 as a service behavior that needs investigation.

Use the result from code

checkShutdown() and runCheck() return the same CheckResult object used by JSON output. junitXml() creates the same XML as the CLI.

import { checkShutdown, junitXml } from "shutdown-check";
 
const result = await checkShutdown(config);
const xml = junitXml(result, "orders-api shutdown");

See the Node API for a complete custom runner.