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

Schema Registry no Node.js

Atualizado em: 14 de setembro de 2026

Rack de servidores processando fluxos de dados no Node.js

O Schema Registry no Node.js centraliza contratos usados por produtores e consumidores de eventos. Em arquiteturas com Kafka, várias aplicações publicam e leem mensagens ao longo do tempo. Sem controle de schema, uma mudança simples — renomear um campo, alterar tipo ou remover propriedade — pode quebrar consumidores sem aviso.

Um registry armazena versões de schemas, verifica compatibilidade e entrega IDs usados na serialização. Em vez de colocar a definição completa em cada mensagem, o produtor registra o schema, recebe um identificador e serializa o payload em um formato como Avro, Protobuf ou JSON Schema.

Neste guia, você aprenderá a integrar Node.js com Schema Registry, registrar schemas, serializar mensagens, configurar compatibilidade, testar evolução, trabalhar com KafkaJS e evitar breaking changes.

O que é Schema Registry?

A documentação oficial do Confluent Schema Registry descreve um repositório central para schemas Avro, Protobuf e JSON Schema. O serviço fornece API REST, versionamento, validação de compatibilidade e suporte a serializers e deserializers.

O fluxo básico é:

  1. definir o schema;
  2. registrar no subject;
  3. receber um schema ID;
  4. serializar a mensagem;
  5. publicar no Kafka;
  6. o consumidor lê o ID;
  7. busca ou usa cache do schema;
  8. desserializa o payload.

Por que não usar JSON livre?

JSON sem contrato é simples no início, mas deixa problemas para produção:

  • campos obrigatórios desaparecem;
  • tipos mudam silenciosamente;
  • consumidores interpretam versões diferentes;
  • documentação fica desatualizada;
  • breaking changes chegam ao tópico;
  • validação é duplicada em cada serviço.

JSON Schema pode resolver parte disso, mas o registry adiciona versionamento e compatibilidade centralizados.

Integração com KafkaJS

Uma combinação comum usa KafkaJS e o cliente de Schema Registry:

npm install kafkajs @kafkajs/confluent-schema-registry
import { Kafka } from 'kafkajs';
import { SchemaRegistry } from '@kafkajs/confluent-schema-registry';

const kafka = new Kafka({
  clientId: 'orders-api',
  brokers: process.env.KAFKA_BROKERS.split(',')
});

const registry = new SchemaRegistry({
  host: process.env.SCHEMA_REGISTRY_URL
});

Para produtores e consumidores, consulte Kafka com Node.js.

Primeiro schema Avro

{
  "type": "record",
  "name": "OrderCreated",
  "namespace": "com.codigofacil.orders",
  "fields": [
    { "name": "orderId", "type": "string" },
    { "name": "customerId", "type": "string" },
    { "name": "totalCents", "type": "long" },
    { "name": "occurredAt", "type": "string" }
  ]
}

O schema define estrutura e tipos. O produtor não pode enviar uma string em totalCents quando o contrato exige long.

Registrando o schema

import { SchemaType } from '@kafkajs/confluent-schema-registry';

const schema = JSON.stringify({
  type: 'record',
  name: 'OrderCreated',
  namespace: 'com.codigofacil.orders',
  fields: [
    { name: 'orderId', type: 'string' },
    { name: 'customerId', type: 'string' },
    { name: 'totalCents', type: 'long' },
    { name: 'occurredAt', type: 'string' }
  ]
});

const { id } = await registry.register({
  type: SchemaType.AVRO,
  schema
});

Em produção, schemas normalmente são registrados por pipeline ou ferramenta de governança, não a cada request.

Serializando o evento

const payload = {
  orderId: 'order-42',
  customerId: 'customer-7',
  totalCents: 15990,
  occurredAt: new Date().toISOString()
};

const encoded = await registry.encode(id, payload);

Depois publique os bytes:

const producer = kafka.producer();
await producer.connect();

await producer.send({
  topic: 'orders.created.v1',
  messages: [
    {
      key: payload.orderId,
      value: encoded
    }
  ]
});

Desserializando no consumidor

const consumer = kafka.consumer({
  groupId: 'billing-orders-created'
});

await consumer.connect();
await consumer.subscribe({
  topic: 'orders.created.v1'
});

await consumer.run({
  eachMessage: async ({ message }) => {
    const event = await registry.decode(message.value);
    await handleOrderCreated(event);
  }
});

O cliente lê o schema ID do wire format e usa cache para evitar chamadas repetidas ao registry.

Subjects

Um subject agrupa versões relacionadas. Estratégias comuns:

  • TopicNameStrategy;
  • RecordNameStrategy;
  • TopicRecordNameStrategy.

A escolha afeta reutilização e compatibilidade. Para um schema por tópico, TopicNameStrategy é simples. Para vários tipos no mesmo tópico, RecordNameStrategy pode ser mais adequado.

Compatibilidade backward

Backward significa que o novo schema consegue ler dados produzidos pelo schema anterior. Um exemplo compatível é adicionar campo com default:

{
  "name": "currency",
  "type": "string",
  "default": "BRL"
}

Consumidores novos leem eventos antigos e usam o valor padrão.

Compatibilidade forward

Forward significa que consumidores antigos conseguem ler dados produzidos com o novo schema. Adicionar um campo geralmente é compatível porque leitores antigos ignoram o que não conhecem, dependendo do formato e das regras.

Compatibilidade full

Full combina backward e forward. É mais restritiva, mas reduz risco quando produtores e consumidores são implantados em ordens diferentes.

Transitive compatibility

Modos transitive comparam com todas as versões anteriores, não apenas a última. Isso impede que uma sequência de mudanças aparentemente compatíveis quebre consumidores muito antigos ainda suportados.

Breaking changes

Mudanças perigosas incluem:

  • remover campo sem planejamento;
  • trocar string por número;
  • renomear propriedade;
  • alterar namespace ou record name;
  • reutilizar campo com outra semântica;
  • mudar enum sem compatibilidade;
  • remover default necessário.

Quando o contrato realmente precisa quebrar, crie novo tópico ou versão explícita.

Schema como API

Trate schemas como APIs públicas. Eles precisam de:

  • revisão;
  • versionamento;
  • documentação;
  • testes;
  • depreciação;
  • responsável definido;
  • política de compatibilidade.

Veja Semantic Versioning no Node.js para pensar em impacto de mudanças.

Validação antes do deploy

O pipeline deve verificar compatibilidade antes de registrar:

npm run schema:check
npm run test
npm run build

A API do registry oferece endpoints de compatibility. A ferramenta usada deve comparar o schema candidato com o subject correto.

Separando registro e runtime

Evite registrar schemas automaticamente em toda inicialização de produção. Isso pode criar versões acidentais e exige permissão de escrita no runtime. Um modelo mais seguro:

  1. CI valida;
  2. release registra;
  3. aplicação recebe ID ou busca por subject;
  4. runtime possui leitura limitada.

Cache

Clientes mantêm schemas em memória. Defina limites e monitore falhas. Se o registry estiver temporariamente indisponível, mensagens com schemas já em cache podem continuar sendo processadas, mas novos IDs podem falhar.

Disponibilidade

Schema Registry vira dependência crítica para novos schemas e consumidores que ainda não têm cache. Em produção:

  • execute múltiplas instâncias;
  • use health checks;
  • proteja storage;
  • configure TLS;
  • monitore latência;
  • planeje backup e recuperação.

Autenticação

const registry = new SchemaRegistry({
  host: process.env.SCHEMA_REGISTRY_URL,
  auth: {
    username: process.env.SCHEMA_REGISTRY_USER,
    password: process.env.SCHEMA_REGISTRY_PASSWORD
  }
});

Use secret manager e não registre credenciais. Consulte Gestão de Segredos no Node.js.

Avro, Protobuf ou JSON Schema?

  • Avro: compacto, bom suporte a evolução e ecossistema Kafka;
  • Protobuf: tipos e geração de código fortes;
  • JSON Schema: formato legível e alinhado a APIs JSON.

A escolha depende de consumidores, linguagem e governança. O próximo artigo aprofunda Avro.

Mensagens com metadata

Não coloque apenas dados de negócio. Inclua envelope:

{
  "eventId": "evt-123",
  "eventType": "order.created",
  "eventVersion": 1,
  "occurredAt": "2026-09-14T12:00:00Z",
  "correlationId": "corr-42",
  "data": {}
}

O envelope também deve ter schema. IDs ajudam idempotência e rastreamento. Veja Idempotência em APIs Node.js.

Outbox

O schema não resolve consistência entre banco e Kafka. Use Outbox Pattern para gravar evento e alteração de negócio na mesma transação. Consulte Outbox Pattern no Node.js.

Testes de contrato

Inclua fixtures antigas:

test('consumidor lê versão anterior', async () => {
  const oldMessage = await loadFixture('order-created-v1.bin');
  const event = await registry.decode(oldMessage);

  assert.equal(event.currency ?? 'BRL', 'BRL');
});

Teste também um produtor novo contra consumidor antigo quando o modo exige forward compatibility.

Testcontainers

Suba Kafka e Schema Registry em integração. Isso valida wire format, subjects e autenticação. Veja Testcontainers no Node.js.

Observabilidade

Meça:

  • latência de encode e decode;
  • cache hit;
  • falhas de registry;
  • schema IDs desconhecidos;
  • incompatibilidades;
  • versões por subject;
  • erros de validação.

Erros comuns

  • JSON sem contrato: consumidores quebram.
  • Registrar no startup: versões acidentais surgem.
  • Compatibilidade none: qualquer breaking entra.
  • Alterar sem default: eventos antigos falham.
  • Runtime com escrita ampla: risco de governança.
  • Ignorar cache: registry vira gargalo.
  • Sem teste de fixtures: compatibilidade teórica.
  • Schema sem owner: evolução fica caótica.

Conclusão

O Schema Registry no Node.js transforma mensagens Kafka em contratos versionados. Produtores serializam com um schema conhecido e consumidores validam evolução antes que mudanças incompatíveis cheguem à produção.

Defina subjects, compatibilidade e ownership desde o início. Registre schemas no pipeline, teste versões antigas e combine com idempotência e outbox. Assim, eventos deixam de ser JSON informal e se tornam APIs duráveis entre serviços.

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