Open-Source Wikis

/

Express

/

Lore

expressjs/express

Lore

Express has been around for almost 17 years. This page traces the eras it has lived through, drawn from History.md and the git log (first commit 2009-06-26, latest commit 2026-04-23, 6,139 commits, 385 unique author emails).

Eras

The TJ years (Jun 2009 – early 2014)

Express was created by TJ Holowaychuk. The first commit lands on 2009-06-26. Through 2010–2013 TJ authored the bulk of the original code — over 3,800 commits in the all-time history are still attributed to tj@vision-media.ca. During this era Express grew from a Sinatra-inspired toy into the dominant Node.js web framework, hitting 3.x and the early 4.x line.

Key events:

  • Jun 2009 — Initial commits, project bootstrap.
  • Mar 2014 — Express 4.0.0 released, removing the bundled Connect middleware and turning Express into a thin layer on top of standalone packages. This was the first major decoupling of the codebase.

The Doug Wilson stewardship (2014 – ~2020)

Douglas Christopher Wilson (doug@somethingdoug.com) takes over day-to-day maintenance after TJ steps back. He becomes the second most prolific author in the history (~1,230 commits). The 4.x line gets a long succession of patch releases focused on security, dependency hygiene, and incremental polish. Express becomes the standard reference for "stable, boring, well-supported" in the Node ecosystem.

Key events:

  • 2014–2018 — Steady 4.x releases (4.10–4.16). Many internals split out into the expressjs/ and pillarjs/ orgs: body-parser, serve-static, send, finalhandler, router.
  • Late 2010spath-to-regexp-based routing is moved to its own router package; subsequent versions of Express simply re-export it.

The OpenJS / TC era and the long road to v5 (2020 – Sep 2024)

Express joins the OpenJS Foundation. A formal Technical Committee (TC) is established, listed in Readme.md (Ulises Gascón, Jon Church, Wes Todd, Linus Unnebäck, Blake Embrey, Jean Burellier, Rand McKinney, Chris de Almeida). Triagers are added. The 5.0 line, originally branched in 2014 as 5.0.0-alpha.1, finally crosses the finish line.

Key events:

  • Feb 20225.0.0-beta.1 based on 4.17.2. Sets query parser default to 'simple', requires Node.js 4+, switches to mime-types, and pulls in the new path-to-regexp parameter modifiers (?, *, +).
  • Mar 20245.0.0-beta.2 and 5.0.0-beta.3 incorporate accumulated 4.x changes.
  • 2024-09-10Express 5.0.0 released. Major changes include:
    • res.status() becomes strict: integers only, range 100–999, throws otherwise.
    • res.redirect('back') and res.location('back') magic strings dropped.
    • res.clearCookie ignores user-provided maxAge/expires.
    • Many dependency upgrades: cookie-signature@^1.2.1, merge-descriptors@^2, serve-static@^2.1, accepts@^2, mime-types@^3, type-is@^2, body-parser@^2, send@^1.1.

The 5.x stabilisation (Sep 2024 – present)

After 5.0.0, the cadence becomes "small, frequent, focused":

  • 2024-10-085.0.1: cookie semver lock for CVE-2024-47764.
  • 2025-03-315.1.0: Uint8Array in res.send(), ETag option in res.sendFile(), multiple links with same rel in res.links(). Cleanup pass removes setprototypeof, safe-buffer, utils-merge, methods, and depd from the dependency tree.
  • 2025-12-015.2.0 ships a security fix for CVE-2024-51999, then 5.2.1 reverts it on the same day after the CVE was rejected and the fix proved to be an unintended breaking change to the extended query parser. A short, instructive saga preserved at the top of History.md.
  • Through 2026-04 — Master is in "unreleased changes" mode: HTML structure improvements in res.redirect() (#5167), app.render accepting null options (#6903), and a res.send() perf tweak avoiding duplicate Content-Type processing (#6991).

Longest-standing features

Feature First seen Why it survives
app.set / app.get settings store Pre-2.0 era (pre-2010) The single source of truth for per-app config; mounted apps inherit via prototype chain.
res.send / res.json / res.render Pre-2.0 The user-facing API contract that has shaped Express's identity since the beginning.
Template engine pluggability Pre-2.0 app.engine(ext, fn) + View.lookup is the original "swap any template engine" abstraction.
Mounted sub-apps 2.x era app.use('/admin', subApp) with prototype-inherited settings. Still implemented the same way.
req.accepts / req.is Connect-era heritage Tiny wrappers over the accepts and type-is packages.
app.METHOD(path, ...) proxies Pre-2.0 Dynamic generation from node:http's METHODS list — has outlasted multiple router rewrites.

Deprecated / removed features

Feature Removed Replacement
Bundled Connect middleware Express 4.0 (Mar 2014) Use middleware packages directly
res.send(status, body) and similar overloads 4.x deprecation, removed in 5.0 res.status(code).send(body)
res.redirect('back') / res.location('back') magic 5.0 (Sep 2024) res.redirect(req.get('Referrer') ?? '/')
res.status accepting non-integer/out-of-range values 5.0 Pass an integer in [100, 999] — anything else throws
path-is-absolute dependency 5.0 node:path isAbsolute
setprototypeof, safe-buffer, utils-merge, methods, depd 5.1.0 (Mar 2025) Native equivalents (Object.setPrototypeOf, node:buffer, spread, node:http METHODS)
Built-in bodyParser() middleware on the app 4.0 body-parser package, re-exported as express.json/urlencoded/...
Built-in static() middleware 4.0 serve-static package, re-exported as express.static
Built-in Router implementation Late 4.x External router package, re-exported as express.Router

Major rewrites and extractions

  • Connect → standalone middlewares (2014, Express 4.0). Body parsing, static serving, sessions, and the rest of Connect's middleware were spun out into individual packages. Express became a small core.
  • Routing extraction → router package (late 4.x). The internal Router moved to the pillarjs/router repo. Express now re-exports it.
  • Body parsing → body-parser package (4.x → 5.x). express.json, express.raw, express.text, and express.urlencoded are now thin re-exports of body-parser's functions.
  • Dependency diet for 5.1 (Mar 2025). Removed five legacy polyfill-style dependencies in favour of native Node features.

Growth trajectory

  • 2009–2013 — Solo project (TJ era), commit cadence routinely > 100/month.
  • 2014–2019 — Doug Wilson era, steady ~30/month. Dependency split into many sub-packages.
  • 2020–2024 — Slow phase of governance work and the v5 push. Cadence dips into ~10/month.
  • 2024–2026 — Modest revival post-v5. Activity is dominated by dependabot bumps, but real fixes and small features keep landing. Triagers and TC turn over occasionally; a long Triagers-emeriti list in Readme.md records the historical roster.

385 unique author email addresses appear in the all-time log. The vast majority are one-time contributors (typo fixes, doc tweaks). Effective long-term maintenance has always rested on a handful of TC members.

See also

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Lore – Express wiki | Factory