DEV Community

Cover image for πŸš€ NestJS Microservices with RabbitMQ, Retries & DLQ β€” Production Setup That Actually Scales.
codingKrills
codingKrills

Posted on

πŸš€ NestJS Microservices with RabbitMQ, Retries & DLQ β€” Production Setup That Actually Scales.

πŸš€ NestJS Microservices with RabbitMQ, Retries & DLQ β€” Production Setup That Actually Scales

❌ Stop building fragile microservices that silently fail.
βœ… Start building systems that retry, recover, and scale automatically.

If you're using NestJS and not handling failures, retries, and dead-letter queues (DLQ) properly… your system will break in production. Period.

In this guide, I’ll show you a battle-tested architecture using NestJS + RabbitMQ with:

  • πŸ” Retries
  • πŸ’€ Dead Letter Queues (DLQ)
  • ⚑ Event-driven communication
  • 🧱 Scalable microservices

🧠 What You’ll Build

A real-world system with services like:

  • authentication
  • rbac
  • quotation
  • packages
  • generate-quotation-pdf
  • generate-quotation-ai
  • subscription-plans
  • user-subscriptions
  • notifications
  • send-otp

πŸ—οΈ Architecture Overview

API Gateway β†’ RabbitMQ β†’ Microservices (Consumers)
Enter fullscreen mode Exit fullscreen mode

πŸ‘‰ No direct service-to-service calls
πŸ‘‰ Fully async & decoupled


πŸ“ Monorepo Structure

nestjs-microservices/
β”‚
β”œβ”€β”€ apps/
β”‚   β”œβ”€β”€ api-gateway/
β”‚   β”œβ”€β”€ authentication/
β”‚   β”œβ”€β”€ rbac/
β”‚   β”œβ”€β”€ quotation/
β”‚   β”œβ”€β”€ packages/
β”‚   β”œβ”€β”€ generate-quotation-pdf/
β”‚   β”œβ”€β”€ generate-quotation-ai/
β”‚   β”œβ”€β”€ subscription-plans/
β”‚   β”œβ”€β”€ user-subscriptions/
β”‚   β”œβ”€β”€ notifications/
β”‚   └── send-otp/
β”‚
β”œβ”€β”€ libs/
β”‚   β”œβ”€β”€ rabbitmq/
β”‚   β”œβ”€β”€ common/
β”‚   β”œβ”€β”€ dto/
β”‚   β”œβ”€β”€ config/
β”‚   └── utils/
Enter fullscreen mode Exit fullscreen mode

πŸ‘‰ Clean separation = easy scaling


πŸ“‘ Messaging Setup (Core Idea)

Instead of this ❌

await this.authService.validateUser();
Enter fullscreen mode Exit fullscreen mode

We do this βœ…

this.client.send('auth.validate', payload);
Enter fullscreen mode Exit fullscreen mode

πŸ‘‰ Async, scalable, resilient


βš™οΈ RabbitMQ Configuration (DLQ + Retry)

ClientsModule.register([
  {
    name: 'RABBITMQ_SERVICE',
    transport: Transport.RMQ,
    options: {
      urls: [process.env.RABBITMQ_URL],
      queue: 'main_queue',
      queueOptions: {
        durable: true,
        deadLetterExchange: 'dlx',
        deadLetterRoutingKey: 'dlq',
      },
    },
  },
]);
Enter fullscreen mode Exit fullscreen mode

πŸ” Retry Mechanism (The Secret Sauce)

Main Queue β†’ Retry Queue (TTL) β†’ Main Queue β†’ DLQ
Enter fullscreen mode Exit fullscreen mode

Retry Queue Example:

{
  queue: 'quotation_retry',
  queueOptions: {
    messageTtl: 5000,
    deadLetterRoutingKey: 'quotation_queue',
  },
}
Enter fullscreen mode Exit fullscreen mode

πŸ‘‰ If a job fails β†’ wait 5s β†’ retry automatically


πŸ’€ Dead Letter Queue (DLQ)

When retries fail:

@EventPattern('quotation.dlq')
handleFailed(data: any) {
  console.error('DLQ Message:', data);
}
Enter fullscreen mode Exit fullscreen mode

πŸ‘‰ No silent failures anymore πŸ”₯


πŸ“€ Producer Example

@Injectable()
export class QuotationProducer {
  constructor(@Inject('RABBITMQ_SERVICE') private client: ClientProxy) {}

  createQuotation(data: any) {
    return this.client.emit('quotation.create', data);
  }
}
Enter fullscreen mode Exit fullscreen mode

πŸ“₯ Consumer Example

@EventPattern('quotation.create')
async handle(data: any, context: RmqContext) {
  const channel = context.getChannelRef();
  const message = context.getMessage();

  try {
    await this.service.process(data);
    channel.ack(message);
  } catch (e) {
    channel.nack(message, false, false); // goes to DLQ
  }
}
Enter fullscreen mode Exit fullscreen mode

⚑ Event-Driven Wins

Traditional API Event-Driven
Tight coupling ❌ Loose coupling βœ…
Blocking ❌ Async βœ…
Hard to scale ❌ Horizontally scalable βœ…

πŸ”₯ Real Use Cases

  • πŸ“© send-otp β†’ async SMS
  • πŸ“„ generate-quotation-pdf β†’ heavy processing
  • πŸ€– generate-quotation-ai β†’ AI calls
  • πŸ”” notifications β†’ emails, push

πŸ‘‰ Your API stays FAST ⚑


🧠 Production Best Practices

  • βœ… Use idempotency keys
  • βœ… Add correlation IDs
  • βœ… Monitor DLQ actively
  • βœ… Scale consumers independently
  • βœ… Separate queues per service
  • βœ… Validate DTOs strictly

🐳 Bonus: Run Everything with Docker

rabbitmq:
  image: rabbitmq:3-management
  ports:
    - "5672:5672"
    - "15672:15672"
Enter fullscreen mode Exit fullscreen mode

πŸ‘‰ Access dashboard β†’ http://localhost:15672


πŸ’£ Hard Truth

If your system doesn’t handle failure… it’s already broken.


πŸš€ Final Takeaway

Build microservices that don’t just β€œwork”… but recover, retry, and scale automatically.


🧠 TL;DR

  • Use NestJS + RabbitMQ
  • Prefer event-driven architecture
  • Implement retries + DLQ
  • Scale consumers independently
  • Never ignore failures

πŸ”₯ Want More?

If this helped you, I can next show:

  • ☸️ Kubernetes deployment (auto-scaling microservices)
  • πŸ“Š Monitoring with Prometheus + Grafana
  • πŸ” Full auth + API Gateway setup

Just comment: β€œPART 2” πŸ‘‡

Top comments (0)