NestJS vs Express vs Hapi vs Koa: When to Pick Which
A practical comparison of popular Node.js frameworks for APIs and microservices—structure, ergonomics, and team fit.
There is no single “best” Node.js framework—only the best fit for your team, timeline, and system shape. Here is how I choose between NestJS, Express, Hapi, and Koa in real projects.
Express
Strengths: Minimal, huge ecosystem, every developer knows it. Fast to prototype.
Trade-offs: Structure is up to you. Large codebases need discipline (modules, DI, validation) or they become spaghetti.
Use when: Small services, internal tools, or teams with strong conventions already in place.
NestJS
Strengths: Opinionated modules, DI, pipes/guards, TypeScript-first. Feels familiar if you come from Spring or Angular.
Trade-offs: Learning curve and ceremony. Overkill for a tiny CRUD API.
Use when: Multi-team microservices, CRM/campaign backends, or anywhere you want enforced structure and OpenAPI/Swagger out of the box.
Hapi
Strengths: Built-in validation (Joi), plugin ecosystem, explicit request lifecycle. Good for config-heavy APIs.
Trade-offs: Less momentum than Express/Nest in new greenfield work, but still solid in enterprise Node.
Use when: You need strong input validation and plugin boundaries without assembling everything yourself.
Koa
Strengths: Modern middleware (async/await), lightweight core, composable context.
Trade-offs: Like Express, you bring your own structure. Smaller community than Express.
Use when: You want a slim core and full control over middleware stack—often in custom gateways or BFF layers.
Quick decision matrix
| Need | Lean toward | |------|-------------| | Fast MVP | Express | | Large typed codebase | NestJS | | Plugin + validation focus | Hapi | | Minimal core, custom stack | Koa |
Takeaway
I have shipped NestJS on multi-tenant CRM and payment services, and Express/Koa on lighter services. Pick for maintainability at 2-year horizon, not hype. Standardize logging, validation, and error shapes regardless of framework.