---
title: "How We Design Production-Ready NestJS Backends"
canonical: https://zarki.tech/insights/production-ready-nestjs-backends
---

# How We Design Production-Ready NestJS Backends

The NestJS shape we keep using for production APIs: modules as boundaries, boring auth, explicit events, and observability you can run at 2am.

By Antoine Khoury Abboud. Published 2026-08-21. Updated 2026-08-21.

NestJS is easy to start and easy to turn into a decorated junk drawer. Production-ready, for us, means a backend an engineer who did not write it can still operate.

That requirement comes from the work, not from a style guide. [In-Out Concepts](/#work) is a construction platform with event-sourced bones and zero-downtime delivery. [Meaco](/#work) unified fragmented internal workflows. Those systems cannot depend on “the person who knows.”

Here is the NestJS shape we keep returning to.

## Modules are bounded contexts, not folders

A `vehicles` module that imports half the company is not a module. It is a namespace.

We split by **change frequency and ownership**:

- identity / tenancy
- the core domain (bookings, sites, sessions)
- integrations (payments, storage, WhatsApp)
- admin / reporting (read models are allowed to be separate)

Controllers stay thin. Domain logic does not live in DTOs. If a use-case is a paragraph, it is a service method with a name a human would say out loud.

## Auth is a gate, not a decoration

`@Roles('admin')` sprinkled after the fact is how you get a leak.

We:

- resolve the tenant and the actor first
- pass a `RequestContext`, not a pile of optional IDs
- deny by default on admin routes
- test the negative cases

Multi-tenant construction and dealership products made this unglamorous and mandatory.

## Events where it counts

Not everything needs to be event-sourced. Inventory of mistakes does.

We use domain events when:

- other modules must react (booking confirmed → notification, invoice, calendar)
- we will be asked “what happened?” six months later
- write contention is real

CRUD for settings. Events for money, safety, and anything that ships a crew or a car.

On In-Out, event-sourcing was not a fashion. Sites cannot rewind a week of WhatsApp. The log is the product.

## Observability is part of the build

A production Nest app we ship has:

- structured logs with request and tenant IDs
- traces on the slow boundaries (DB, HTTP, queues)
- health that checks dependencies, not just `pong`
- migrations that run as a release step, not as folklore

Zero-downtime is a release habit. It is also a schema habit. Expand/contract beats “take it down on Friday.”

## What we skip

- GraphQL by default. Most of these products need a clear command API and a few read models.
- Shared “god” Prisma service used from every controller.
- Microservices on week one. A modular monolith with events will carry you until it won’t — and you will know when it won’t.

For the product side of the same discipline, read [booking platforms](/insights/building-scalable-booking-platforms). For the mobile clients these APIs serve, [React Native vs native](/insights/react-native-vs-native-2026).
