Home > Blog > Desenvolvimento Web
Desenvolvimento Web
JavaScript
Programação

gRPC no Node.js: Protobuf, TLS e retries

Atualizado em: 28 de outubro de 2026

Terminal Linux usado em desenvolvimento e administração de aplicações Node.js

gRPC no Node.js permite criar APIs de alto desempenho baseadas em contratos Protobuf e HTTP/2. Em vez de definir endpoints e JSON manualmente, cliente e servidor compartilham um arquivo .proto que descreve serviços, métodos e mensagens.

O modelo é útil para comunicação interna entre serviços, sistemas poliglotas, chamadas com tipos bem definidos e streaming bidirecional. Ele não elimina a necessidade de autenticação, deadlines, observabilidade e compatibilidade de contratos.

Pacotes principais

npm install @grpc/grpc-js @grpc/proto-loader

@grpc/grpc-js é a implementação em JavaScript puro. @grpc/proto-loader carrega arquivos Protobuf em tempo de execução.

Definindo o contrato

syntax = "proto3";

package catalog.v1;

service CatalogService {
  rpc GetProduct(GetProductRequest) returns (Product);
}

message GetProductRequest {
  string id = 1;
}

message Product {
  string id = 1;
  string name = 2;
  int64 price_cents = 3;
}

Não reutilize números de campos removidos. Preserve compatibilidade conforme o contrato evolui. Consulte Protobuf no Node.js.

Carregando o proto

import grpc from '@grpc/grpc-js';
import protoLoader from '@grpc/proto-loader';

const definition = protoLoader.loadSync('catalog.proto', {
  keepCase: false,
  longs: String,
  enums: String,
  defaults: true,
  oneofs: true
});

const descriptor = grpc.loadPackageDefinition(definition);
const catalog = descriptor.catalog.v1;

Decida explicitamente como representar int64. JavaScript não representa todos os inteiros de 64 bits com precisão em number.

Implementando o servidor

const server = new grpc.Server();

server.addService(catalog.CatalogService.service, {
  async getProduct(call, callback) {
    try {
      const product = await repository.findById(call.request.id);

      if (!product) {
        return callback({
          code: grpc.status.NOT_FOUND,
          message: 'Produto não encontrado'
        });
      }

      callback(null, {
        id: product.id,
        name: product.name,
        priceCents: String(product.priceCents)
      });
    } catch (error) {
      callback({
        code: grpc.status.INTERNAL,
        message: 'Erro interno'
      });
    }
  }
});

Não devolva stack traces ou mensagens de banco ao cliente. Traduza erros de domínio para status gRPC estáveis.

Iniciando com TLS

const credentials = grpc.ServerCredentials.createSsl(
  rootCertificates,
  [{ private_key: privateKey, cert_chain: certificateChain }],
  false
);

server.bindAsync('0.0.0.0:50051', credentials, error => {
  if (error) throw error;
  server.start();
});

Em ambientes internos, TLS continua importante. Para autenticação mútua, exija certificado do cliente e valide a identidade.

Criando o cliente

const client = new catalog.CatalogService(
  'catalog.internal:50051',
  grpc.credentials.createSsl(rootCa)
);

client.getProduct(
  { id: 'p-10' },
  { deadline: Date.now() + 1000 },
  (error, response) => {
    if (error) {
      console.error(error.code, error.details);
      return;
    }
    console.log(response);
  }
);

Toda chamada deve ter deadline. Sem limite, conexões lentas podem consumir recursos indefinidamente.

Status codes

Use códigos coerentes:

  • INVALID_ARGUMENT: entrada inválida;
  • NOT_FOUND: recurso ausente;
  • ALREADY_EXISTS: conflito de criação;
  • FAILED_PRECONDITION: estado incompatível;
  • UNAUTHENTICATED: credencial ausente ou inválida;
  • PERMISSION_DENIED: identidade sem acesso;
  • RESOURCE_EXHAUSTED: quota ou capacidade;
  • UNAVAILABLE: falha temporária;
  • INTERNAL: erro inesperado.

Metadata

const metadata = new grpc.Metadata();
metadata.set('authorization', `Bearer ${token}`);
metadata.set('x-request-id', requestId);

client.getProduct(request, metadata, options, callback);

Metadata é semelhante a headers. Valide tamanho e allowlist. Não registre tokens.

Autenticação

O servidor pode ler metadata:

function authenticate(call) {
  const values = call.metadata.get('authorization');
  const value = values[0];

  if (typeof value !== 'string') {
    throw createGrpcError(grpc.status.UNAUTHENTICATED, 'Token ausente');
  }

  return verifyToken(value);
}

Autenticação deve ocorrer antes da lógica de negócio. Autorização ainda precisa considerar recurso, tenant e ação.

Validação

Protobuf garante estrutura binária, não regras de negócio. Valide tamanho, formato e limites:

if (!call.request.id || call.request.id.length > 100) {
  return callback({
    code: grpc.status.INVALID_ARGUMENT,
    message: 'id inválido'
  });
}

Unary versus streaming

Uma chamada unary possui uma requisição e uma resposta. gRPC também oferece server streaming, client streaming e bidirectional streaming. Escolha streaming apenas quando o fluxo incremental traz benefício real.

Compatibilidade de schema

Adicionar campos opcionais geralmente é compatível. Remover ou alterar significado exige cuidado. Marque números removidos como reserved:

message Product {
  reserved 4;
  reserved "legacy_code";
  string id = 1;
}

Geração de código

Projetos maiores podem gerar clientes e tipos durante o build, reduzindo parsing dinâmico e melhorando integração com TypeScript. Fixe versões do compilador e plugins no CI.

Load balancing

O cliente gRPC mantém conexões HTTP/2 longas. Balanceadores L4, DNS e service mesh precisam ser configurados considerando multiplexação. Um balanceador HTTP tradicional pode concentrar tráfego em poucas conexões.

Retries

Repita apenas status transitórios e operações idempotentes. Um método de criação pode concluir no servidor e perder a resposta. Use idempotency key ou identificador fornecido pelo cliente.

Consulte Retry com Backoff no Node.js.

Keepalive

Keepalive detecta conexões quebradas, mas configurações agressivas podem sobrecarregar servidores e proxies. Ajuste cliente e servidor de forma compatível.

Tamanho de mensagens

Defina limites de envio e recebimento. gRPC não deve transportar arquivos enormes sem necessidade. Para objetos grandes, use object storage e envie referência autorizada.

Observabilidade

Registre:

  • serviço e método;
  • status code;
  • duração;
  • deadline restante;
  • bytes enviados e recebidos;
  • retries;
  • identidade técnica;
  • trace ID.

Não use IDs de usuário como labels de métricas. Integre com OpenTelemetry e propagação de contexto.

Health checking

Implemente o protocolo padrão de health checking para que orquestradores e balanceadores consultem disponibilidade. O processo estar vivo não significa que o serviço está pronto.

Shutdown gracioso

process.once('SIGTERM', () => {
  server.tryShutdown(error => {
    if (error) server.forceShutdown();
  });
});

Pare de aceitar novas chamadas, aguarde as ativas dentro de um prazo e force o encerramento somente ao final.

Testes

  • contrato carregado;
  • resposta de sucesso;
  • entrada inválida;
  • não encontrado;
  • autenticação e autorização;
  • deadline excedida;
  • mensagem acima do limite;
  • indisponibilidade transitória;
  • compatibilidade entre versões;
  • shutdown com chamada ativa.

Erros comuns

  • chamada sem deadline;
  • usar number para int64 sem avaliar precisão;
  • vazar erro interno;
  • reutilizar field numbers;
  • retries em métodos não idempotentes;
  • mensagens enormes;
  • conexão sem TLS;
  • confundir autenticação com autorização;
  • não observar status codes.

Conclusão

gRPC no Node.js oferece contratos tipados, HTTP/2 e diferentes modelos de streaming para comunicação entre serviços. O ganho de desempenho e consistência depende de um desenho cuidadoso de schemas e operações.

Use deadlines, TLS, validação, status codes estáveis e compatibilidade Protobuf. Trate observabilidade, retries e shutdown como partes do protocolo, não como detalhes posteriores.

Consulte a documentação oficial de gRPC para Node.js e o repositório grpc-node.

10 melhores cursos de programação em 2026

Descubra os melhores cursos de programação. Aprenda a escolher o curso ideal para iniciar ou avançar na carreira de desenvolvedor

POSTS RELACIONADOS

Ver todos

Seta para a direita