Avro no Node.js oferece serialização binária orientada por schema para eventos, arquivos e integração entre serviços. O formato é comum em pipelines de dados e Kafka porque separa o contrato do payload, suporta evolução e produz mensagens menores que JSON em muitos cenários.
Avro não é apenas compactação. O schema define nomes, tipos, valores padrão e regras de compatibilidade. Produtores e consumidores precisam coordenar versões para que mensagens antigas continuem legíveis durante deploys independentes.
Schema básico
{
"type": "record",
"name": "OrderCreated",
"namespace": "com.codigofacil.events",
"fields": [
{ "name": "eventId", "type": "string" },
{ "name": "orderId", "type": "string" },
{ "name": "amountCents", "type": "long" },
{ "name": "currency", "type": "string", "default": "BRL" }
]
}Campos com default facilitam consumidores antigos e novos. O valor padrão deve ser válido para o tipo e representar uma semântica real.
Compilando um schema
import avro from 'avsc';
const type = avro.Type.forSchema(schema);
const event = {
eventId: crypto.randomUUID(),
orderId: 'ord-123',
amountCents: 12990,
currency: 'BRL'
};
const buffer = type.toBuffer(event);A biblioteca valida o objeto durante a serialização. Ainda assim, valide regras de negócio antes de codificar.
Decodificando
const decoded = type.fromBuffer(buffer);
console.log(decoded.orderId);O consumidor precisa conhecer o schema do escritor ou usar um envelope que indique a versão registrada.
Schema Registry
Em Kafka, um padrão comum é registrar schemas e enviar um ID pequeno junto ao payload. O consumidor busca e armazena o schema em cache.
[magic byte][schema id][avro payload]O registry centraliza compatibilidade, mas vira parte da infraestrutura crítica. Configure cache, timeout, autenticação e comportamento quando ele estiver indisponível.
Compatibilidade backward
Um novo consumidor consegue ler eventos produzidos pelo schema antigo. Adicionar campo com default costuma ser compatível.
{ "name": "source", "type": "string", "default": "unknown" }Compatibilidade forward
Um consumidor antigo consegue ler dados do schema novo. Remover campos usados pelo leitor ou mudar tipos pode quebrar essa direção.
Compatibilidade full
Exige backward e forward. É mais restritiva e apropriada para ecossistemas com deploys independentes.
Tipos opcionais
Avro representa opcionalidade com union.
{
"name": "couponCode",
"type": ["null", "string"],
"default": null
}A ordem do union influencia o default. Teste a biblioteca usada pelo produtor e pelo consumidor.
Long e JavaScript
O tipo long pode exceder o inteiro seguro de Number. Para IDs ou valores grandes, configure suporte a BigInt, tipos customizados ou represente como string quando o contrato permitir.
if (!Number.isSafeInteger(value)) {
throw new Error('Valor excede o intervalo seguro');
}Valores financeiros inteiros em centavos normalmente cabem, mas limites precisam ser explícitos.
Logical types
Datas, timestamps e decimais são representados sobre tipos primitivos.
{
"name": "createdAt",
"type": {
"type": "long",
"logicalType": "timestamp-millis"
}
}Confirme como a biblioteca converte o logical type. Evite misturar segundos, milissegundos e microssegundos.
Envelope de evento
{
"eventId": "...",
"eventType": "order.created.v1",
"occurredAt": 1792840000000,
"tenantId": "t-1",
"data": { }
}Mesmo com Avro, IDs e tipos versionados ajudam idempotência, roteamento e auditoria.
Kafka
Serializar antes de publicar:
const value = type.toBuffer(event);
await producer.send({
topic: 'orders',
messages: [{ key: event.orderId, value }]
});Consulte Kafka no Node.js.
Validação no consumidor
try {
const event = readerType.fromBuffer(message.value);
await handleOrderCreated(event);
} catch (error) {
await deadLetter.publish({
reason: 'avro_decode_failed',
messageId: message.id
});
}Não faça retry infinito para payload inválido. Encaminhe a uma DLQ com metadados seguros.
Schema versus regras de negócio
O schema valida estrutura, não todas as invariantes. Um valor pode ser do tipo correto e ainda assim ser inválido, como moeda desconhecida ou total negativo.
Evolução de eventos
Prefira mudanças aditivas. Quando o significado muda, publique novo tipo de evento ou nova versão.
Veja API Versioning no Node.js e Testes de Contrato no Node.js.
Arquivos Avro
Object Container Files armazenam schema e blocos de dados, sendo úteis para exportações e processamento em lote. Para dados não confiáveis, limite tamanho, quantidade de registros e memória durante a leitura.
Desempenho
Compile schemas uma vez e reutilize tipos. Não faça parsing do schema a cada mensagem.
const types = new Map([
['order.created.v1', avro.Type.forSchema(orderCreatedSchema)]
]);Meça serialização, tamanho, CPU e garbage collection com payloads reais.
Segurança
- limite bytes antes de decodificar;
- não aceite schema arbitrário do cliente;
- confie apenas em registries autenticados;
- valide ID do schema;
- limite arrays, maps e strings;
- não registre payloads sensíveis;
- trate schemas como código de contrato revisado.
Observabilidade
Monitore versão do schema, falhas de encoding e decoding, cache do registry, latência, tamanho das mensagens e DLQ. Inclua schema ID em logs técnicos.
Testes
- round trip;
- leitor novo com escritor antigo;
- leitor antigo com escritor novo;
- campos com default;
- union com null;
- long acima do limite;
- timestamp;
- payload truncado;
- schema desconhecido;
- registry indisponível.
Erros comuns
- mudar tipo de campo;
- adicionar campo sem default;
- usar Number para qualquer long;
- compilar schema por mensagem;
- não testar compatibilidade;
- confiar apenas na validação estrutural;
- não limitar payload;
- acoplar consumidores ao deploy do produtor.
Checklist
- schema versionado;
- compatibilidade definida;
- registry protegido;
- tipos compilados e reutilizados;
- longs tratados;
- defaults revisados;
- regras de negócio validadas;
- DLQ configurada;
- testes de contrato;
- métricas por schema.
Conclusão
Avro no Node.js oferece contratos binários compactos e evolução controlada para eventos e dados em lote. O maior benefício não é apenas tamanho: é tornar compatibilidade uma regra verificável.
Use schemas revisados, defaults seguros, registry autenticado e testes entre versões. Com limites e observabilidade, Avro permite que produtores e consumidores evoluam de forma independente sem transformar eventos antigos em dados ilegíveis.
Consulte a especificação oficial do Apache Avro.


