← WritingBackend · Mar 2026 · 6 min

Why I left Express for NestJS in 2024

After seven projects on Express, I moved my default backend to NestJS. Not because Express is bad — because my projects stopped being small.

Express is a great router with a great ecosystem, and for a weekend API it is still what I would reach for. The problem showed up around the fourth client project that needed auth, roles, validation, file uploads, and a job queue: every Express codebase I wrote solved those the way past-me felt like solving them that month. Six months later, onboarding myself back into my own code was the slow part of every change request.

NestJS makes the boring decisions for me. Modules give every feature the same shape, dependency injection makes services testable without ceremony, and decorators put validation and access control next to the route they protect. When I hand a project to a client's team, the documentation is effectively 'this is a standard Nest app' — that sentence has real monetary value in a handoff.

The costs are real too: more files, more abstraction, a steeper start for juniors, and you will fight the framework if your problem doesn't fit a controller-service-repository shape. For tiny services I still skip it. But for the 200-hour-plus builds that make up most of my work — storefronts, admin panels, anything with roles — the structure pays for itself by the second month.

The practical migration advice: don't rewrite. I moved one Express project to Nest incrementally by mounting the legacy router inside a Nest app and migrating route by route as features got touched. Three months later the legacy router was empty and nothing had broken in production.