Schema registry: governança de contratos de eventos
1. Fundamentos do Schema Registry na Arquitetura Orientada a Eventos
1.1. O problema da evolução descontrolada de contratos entre produtores e consumidores
Em arquiteturas orientadas a eventos, produtores e consumidores evoluem de forma independente. Sem governança, um produtor pode alterar o formato de um evento sem aviso, quebrando consumidores downstream. O cenário típico de falha:
- Produtor adiciona um campo obrigatório
userIdem um eventoOrderCreated - Consumidor antigo espera apenas
orderIdeamount - O consumidor falha ao desserializar o evento, gerando erros silenciosos ou perda de dados
Esse problema se agrava com dezenas de microsserviços e centenas de tipos de eventos.
1.2. Definição e papel central do Schema Registry como catálogo de contratos
O Schema Registry é um serviço centralizado que armazena, valida e versiona schemas de eventos. Funciona como um catálogo de contratos, garantindo que:
- Todo evento publicado siga um schema registrado
- Mudanças sejam compatíveis com consumidores existentes
- Haja rastreabilidade de versões e evolução
Exemplo de schema registrado (Avro):
{
"type": "record",
"name": "OrderCreated",
"namespace": "com.exemplo.pedidos",
"fields": [
{"name": "orderId", "type": "string"},
{"name": "amount", "type": "double"},
{"name": "userId", "type": ["null", "string"], "default": null}
]
}
1.3. Diferença entre schema registry e message broker
O message broker (Kafka, RabbitMQ, Pulsar) é responsável pelo transporte e armazenamento de mensagens. O Schema Registry é responsável pela governança de formato e evolução dos dados. Eles têm responsabilidades distintas:
- Broker: roteamento, persistência, entrega
- Registry: validação, versionamento, compatibilidade
Um broker pode operar sem schema registry, mas perde a capacidade de garantir contratos entre serviços.
2. Modelos de Compatibilidade e Estratégias de Evolução
2.1. Compatibilidade backward, forward e full
- Backward: novos schemas podem ler dados escritos com schemas antigos. Permite adicionar campos com default.
- Forward: schemas antigos podem ler dados escritos com schemas novos. Permite remover campos ou adicionar campos opcionais.
- Full: combina backward e forward. Mais restritivo, mas seguro para evolução bidirecional.
Exemplo de configuração no Confluent Schema Registry:
# backward compatibility
compatibility.level=backward
# forward compatibility
compatibility.level=forward
# full compatibility
compatibility.level=full
2.2. Regras de validação de schemas
- Adição de campo opcional: permitido em backward (com default)
- Remoção de campo: permitido em forward (se consumidor antigo ignora)
- Renomeação de campo: geralmente proibido, pois quebra referência por nome
- Mudança de tipo: proibido, exceto ampliações seguras (int para long)
2.3. Versionamento semântico vs. versionamento baseado em compatibilidade
- Versionamento semântico: 1.0.0, 1.1.0, 2.0.0 — baseado em impacto da mudança
- Versionamento por compatibilidade: versão 1, 2, 3 — cada nova versão deve passar nas regras de compatibilidade configuradas
O Schema Registry geralmente usa o segundo modelo, onde o registry atribui IDs numéricos automaticamente.
3. Arquitetura e Integração do Schema Registry com o Ecossistema
3.1. Fluxo de registro e validação
- Produtor define schema e envia para o registry
- Registry valida compatibilidade com versões anteriores
- Se compatível, registry armazena e retorna um ID único
- Produtor serializa o evento usando o schema referenciado pelo ID
- Consumidor obtém o schema pelo ID e desserializa
Exemplo de fluxo com serializador Kafka Avro:
// Produtor
ProducerRecord<String, Order> record = new ProducerRecord<>("orders", order);
producer.send(record);
// O serializador automaticamente registra o schema e inclui o ID
// Consumidor
ConsumerRecords<String, Order> records = consumer.poll(Duration.ofMillis(100));
// O desserializador obtém o schema pelo ID e converte
3.2. Mecanismos de cache e latência
Consumidores e produtores mantêm cache local de schemas para evitar chamadas frequentes ao registry. O cache reduz latência e evita sobrecarga:
- Cache local com TTL configurável (ex: 5 minutos)
- Fallback para registry se cache expirar
- Estratégia de cache-first para leitura
3.3. Integração com serializadores
- Avro: mais maduro, suporte nativo no Confluent Schema Registry, esquemas binários compactos
- Protobuf: popular em ambientes gRPC, suporte via Apicurio Registry
- JSON Schema: mais legível, mas maior overhead de serialização
Diferenças práticas:
Avro: schema evolution robusta, compressão nativa, tipos complexos
Protobuf: velocidade, integração com gRPC, definição de serviços
JSON Schema: simplicidade, compatibilidade com REST, maior payload
4. Governança e Ciclo de Vida dos Contratos
4.1. Políticas de retenção e expiração de versões antigas
- Manter versões compatíveis por período mínimo (ex: 30 dias)
- Remover versões que nenhum consumidor utiliza (com base em telemetria)
- Backup de schemas antigos para auditoria
4.2. Controle de acesso e RBAC
- Quem pode registrar novo schema (admin, líder técnico)
- Quem pode modificar compatibilidade (apenas admin)
- Quem pode excluir (quase ninguém, exceto em limpeza controlada)
Exemplo de política RBAC:
Role: schema-admin
- registrar, modificar, excluir schemas
- alterar nível de compatibilidade
Role: schema-developer
- registrar novas versões compatíveis
- consultar schemas existentes
Role: schema-reader
- apenas consultar schemas
4.3. Estratégias de depreciação e migração de schemas obsoletos
- Marcar schema como deprecated, mas manter ativo por X dias
- Notificar consumidores sobre depreciação via header de evento
- Remover apenas quando todos os consumidores migrarem
5. Tratamento de Falhas e Resiliência no Schema Registry
5.1. Lidando com schemas incompatíveis
- Rejeição no produtor: registry retorna erro 409 Conflict, produtor não publica
- Fallback no consumidor: consumidor tenta desserializar com schema antigo, ignora campos novos
5.2. Alta disponibilidade do schema registry
- Múltiplas instâncias ativas com balanceamento de carga
- Replicação entre data centers (Kafka MirrorMaker + schema sync)
- Consistência eventual: registry pode ficar inconsistente por segundos, mas dados não são perdidos
5.3. Impacto de falhas no registry
- Produtores com cache conseguem publicar por horas sem registry
- Consumidores com cache conseguem consumir schemas conhecidos
- Degradação graciosa: se registry cai, usar schema local em cache e registrar quando voltar
6. Casos de Uso e Padrões Avançados
6.1. Schema evolution em pipelines de dados com múltiplos consumidores heterogêneos
Um evento UserUpdated pode ser consumido por:
- Serviço de email (precisa de email, name)
- Serviço de analytics (precisa de userId, eventType)
- Data lake (precisa de todos os campos)
O schema registry garante que todas as versões sejam compatíveis com todos os consumidores.
6.2. Uso do schema registry para documentação viva e descoberta de domínio
O registry funciona como documentação viva da API de eventos. Times podem consultar schemas para entender:
- Quais eventos existem
- Quais campos cada evento contém
- Qual versão está em produção
6.3. Integração com event versioning e idempotent consumers
- Schema version + event version: schema evolui, evento pode ter versão semântica no payload
- Idempotent consumers usam schema para validar estrutura antes de processar
- Alinhamento de contratos evita duplicatas por mau entendimento de formato
7. Trade-offs e Considerações Finais
7.1. Overhead operacional vs. benefícios
- Overhead: gerenciar registry, configurar compatibilidade, treinar times
- Benefícios: zero quebras silenciosas por mudança de schema, rastreabilidade, documentação viva
7.2. Quando evitar schema registry
- Sistemas com menos de 5 microsserviços
- Prototipação rápida sem necessidade de evolução controlada
- Eventos efêmeros com vida útil de minutos
7.3. Relação com outros temas da série
- Outbox pattern: schema registry garante que eventos no outbox sigam contratos
- Event storming: schemas documentam os eventos identificados
- Consistência de contratos: schema registry é a ferramenta central para manter consistência entre serviços
Referências
- Confluent Schema Registry Documentation — Documentação oficial do Confluent Schema Registry, com guias de configuração, compatibilidade e integração com Kafka
- Avro Schema Specification — Especificação completa do Apache Avro, incluindo tipos, serialização e regras de evolução de schemas
- Apicurio Registry Documentation — Documentação do Apicurio Registry, alternativa open-source ao Confluent Schema Registry, com suporte a Avro, Protobuf e JSON Schema
- Schema Evolution in Event-Driven Architectures — Artigo de Martin Fowler sobre evolução de schemas em arquiteturas orientadas a eventos, com exemplos práticos
- Kafka Schema Registry Best Practices — Blog da Confluent com boas práticas para usar Schema Registry em produção, incluindo estratégias de compatibilidade e governança
- Event-Driven Architecture: Schema Registry vs Message Broker — Artigo da Red Hat explicando as diferenças entre schema registry e message broker, com casos de uso