2

Microserviços com Node.js: Comunicação, Resiliência e Observabilidade

Um serviço HTTP que chama outro serviço HTTP que chama outro serviço HTTP. Quando o terceiro demora 5 segundos para responder, o primeiro segura a conexão, o segundo acumula requests na fila, e o usuário vê um spinner eterno. Três serviços, um único ponto de falha cascateado.

Microserviços não resolvem problemas de complexidade: eles redistribuem a complexidade para a rede. E a rede falha. A questão não é SE um serviço vai ficar indisponível, mas QUANDO, e como o sistema se comporta nesse cenário.

Este post cobre três pilares que separam microserviços funcionais de microserviços frágeis: comunicação (síncrona e assíncrona), resiliência (circuit breaker, retry, timeout) e observabilidade (tracing distribuído com OpenTelemetry).

Comunicação síncrona vs assíncrona: quando usar cada uma

A escolha entre HTTP direto e mensageria define o acoplamento temporal entre serviços. Se o serviço A precisa da resposta do serviço B para continuar, a comunicação é síncrona. Se o serviço A dispara um evento e segue em frente, é assíncrona.

CritérioHTTP síncronoMensageria assíncrona
Latência percebidaSoma das latências de toda a cadeiaResposta imediata ao cliente, processamento em background
Acoplamento temporalAlto: se B cai, A falhaBaixo: se B cai, a mensagem espera na fila
Complexidade de debugMenor (request/response linear)Maior (mensagens em filas, ordem não garantida, dead letter queues)
Consistência de dadosMais fácil de garantir por transaçãoEventual consistency, exige idempotência
Caso de uso típicoConsulta de dados em tempo real, validaçãoProcessamento de pedidos, envio de e-mails, geração de relatórios

Se o usuário precisa ver o resultado na mesma request (consulta de saldo, validação de CPF), use HTTP. Se o resultado pode chegar depois (confirmação de pagamento, geração de PDF), use mensageria. Já cobrimos o lado assíncrono em detalhes no post sobre mensageria com BullMQ e Redis.

Chamadas HTTP entre serviços com timeout e retry

Uma chamada HTTP entre serviços sem timeout é uma bomba-relógio. O default do Node.js (runtime que usa libuv para I/O) para http.request não tem timeout de resposta: ele espera indefinidamente. Isso significa que um serviço lento trava quem o chama.

// src/infra/http-client.ts
import { setTimeout } from "node:timers/promises";

interface RetryConfig {
  maxRetries: number;
  baseDelayMs: number;
  timeoutMs: number;
}

const DEFAULT_CONFIG: RetryConfig = {
  maxRetries: 3,
  baseDelayMs: 200,
  timeoutMs: 3000,
};

export async function fetchWithRetry(
  url: string,
  options: RequestInit = {},
  config: RetryConfig = DEFAULT_CONFIG
): Promise<Response> {
  let lastError: Error | null = null;

  for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
    try {
      const controller = new AbortController();
      // Timeout via AbortController: se o serviço não responder
      // em timeoutMs, a request é cancelada no nível de socket
      const timeoutId = globalThis.setTimeout(
        () => controller.abort(),
        config.timeoutMs
      );

      const response = await fetch(url, {
        ...options,
        signal: controller.signal,
      });

      clearTimeout(timeoutId);

      // Retry apenas em erros de servidor (5xx), não em 4xx
      // porque 4xx indica erro do chamador, não indisponibilidade
      if (response.status >= 500 && attempt < config.maxRetries) {
        lastError = new Error(`HTTP ${response.status} from ${url}`);
        const delay = config.baseDelayMs * Math.pow(2, attempt);
        await setTimeout(delay);
        continue;
      }

      return response;
    } catch (error) {
      lastError = error as Error;

      if (attempt < config.maxRetries) {
        // Exponential backoff: 200ms, 400ms, 800ms
        // Evita thundering herd quando o serviço volta
        const delay = config.baseDelayMs * Math.

---

Leia o artigo completo em [https://www.vivodecodigo.com.br/backend/microservicos-nodejs-comunicacao-resiliencia-observabilidade](https://www.vivodecodigo.com.br/backend/microservicos-nodejs-comunicacao-resiliencia-observabilidade)
Carregando publicação patrocinada...