NestJS is the framework we pick for Node.js backends that several developers will work on for years. We design, build and rescue NestJS applications: REST and GraphQL APIs, multi-module products, queue-driven services, and migrations from Express. This page explains when Nest fits, when it does not, and how we build with it.
When does NestJS fit, and when does it not?
NestJS gives a Node.js backend a fixed shape: modules, controllers, providers and dependency injection. That shape costs some boilerplate and pays back as the codebase and the team grow. Smaller tools win in other cases.
| Framework | Best for | Trade-off |
|---|---|---|
| NestJS | Products with many modules, teams of three or more, long-lived APIs | More ceremony; slower to start than a single file |
| Express | Small services, prototypes, existing apps you will not restructure | No structure; every team invents its own |
| Fastify | Fast, lean HTTP services with a good plugin model | You design the architecture yourself |
| Hono | Edge and serverless handlers, very small APIs | Fewer batteries for large domain logic |
Nest is not a rival to Express or Fastify. It runs on one of them as its HTTP layer, so you can pick Fastify under Nest when throughput matters. If your backend is a handful of endpoints, we will tell you that plain Fastify is enough. Our wider backend development page covers how we choose across stacks.
How do we structure a NestJS application?
The structure is the product of the framework, so we use it deliberately.
- Modules per domain. Billing, accounts and notifications each get a module with a public surface. Other modules import only what a module exports. This is what keeps a monolith splittable later.
- Providers and dependency injection. Services receive their dependencies through the constructor, which makes them easy to replace in tests and easy to read.
- Guards, pipes and interceptors. Authorisation, input validation and response shaping live in one place instead of being repeated in handlers.
- Configuration and data access. Typed configuration loaded at startup, and a data layer on PostgreSQL through an ORM or query builder chosen with the team. We keep migrations in version control and run them in CI.
Because Nest is TypeScript from the first line, request types, database types and the frontend client can share definitions. Our TypeScript page covers how we set that up end to end.
REST, GraphQL and real-time in Nest
Nest handles all three, and a product often needs more than one.
REST is the default for public and partner APIs. We generate an OpenAPI document from the code so documentation and client SDKs never drift.
GraphQL fits when clients need to pick fields across related objects. Nest supports a code-first approach where the schema comes from TypeScript classes. We add query cost limits and batching early, because an open GraphQL endpoint is easy to overload. The trade-offs are laid out in REST vs GraphQL.
WebSockets serve live dashboards, notifications and collaborative screens through gateways that reuse the same guards as HTTP routes.
How do NestJS microservices work?
Nest includes a microservices layer where handlers listen for messages instead of HTTP calls. Supported transports include TCP, Redis, NATS, MQTT, RabbitMQ, Kafka and gRPC. We choose the transport from the delivery guarantee you need: a broker such as RabbitMQ or Kafka when messages must survive a restart, gRPC for typed calls between services.
We start with a modular monolith. One deployable, clear module boundaries, one database schema per domain. A module becomes a service when its load, release cadence or owning team demands it. That order avoids the distributed tangle that early splitting produces. A marketplace migration we ran followed the same pattern: five domains extracted one at a time from a PHP monolith, with P95 API latency down by about 65%.
How do we test a NestJS backend?
Nest ships a testing module that builds a small container with real or replaced providers. We write unit tests for service logic, integration tests that run controllers against a real PostgreSQL in CI, and end-to-end tests for the critical flows such as sign-up and payment. Contract tests protect the API from accidental breaking changes. Nothing reaches production without these running on the pull request.
Can we migrate an Express app to NestJS?
Yes, without stopping feature work. The route we use:
- Add Nest beside the Express app, sharing the same HTTP server.
- Write tests that pin current behaviour of the routes you will move.
- Move one route group at a time into a Nest module, then delete the Express version.
- Replace hand-rolled auth and validation with guards and pipes as each module lands.
Each step ships on its own, so there is no big-bang cutover to fail.
What does a NestJS project cost to own?
Drivers matter more than a headline number: how many modules and integrations, whether you need GraphQL or message brokers, how much existing code must be migrated, and the test coverage you require. We scope it after a short audit.
For a SaaS product, Nest is a common core of our stack, described on the SaaS development page. To add engineers to your own team, see hire NestJS developers.