# System map — expressjs/express

> Canonical page: https://codevetter.com/unpack/express/system-map

# System map — expressjs/express

Scanned commit 9a34acf03cb818ff3f8bc40e44176e277a25cbb9 (2026-09-15). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

A single npm entrypoint (`index.js` → `lib/express.js`) exposes a factory, `createApplication()`, that returns a callable function decorated with the application prototype and EventEmitter. Five runtime modules split responsibility: `application.js` (settings, dispatch, mounting, rendering), `request.js` and `response.js` (prototypes grafted onto `http.IncomingMessage`/`http.ServerResponse`), `view.js` (template lookup), and `utils.js` (compilers for etag/query/trust). The runtime boundary is deliberately thin — routing, body parsing and static file serving are re-exported from sibling npm packages rather than implemented here. There is no persistent storage; all state is per-app in-memory objects. Distribution is npm-only, driven by a GitHub release event.
- `index.js` is a three-line re-export of `lib/express.js`, and `package.json` restricts the published tarball to `LICENSE`, `Readme.md`, `index.js` and `lib/` — so `test/` and `examples/` never ship. — [index.js](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/index.js) [package.json#L95-L100](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/package.json#L95-L100)
- `createApplication()` builds `app` as a closure that forwards to `app.handle(req, res, next)`, then uses `merge-descriptors` to mixin `EventEmitter.prototype` and the `application` proto (both with `redefine=false`), and finally calls `app.init()`. — [lib/express.js#L36-L56](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/express.js#L36-L56)
- Per-app request/response prototypes are created with `Object.create(req, { app: {...value: app} })`, which is why every `req`/`res` getter can reach `this.app.get('trust proxy fn')` without a closure. — [lib/express.js#L44-L51](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/express.js#L44-L51) [lib/request.js#L297-L343](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/request.js#L297-L343)
- Routing is not implemented in this repo: `lib/express.js` requires the external `router` package and re-exports `Router` and `Router.Route`; `app.router` is a lazy getter that instantiates `new Router({ caseSensitive, strict })` on first access. — [lib/express.js#L19-L71](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/express.js#L19-L71) [lib/application.js#L59-L84](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/application.js#L59-L84) [package.json#L52](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/package.json#L52)
- Body parsing is a pure re-export — `express.json`, `express.raw`, `express.text`, `express.urlencoded` all point straight at `body-parser`, and `express.static` at `serve-static`. — [lib/express.js#L77-L81](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/express.js#L77-L81) [test/exports.js#L11-L35](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/test/exports.js#L11-L35)
- All per-app state lives in three null-prototype objects created in `app.init()` — `this.cache` (compiled views), `this.engines` (extension→renderer), `this.settings` — plus `this.locals`; there is no database or persistence layer anywhere in `lib/`. — [lib/application.js#L59-L66](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/application.js#L59-L66) [lib/application.js#L118-L128](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/application.js#L118-L128)
- `app.handle()` is the single dispatch boundary: it builds a `finalhandler` terminator, sets `X-Powered-By`, wires the `req.res`/`res.req` circular refs, swaps both prototypes with `Object.setPrototypeOf`, and delegates to `this.router.handle`. — [lib/application.js#L152-L182](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/application.js#L152-L182)
- The external integration surface is 28 runtime dependencies, of which the load-bearing ones are `proxy-addr` (trust proxy), `qs`/`node:querystring` (query), `send`+`serve-static` (file IO), `etag`+`fresh` (conditional GET), `cookie`+`cookie-signature`, and `finalhandler`. — [package.json#L27-L56](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/package.json#L27-L56) [lib/utils.js#L16-L23](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/utils.js#L16-L23) [lib/response.js#L15-L36](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/response.js#L15-L36)
- There is no build step. The npm scripts are `lint` (eslint), `test` (mocha over `test/` and `test/acceptance/` with `--check-leaks`), `test-ci` (nyc → lcovonly), `test-cov` (nyc → html) and `test-tap`. — [package.json#L101-L107](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/package.json#L101-L107)
- CI runs a 2-OS × 9-Node matrix (ubuntu/windows × Node 18–26) in `ci.yml`, with a separate `legacy.yml` still exercising Node 16 and 17 despite `engines.node` declaring `>= 18`. — [.github/workflows/ci.yml#L44-L52](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/.github/workflows/ci.yml#L44-L52) [.github/workflows/legacy.yml#L30-L36](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/.github/workflows/legacy.yml#L30-L36) [package.json#L91-L93](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/package.json#L91-L93)
- Deployment is npm publish triggered by GitHub release `published`; the workflow derives the dist-tag from `package.json` version rather than the release branch (`next` for prereleases, `latest` for the newest major, `latest-<major>` for maintenance lines). — [.github/workflows/npm-publish.yml#L37-L79](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/.github/workflows/npm-publish.yml#L37-L79)
- Supply-chain hardening is explicit: `.npmrc` disables lockfiles, enforces a 7-day minimum release age, sets `ignore-scripts=true` and `allow-git=none`; every Action in CI is pinned to a full commit SHA. — [.npmrc](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/.npmrc) [.github/workflows/ci.yml#L28-L35](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/.github/workflows/ci.yml#L28-L35) [.github/workflows/scorecard.yml#L34-L40](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/.github/workflows/scorecard.yml#L34-L40)
- `app.listen()` is a thin wrapper over `http.createServer(this)` that only adds `once`-wrapped error forwarding when the last argument is a callback — HTTPS is left to the caller. — [lib/application.js#L598-L607](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/application.js#L598-L607) [test/app.listen.js#L7-L26](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/test/app.listen.js#L7-L26)
- Observability is limited to two `debug` namespaces, `express:application` and `express:view`; runtime errors reaching `finalhandler` are console-logged via `logerror` unless `env === 'test'`. — [lib/application.js#L17](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/application.js#L17) [lib/application.js#L615-L618](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/application.js#L615-L618) [lib/view.js#L18](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/view.js#L18)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
