Microservices and Performance

@MessagePattern vs @EventPattern?

@MessagePattern is request-response: the client calls client.send(pattern, data), exactly one handler replies, and the caller waits (convert with firstValueFrom, add a timeout). @EventPattern is fire-and-forget: client.emit(pattern, data), zero or many handlers react, no reply. Use messages for "reserve stock?" and events for "order placed".

Which transport would you choose: TCP, Redis, RabbitMQ or Kafka?

  • TCP: simple, internal request-response, no broker. No durability.
  • Redis: lightweight pub/sub if you already run Redis; messages are lost if nobody listens.
  • RabbitMQ: reliable work queues with acknowledgements and retries (invoices, emails).
  • Kafka: high-throughput durable event log, consumer groups, replay (order events, analytics).
  • gRPC: typed, fast synchronous calls between services.

How would you improve the performance of a slow NestJS API?

  • Measure first: logs with response time, APM/tracing, slow query log.
  • Database: add indexes for filters/sorts, fix N+1 (include/joins, DataLoader), paginate with limits, select only needed fields.
  • Cache hot reads in Redis (cache-aside with invalidation); HTTP caching headers/CDN for public GETs.
  • Move slow work (emails, PDFs, third-party calls) to BullMQ queues.
  • Run multiple instances (pm2 cluster / containers); consider the Fastify adapter; enable compression at the proxy.
  • Avoid REQUEST-scoped providers on hot paths.

How do you implement rate limiting, and what changes when you run several instances?

Use @nestjs/throttler: ThrottlerModule.forRoot([{ ttl: 60_000, limit: 100 }]), a global ThrottlerGuard, @Throttle() for stricter routes (login, OTP) and @SkipThrottle() for health checks. The default storage is in-memory per process, so with N instances a client gets N times the limit; use a shared Redis storage. Behind a proxy, enable trust proxy so the real client IP is used.