ADR: Framework Selection
Choosing Express 5, Fastify 5, or NestJS 11 shapes hiring, performance, and test strategy for years. This ADR template scores options against measurable squad constraints - not framework religion.
Search across all documentation pages
Choosing Express 5, Fastify 5, or NestJS 11 shapes hiring, performance, and test strategy for years. This ADR template scores options against measurable squad constraints - not framework religion.
Quick-reference recipe card - copy-paste ready.
# ADR-NNN: HTTP Framework for <Service>
## Status
Proposed | Accepted | Superseded by ADR-XXX
## Context
- Endpoints: N REST (+ GraphQL?)
- Team: M engineers, hiring pipeline
- SLO: p95 latency, RPS peak
- Existing: Express 4 monolith? shared auth package?
## Scoring (1-5, weight in parentheses)
| Criterion | Weight | Express 5 | Fastify 5 | NestJS 11 |
| --- | --- | --- | --- | --- |
| Throughput / latency | 25% | | | |
| Team familiarity | 20% | | | |
| Structure at scale | 20% | | | |
| Testing ergonomics | 15% | | | |
| Ecosystem / middleware | 10% | | | |
| Migration cost | 10% | | | |
| **Weighted total** | | | | |
## Decision
We will use <framework> because <one sentence>.
## Consequences
### Positive
- ...
### Negative
- ...
## Review Trigger
Revisit when endpoints > X or p95 exceeds Y under load test.When to reach for this:
# ADR-003: HTTP Framework for Orders API
## Status
Accepted (2026-07-09)
## Context
- B2B orders API: 42 REST endpoints, webhooks, no GraphQL
- Squad: 6 engineers, 2 familiar with Nest, 4 with Express
- SLO: p95 200ms at 8k RPS peak; error budget 99.9%
- Greenfield service; shared `@acme/auth` Fastify plugin exists
- Node 24.18.0, TypeScript 5.6, Postgres + Prisma
## Scoring
| Criterion | Weight | Express 5 | Fastify 5 | NestJS 11 |
| --- | --- | --- | --- | --- |
| Throughput / latency | 25% | 3 | 5 | 4 |
| Team familiarity | 20% | 4 | 3 | 3 |
| Structure at scale | 20% | 2 | 4 | 5 |
| Testing ergonomics | 15% | 3 | 5 | 4 |
| Ecosystem | 10% | 5 | 4 | 4 |
| Migration cost | 10% | 5 | 4 | 3 |
| **Weighted** | | 3.35 | **4.30** | 3.95 |
## Decision
**Fastify 5** with modular plugins and shared `@acme/auth-fastify`.
NestJS rejected: DI overhead unjustified below 60 endpoints and no microservices split planned.
## Consequences
### Positive
- `inject()` tests without port binding
- JSON schema validation compiled at boot
- Reuse internal Fastify auth plugin
### Negative
- Juniors learn plugin encapsulation curve
- Fewer Stack Overflow answers than Express
- Hiring: spell out Fastify in JD
## Node.js Notes
- Pino logging built-in; align with platform OTel SDK
- Express 5 migration path documented if acquisition forces it (ADR supersede candidate)
## Review Trigger
- Endpoint count > 80 OR second squad owns same deployable
- p95 > 250ms after DB tuning (don't blame framework first)What this demonstrates:
| Criterion | Measure |
|---|---|
| Throughput | autocannon or k6 on hello-world + typical JSON handler |
| Structure | Modules without god app.ts; Nest modules vs Fastify plugins |
| Testing | inject() / supertest speed; DI mock cost in Nest |
| Ecosystem | Passport, rate-limit, OpenAPI generators you need |
| Migration | Person-weeks from current codebase |
| Framework | Sweet spot | Watch out |
|---|---|---|
| Express 5 | Familiarity, vast middleware | Easy to build unmaintainable monolith |
| Fastify 5 | Performance, schema-first | Plugin encapsulation learning curve |
| NestJS 11 | Large teams, modular monolith | Cold start and DI overhead on tiny APIs |
| Alternative | Use When | Don't Use When |
|---|---|---|
| Hono | Edge + small API | Heavy Nest-style DI needs |
| tRPC | TS monolith front+back | Public REST API contract required |
| Spike only, no ADR | 2-week throwaway | Production service |
Express 5 is the current major with improved routing and promise rejection handling. New ADRs should cite Express 5 on Node 24.
Nest uses Fastify adapter - valid ADR outcome. Document adapter choice in Node.js Notes.
Tech lead authors; EM acknowledges delivery impact; platform architect for org-wide alignment.
Stack versions: This page was written for Node.js 24.18.0 (Active LTS), npm 10+, TypeScript 5.6+, Express 5, Fastify 5, and NestJS 11.
Reviewed by Chris St. John·Last updated Jul 16, 2026