Files
PersonalBlog/docs/adr/ADR-002-node-24-lts-runtime.md

4.5 KiB

ADR-002: Node.js 24 LTS runtime

  • Status: Accepted
  • Date: 2026-08-31
  • Deciders: platform stream
  • References: ADR index (section 70), Technology stack wiki (sections 5.2, 6, 7, 8), ADR-001

Context

EPPP is a greenfield personal blogging platform (ADR-001) whose runtime is a single modular-monolith application plus an optional worker, deployed as one or more containers of one image. The whole platform — public server, admin API, rendering pipeline, extension runtime, core services and background jobs — executes on one runtime, so the runtime choice is a platform-wide, hard-to-reverse decision with security, tooling and operational reach.

The workspace is a pnpm monorepo (pnpm 11.23.0) whose root manifest already declares engines.node: ">=24.0.0 <25.0.0" with engineStrict: true, and the CI pipeline installs and runs on Node 24 (E00-S01-T08). The technology stack wiki classifies Node.js as support class A — a fixed upstream EOL date — and pins the golden compatibility tuple to Node 24.19.0 LTS (Krypton), with node:24.19.0-bookworm-slim as the application container base image.

Decision

EPPP runs on the Node.js 24 LTS runtime line, exact-pinned to Node 24.19.0 LTS (Krypton) in the golden compatibility tuple and the container image. The workspace root manifest restricts the engine to 24.x (engines.node: ">=24.0.0 <25.0.0"), pnpm enforces it at install time (engineStrict: true), and CI installs and runs on Node 24. The runtime is a class A dependency: its upstream EOL (2028-04-30) drives the upgrade schedule, and a move to a later major line (for example Node 26) is only evaluated once that line is LTS and the compatibility suite passes, and then only as a deliberate, ADR-recorded change. The decision text — Node.js 24 LTS runtime — matches the ADR index entry (ADR-002, section 70).

Alternatives

  • Node 22 LTS (Jod) — rejected: it is the previous LTS line and reaches EOL before Node 24 (2027-04-30), shortening the runway for a platform whose v1.1 boundary contracts (ADR-027 to ADR-032) extend past that date.
  • Node 26 (current, non-LTS at decision time) — rejected: not LTS when the decision was made; running a non-LTS line contradicts the class A support posture (fixed EOL, security patching on an LTS cadence).
  • Node 24 with no exact pin (floating latest 24.x) — rejected: a floating minor would break the reproducibility of the golden compatibility tuple and the container image; the line is pinned and minors move deliberately.
  • Node 24 LTS, exact-pinned 24.19.0 — chosen: an LTS major with a fixed EOL, exact-pinned in the image and tuple, engine-restricted in the manifest, and enforced in CI.

Consequences

  • Positive: an LTS line with a fixed upstream EOL (2028-04-30) gives a predictable security-patching and upgrade horizon; the exact pin makes builds and containers reproducible; the engine restriction rejects unsupported Node versions at install time instead of failing at runtime.
  • Negative: Node 24 API and behaviour become the platform floor — anything needing a newer Node feature waits for the deliberate, ADR-recorded major upgrade; minor upgrades inside 24.x still need the weekly dependency sweep and full CI.
  • Neutral: the runtime is shared by every module, so a future extraction (ADR-001) keeps running on the same Node line until that module's runtime needs diverge.

Operational impact

  • Application and worker containers run node:24.19.0-bookworm-slim; release automation records the immutable image digest in the SBOM/release manifest.
  • The supported runtime is enforced at install (engineStrict: true fails installs on unsupported Node) and at test time (the node-engine suite asserts the current runtime satisfies the 24.x range).
  • CI installs and runs every stage on Node 24, so the committed pipeline is the operational proof that the platform runs on the chosen line.
  • Node 24 is patched on the LTS cadence; security-emergency updates go through the focused lane (immediate, full CI), and the EOL date is the deadline for the next major-line ADR.

Revisit trigger

  • Revisit when Node 26 becomes LTS and passes the compatibility suite, per the LTS strategy — the decision to move majors is a new ADR, not a patch.
  • Revisit on a security-emergency or patch-lane event that forces a minor upgrade outside the weekly sweep, or if upstream announces a change to the Node 24 support horizon.
  • Revisit if a module's runtime needs (ADR-001 extraction) diverge from the shared Node line and a second runtime enters the platform.