This is one of the most common backend interview questions: “Why Express over Fastify?” or “When would you use NestJS?” Let’s break down what actually differs.
The 30-second version
- Express — the default. Old, stable, huge ecosystem, unopinionated.
- Koa — Express’s spiritual successor. Async/await first, no built-in router or body parser.
- Fastify — Express-like API but ~2x faster. Schema-based validation built-in.
- NestJS — Opinionated framework on top of Express (or Fastify). TypeScript, decorators, DI — basically Angular for the backend.
*Express 5 has better async error propagation, but Express 4 (still dominant) needs try/catch or wrappers.
Express
The default choice. Used everywhere — old projects, tutorials, Stack Overflow answers. The ecosystem (middlewares, integrations, Stack Overflow answers) is unmatched.
const express = require('express');
const app = express();
app.get('/users/:id', (req, res) => {
res.json({ id: req.params.id });
});
Pick when: building a typical REST API, team already knows it, need a specific middleware.
Koa
Built by the same team that made Express. Smaller, async-first, uses a ctx (context) object instead of req, res. No bundled router or body parser — you install separately.
const Koa = require('koa');
const app = new Koa();
app.use(async (ctx) => {
ctx.body = { hello: 'world' };
});
Pick when: you want a clean async-first base and don’t mind assembling pieces yourself. Honestly, Koa is fading — Fastify ate its lunch.
Fastify
Express-like API but with serious engineering behind perf. Uses JSON Schema for validation AND fast serialization (it compiles a fast JSON.stringify from your schema). Built-in logger (Pino), plugins for everything.
const fastify = require('fastify')({ logger: true });
fastify.get('/users/:id', async (req) => {
return { id: req.params.id };
});
fastify.listen({ port: 3000 });
Pick when: you need high throughput, want schema validation built-in, starting a new project without legacy Express middleware to keep.
NestJS
A full framework — controllers, services, modules, dependency injection. Heavy use of TypeScript decorators. Feels like Spring Boot or Angular.
@Controller('users')
export class UsersController {
@Get(':id')
findOne(@Param('id') id: string) {
return { id };
}
}
Pick when: large team, large codebase, want enforced structure, building something complex with many modules. Overkill for a 5-route service.
The interview answer
“Express is the safe default — huge ecosystem, easy hiring. We’d pick Fastify for high-throughput APIs where the 2x perf actually matters, since it has Express-like DX with schema validation built in. NestJS makes sense for large teams that benefit from enforced structure and DI — but it’s overhead for small services. Koa is mostly legacy at this point.”
That’s the call. The framework rarely matters as much as the team’s familiarity with it.