Versions, Support & LTS

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

The reference material consulted while preparing these pages is listed in the section bibliography.

This page is written against Express 5.3.0 (npm and GitHub release of 2026-10-09) and Express 4.22.3 (2026-09-14, the newest 4.x), running on Node.js 24 LTS, and the facts were checked on 2026-10-29. It answers the questions every project asks before the first line of code and again at every upgrade: which Express line should I install, which Node.js does it need, how long will it receive fixes, and where do I read about what changed.

Express keeps a deliberately simple policy. Only the latest version of each major line is supported, a major line moves through documented phases, and the project publishes the minimum Node.js it supports for each line. The table in the next section is the short answer. The rest of the page explains how to read the history behind it and how to automate the checks so a project never silently falls behind.

Release history

Express 4 was the long-lived line: it started in April 2014 and, for more than ten years, was what npm install express gave you. Express 5 was published as 5.0.0 in September 2024, but it was released under the next dist-tag rather than latest, so ordinary installs stayed on 4.x for another six months. The switch happened with 5.1.0 on 2025-03-31, the first Express 5 release on the latest tag. From that day npm install express installs Express 5.

Table 1. Express releases that matter for this section
Version Date What it means

4.0.0

April 2014

Start of the Express 4 line (the support page lists the line as starting in April 2014). The four books behind this section target 4.0 to 4.18.

3.x

ended July 2015

Deprecated. The site still shows the 3.x API reference, but the line has been unsupported for years.

5.0.0

2024-09-10

First Express 5 release, published on the next tag. Breaking changes are listed in the migration guide and in Migrating and what changed.

5.0.1

2024-10-08

First patch release of the 5.x line.

5.1.0

2025-03-31

First release on the latest tag. From here npm install express installs Express 5.

5.2.0 and 5.2.1

2025-12-01

Published together with 4.22.0 and 4.22.1 on the same day.

4.22.2

2026-05-11

Maintenance release of the 4.x line.

4.22.3

2026-09-14

Newest Express 4 release at the time of writing, on the latest-4 tag.

5.3.0

2026-10-09

Newest Express release at the time of writing. The History.md entry lists CVE fixes through qs ^6.16.0, proxy-addr ^2.0.8 and req.fresh support for the QUERY method.

Two practical consequences follow from this timeline. First, a tutorial or book that targets Express 4 is not wrong because it is old, it is wrong for new projects only where the Express 5 changes bite. Second, because Express 5.0.0 existed for half a year without being the default, search results, Stack Overflow answers and package templates written in that window often show Express 4 behaviour next to an express@5 install. When an example fails with a path-syntax error or an undefined req.body, check the installed major version first.

There is no Express 6. No release or roadmap has been announced, and this section does not document speculative work in progress.

What the 5.x releases changed

Express 5 itself is mostly a cleanup of the 4.x API plus a new routing engine. Each release since then added a small amount.

  • 5.0: removal of long-deprecated methods, path matching rebuilt on path-to-regexp 8 (through router 2), rejected promises forwarded to error handlers, req.body left undefined when no body was parsed, and express.urlencoded defaulting to extended: false.

  • 5.1: the line becomes latest, and the documentation and the Node.js minimum are updated for it (see the support table).

  • 5.2: security and dependency updates shipped together with the 4.22 releases.

  • 5.3: app.query() and QUERY method support in the request pipeline, req.fresh aware of that method, and updated dependencies including qs ^6.16.0 and proxy-addr ^2.0.8.

The dependency set is part of the version story, because most behaviour that people attribute to Express actually lives in a sibling module. Express 5.3.0 depends on router ^2.2.0 (which uses path-to-regexp 8), body-parser ^2.3.0, serve-static ^2.2.0, send ^1.1.0, finalhandler ^2.1.0, qs ^6.16.0 and cookie ^0.7.1. Newer releases of those modules than the ones Express pins can exist on npm: path-to-regexp has a 9.x release, yet Express 5.3 still routes through path-to-regexp 8. Read the dependency ranges of the installed Express, not the newest version of each module, when you reason about behaviour.

The LTS phases

Express uses three phases for a major line, borrowed from the Node.js model.

Phase Meaning

CURRENT

The newest major line. It receives new features, bug fixes and security fixes.

ACTIVE

The line recommended for production. It receives bug fixes and security fixes, and features only where they are backward compatible.

MAINTENANCE

The line receives critical bug fixes and security fixes only, and the project advises moving to the newer line.

After MAINTENANCE a line reaches end of life, which means no further releases, including no security patches from the project. The support page expresses the end date as a floor ("no sooner than") rather than a promise, so the real end of life is announced when the team decides it, not when a calendar date passes.

The schedule that the support page and the 5.1 release announcement described when they were last read for this section was:

  • Express 5: ACTIVE since 2025-03-31 (the 5.1.0 release), MAINTENANCE no sooner than 2026-04-01, end of life no sooner than 2027-04-01.

  • Express 4: MAINTENANCE since 2025-04-01, end of life no sooner than 2026-10-01.

These phase dates are the announced floors, not facts that were re-extracted from the live page on the check date. What was verified on 2026-10-29 is the supported-versions table, which shows both Express 5 and Express 4 with an end date of "ongoing", and the absence of any end-of-life announcement for Express 4. Treat the phase dates as planning hints and read the support page before relying on them.

gantt title Express 4.x and 5.x lines - announced phases dateFormat YYYY-MM-DD axisFormat %Y-%m section Express 4.x Release line starts April 2014 :milestone, m4, 2014-04-01, 0d Maintenance from 2025-04-01 :active, v4m, 2025-04-01, 2026-10-29 End of life floor 2026-10-01 not announced :crit, v4e, 2026-10-01, 2026-10-29 section Express 5.x 5.0.0 on the next tag :milestone, m50, 2024-09-10, 0d 5.1.0 first on latest :milestone, m51, 2025-03-31, 0d Active from 2025-03-31 :active, v5a, 2025-03-31, 2026-10-29 5.3.0 released :milestone, m53, 2026-10-09, 0d Maintenance floor 2026-04-01 :v5m, 2026-04-01, 2026-10-29 End of life floor 2027-04-01 :v5e, 2027-04-01, 2027-04-02

The chart draws the announced floors against the check date. Express 4 sits past its end-of-life floor while still showing "ongoing" on the support page, which is exactly why the floor must not be read as a deadline.

The support table

The official support page lists one row per major line. The values below were read on 2026-10-29.

Table 2. Supported versions of Express
Line Starts Ends Minimum Node.js Notes

5.x

September 2024

ongoing

18

engines.node of express@5.3.0 is >= 18. The latest tag.

4.x

April 2014

ongoing

0.10.0

On the latest-4 tag. Receives fixes, but in the MAINTENANCE phase.

3.x

before 4.x

July 2015

not supported

Deprecated.

Node.js minimums

Express 5 requires Node.js 18 or newer. Express 4 declares support back to Node.js 0.10, which is a statement about the code Express ships, not a recommendation: Node.js 0.10 is long past its own end of life. Run a Node.js release that is itself supported, that is, an Active or Maintenance LTS line on the Node.js release schedule. This section uses Node.js 24 LTS.

The Express minimum is a floor, and individual features can need more. app.query(), which registers handlers for the HTTP QUERY method, needs a Node.js line whose HTTP parser knows that method. The API page lists >=20.19.3 <21 || >=22.2.0. On Node.js 18, or on an older 20 or 22 release, app.query is not defined, so an app that calls it throws a TypeError at startup unless it first checks http.METHODS for QUERY. Pin your own engines.node to the Node.js lines you test, not to the Express floor.

Security releases and where to find them

Express publishes fixes frequently. The History.md entry for 5.3.0 alone bundles dependency updates with CVE fixes (qs ^6.16.0 and proxy-addr ^2.0.8), and 2026 had a steady stream of 4.x and 5.x patch releases. Three places carry the details, and none of them is complete on its own.

  • The GitHub security advisories of the expressjs/express repository carry the structured data (CVE identifier, affected and patched versions). This is where 5.x vulnerabilities are published.

  • The Express blog announces notable security releases and policy changes.

  • The security updates page of the documentation lists vulnerabilities that were fixed for the 4.x and 3.x lines. It does not list 5.x issues, so a project on Express 5 that only reads that page sees nothing.

Express also depends on many small modules. A vulnerability in qs, path-to-regexp, cookie, send or body-parser is fixed by a release of that module and is delivered to your project either by an Express release that raises the dependency range or by a plain npm update inside the existing range. Keeping package-lock.json current and running npm audit in CI therefore matters as much as tracking Express releases. The project also publishes a security policy and a threat model through its governance repositories, and the practices that go with them are covered in Security best practices.

Extended commercial support

The support policy covers only the latest release of each major line and does not promise long-term fixes for old ones. The support page points to commercial extended support for lines that the project no longer maintains, naming HeroDevs as a provider. This is a paid third-party service, separate from the OpenJS Foundation project. It matters when a codebase cannot leave Express 3 or Express 4 before the project ends the line, and you need security patches for a compliance reason in the meantime. Compare it with the cost of the Express 5 migration before buying it: the migration is mostly mechanical, because official codemods cover the removed methods (see Migrating and what changed).

Reading History.md and GitHub releases

Two official change logs exist and they complement each other.

  • History.md in the expressjs/express repository is the curated change log. The newest release is at the top. Each entry groups changes into bullets: breaking changes, deprecations, new features, fixes and dependency bumps. It is the file to search when you want to know in which version an option appeared.

  • The GitHub releases page carries the same releases with generated notes (merged pull requests and contributors) and the exact publication time. It is the better place to find the pull request that introduced a change and to subscribe to notifications.

A reliable reading routine for an upgrade is: read the History.md entries between your installed version and the target, then read the release page of any version whose entry mentions a dependency range or a CVE, and finally check the dependency ranges with npm view. The npm registry is the third source of truth, because it records the real publication date and the dist-tags.

# Which versions exist and which tag points where
npm view express dist-tags

# The newest version of each line, with its publication time
npm view express time --json | node --eval "
  let json = '';
  process.stdin.on('data', (chunk) => { json += chunk; });
  process.stdin.on('end', () => {
    const times = JSON.parse(json);
    for (const version of ['5.3.0', '4.22.3']) {
      console.log(version, times[version]);
    }
  });
"

# What the exact release depends on and which Node.js it declares
npm view express@5.3.0 dependencies engines

On 2026-10-29 the first command printed the two tags, latest (5.3.0) and latest-4 (4.22.3):

{ latest: '5.3.0', 'latest-4': '4.22.3' }

Source: npm: npm view

The latest-4 tag exists so that a project can stay on the 4.x line and still pick up its fixes without a manual version bump: npm install express@latest-4 installs 4.22.3, and a range such as ^4.22.3 in package.json never crosses into 5. To move to 5 you change the range on purpose.

Choosing 4 or 5 today

Choose Express 5 for every new project. It is the latest tag, in the ACTIVE phase, has the maintained routing engine and body parser, and forwards rejected promises to the error handler, which removes a category of crashes. Stay on Express 4 only when an existing codebase is blocked by a dependency that has not moved, and plan the migration, because the 4.x line is in MAINTENANCE and there is no promise that it will be patched indefinitely.

Table 3. Choosing between Express 4 and Express 5
Question Express 5 Express 4

New project

Yes, default.

No.

Minimum Node.js

18 (use a supported LTS, this section uses 24)

0.10 declared, use a supported LTS in practice

Rejected promises in handlers

Forwarded to the error handler

Unhandled unless wrapped

Path patterns

path-to-regexp 8: named wildcards such as /*splat, braces for optional segments

Older path-to-regexp: bare * and ?

req.body after a parser on a request without a body

undefined

{}

Security fixes

Yes, ACTIVE line

Yes, MAINTENANCE line

Migration effort

None

Official guide and codemods, mostly mechanical

The migration guide and the codemods are the way across. The mechanical part (removed methods, renamed methods, argument order) is automated, and the behavioural part (path syntax, async errors, req.body, req.query) is small enough to review by hand. All of it is listed in Migrating and what changed, and the routing syntax is covered in Route paths and parameters.

Automating the version checks for Bookshelf

The Bookshelf API of this section is a good candidate for three small guards: declare the supported runtime in package.json, fail fast at startup on an unsupported Node.js, and fail the test suite if the installed Express major is not the one the code targets.

{
  "name": "bookshelf-api",
  "version": "1.0.0",
  "private": true,
  "type": "module",
  "engines": {
    "node": ">=24"
  },
  "scripts": {
    "start": "node --env-file=.env src/server.js",
    "test": "node --test"
  },
  "dependencies": {
    "express": "^5.3.0"
  }
}

The engines field is advisory by default: npm prints a warning when the running Node.js does not satisfy it, and refuses only when engine-strict is set in .npmrc. The guard below enforces it at runtime and exposes the result on a small endpoint, so an operator can see which Express range and Node.js release a running instance uses.

// src/version-info.js
import { readFile } from 'node:fs/promises';

const MINIMUM_NODE_MAJOR = 24;

export function assertSupportedNode(version = process.versions.node) {
  const major = Number.parseInt(version.split('.')[0], 10);
  if (major < MINIMUM_NODE_MAJOR) {
    throw new Error(
      `Node.js ${MINIMUM_NODE_MAJOR} or newer is required, found ${version}`,
    );
  }
}

export async function readVersionInfo() {
  const manifest = JSON.parse(
    await readFile(new URL('../package.json', import.meta.url), 'utf8'),
  );
  return {
    name: manifest.name,
    version: manifest.version,
    node: process.versions.node,
    expressRange: manifest.dependencies.express,
    nodeRange: manifest.engines.node,
  };
}
// src/server.js
import express from 'express';
import { assertSupportedNode, readVersionInfo } from './version-info.js';

assertSupportedNode();

const app = express();
app.disable('x-powered-by');

app.get('/api/v1/version', async (req, res) => {
  res.json(await readVersionInfo());
});

const port = Number.parseInt(process.env.PORT ?? '3000', 10);
const server = app.listen(port, (error) => {
  if (error) {
    throw error;
  }
  console.log(`bookshelf-api listening on port ${port}`);
});

process.on('SIGTERM', () => server.close());

Run it with node --env-file=.env src/server.js (or npm start), and call the endpoint:

curl --silent http://localhost:3000/api/v1/version
{
  "name": "bookshelf-api",
  "version": "1.0.0",
  "node": "24.11.0",
  "expressRange": "^5.3.0",
  "nodeRange": ">=24"
}

The exact Node.js version in the output is whatever runs on your machine. Notice that app.listen() passes an error argument to its callback in Express 5, a change from Express 4, where startup errors such as a busy port were emitted as events and a callback never saw them.

The last guard is a test that fails when the installed Express is not the major version the code was written for. It reads the installed package manifest from disk, so it checks what npm actually put in node_modules, not what package.json hopes for.

// test/express-version.test.js
import assert from 'node:assert/strict';
import { readFile } from 'node:fs/promises';
import { test } from 'node:test';

test('the installed Express is a 5.x release', async () => {
  const manifest = JSON.parse(
    await readFile(
      new URL('../node_modules/express/package.json', import.meta.url),
      'utf8',
    ),
  );
  const major = Number.parseInt(manifest.version.split('.')[0], 10);
  assert.equal(major, 5, `Express ${manifest.version} is installed`);
  assert.equal(manifest.engines.node, '>= 18');
});

Two commands keep the dependency side honest over time. They need no configuration and fit a scheduled CI job.

# Show which direct dependencies have newer releases
npm outdated

# Report known vulnerabilities in the full dependency tree
npm audit --omit=dev

Source: npm: npm audit

Where the books are outdated

The four books behind this section were all written for Express 4. A reader following them in 2026 meets these version-related differences.

What the books assume What is true today

Express 4 is the current line, from 4.0 up to 4.18.

Express 5.3.0 is the latest release and Express 4 is in MAINTENANCE. One book was published three months before 5.0.0, so none of them can show Express 5.

Install the framework globally to get a command-line tool.

The generator is a separate package (express-generator) and still produces an Express 4 style application. Install Express per project.

Old Node.js releases and tooling from the era of each book.

Express 5 needs Node.js 18 or newer, and a project should run a supported LTS such as Node.js 24.

Hosting, CI and package-manager workflows of 2014 to 2018.

Several of those services no longer exist. Use node --watch and node --env-file in development and a container image in production.

CommonJS with var and callbacks.

Express 5 works with both module systems. This section uses ESM, node: prefixes and async handlers.