Careeroza
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.