Skip to content

Systems & architecture

NestJS in production

One NestJS modular monolith, from the request lifecycle and module boundaries, through background jobs that never lose work, to passkeys and sessions done right.

3 parts67 min readUpdated Sep 5, 2026

Parts

  1. Part 1

    NestJS in production: the request lifecycle, dependency injection and module boundaries that scale

    What NestJS does under the hood — the order of middleware, guards, interceptors, pipes and filters; DI, scopes and durable providers; dynamic modules — and how to use it to structure a large API as a clean modular monolith with a consistent error model, request context and graceful shutdown.

    22 min

  2. Part 2

    Reliable background jobs in NestJS with BullMQ: retries, idempotency and the transactional outbox

    How to build background jobs in NestJS 12 with BullMQ 6 that never silently lose work and never charge a customer twice: at-least-once delivery and idempotency, the transactional outbox, retries with error classification, dead letters, rate limiting, graceful shutdown and observability.

    25 min

  3. Part 3

    NestJS Auth Done Right: Passkeys, Sessions vs JWT, and Refresh Token Rotation

    An honest authentication design for a NestJS API and a Next.js frontend: when to use sessions, when to use JWT, how to rotate refresh tokens with reuse detection, passkey sign-in with SimpleWebAuthn, and the guards, rate limits and CSRF protection that go with it.

    20 min

Series review

0/6 answered · 0 correct

6 questions drawn from the parts of this series. Answers here count toward each post's own quiz.

  1. Question 1 of 6IntermediateIn the chain OrdersController → OrdersService → OrderRepository → TenantContext, only TenantContext is REQUEST scoped. What happens to the other providers?
  2. Question 2 of 6IntermediateTwo feature modules, orders and payments, import each other through forwardRef. Which fix matches the post's approach?
  3. Question 3 of 6IntermediateWhy is await orders.save(order); await queue.add('capture-payment', ...) unsafe, and how does an outbox address the root cause?
  4. Question 4 of 6StarterBullMQ delivers jobs at-least-once. What realistic goal does the post propose for jobs with consequences?
  5. Question 5 of 6IntermediateYour team uses 7-day JWT access tokens because they are "stateless and fast". Product then asks to "lock a hijacked account immediately". What is most accurate?
  6. Question 6 of 6AdvancedWith refresh token rotation, an already-used refresh token shows up at the server again. Why should the server revoke the whole family instead of just rejecting that request?

Other series

Series