Documentação de Arquitetura Event-Driven com Modelo C4
Arquitetura event-driven se tornou o padrão para construir sistemas escaláveis e fracamente acoplados. Serviços publicam eventos quando algo acontece. Outros serviços assinam esses eventos e reagem. O publicador não sabe quem está ouvindo. O assinante não sabe quem publicou. O sistema é desacoplado, resiliente e flexível.
Também e quase invisível.
Quando você olha para um diagrama C4 tradicional de um sistema event-driven, você vê serviços com setas apontando para um message broker. Serviço A publica para o Kafka. Serviço B consome do Kafka. Mas quais eventos fluem entre eles? Qual é o schema? Quem mais está ouvindo? O que acontece se um consumidor falha? O diagrama mostra o encanamento mas esconde o comportamento.
Documentar arquitetura event-driven requer técnicas que tornam o invisível visível -- que mostram não apenas a infraestrutura (brokers, filas, tópicos) mas os eventos em si, seus fluxos, seus schemas e suas garantias. Este guia cobre como fazer isso usando o modelo C4 e como os recursos de event channel do Archyl tornam sistemas event-driven cidadãos de primeira classe na sua documentação de arquitetura.
Por Que Sistemas Event-Driven São Difíceis de Documentar
Arquitetura event-driven introduz vários desafios de documentação que não existem em sistemas síncronos de request-response. (Para o lado request-response, veja como documentar uma arquitetura de microsserviços.)
Fluxo de Controle Invisível
Em um sistema síncrono, você pode rastrear uma requisição do cliente ao servidor seguindo a cadeia de chamadas. Serviço A chama Serviço B, que chama Serviço C. O fluxo de controle e explicito e visível no código.
Em um sistema event-driven, o fluxo de controle e implícito. Serviço A publica um evento OrderCreated. Em algum lugar, Serviço B reage a esse evento reservando estoque. Em outro lugar, Serviço C reage enviando um email de confirmação. Serviço A não sabe sobre B ou C. O fluxo de controle é definido pelas assinaturas de evento, não pelo código do publicador.
Essa indireção significa que você não pode entender o comportamento do sistema lendo o código de um único serviço. Você precisa de uma visão de nível mais alto que mostre os fluxos de eventos entre serviços -- e essa visão é exatamente o que a documentação de arquitetura deve fornecer.
Relacionamentos Muitos-para-Muitos
Em arquiteturas síncronas, relacionamentos são tipicamente um-para-um ou um-para-poucos. Serviço A chama Serviço B. O relacionamento e direto e documentado pela chamada de API.
Em arquiteturas event-driven, relacionamentos são muitos-para-muitos. Um único tipo de evento pode ter um produtor e cinco consumidores. Um único serviço pode consumir eventos de dez produtores diferentes. O grafo de relacionamentos é mais denso e complexo do que em sistemas síncronos.
Diagramas de arquitetura tradicionais têm dificuldade com essa densidade. Desenhar uma seta de cada produtor para cada consumidor através de cada tópico cria um diagrama que parece um prato de spaghetti. Você precisa de uma abordagem de documentação que mostre fluxos de eventos no nível certo de abstração.
Evolução de Schema
Schemas de eventos evoluem ao longo do tempo. O evento OrderCreated pode começar com cinco campos e crescer para quinze em dois anos. Consumidores podem depender de campos específicos. Mudanças de schema podem quebrar consumidores se não forem retrocompativeis.
Documentar o schema atual é necessário mas não suficiente. Você também precisa documentar a estrategia de versionamento de schema, garantias de compatibilidade e o histórico de breaking changes.
Consistência Eventual
Sistemas event-driven são eventualmente consistentes por natureza. Quando Serviço A publica um evento, Serviço B pode processa-lo milissegundos depois ou minutos depois (se o consumidor estiver atrasado ou se retries forem necessários). O sistema está em um estado inconsistente durante essa janela.
A documentação deve capturar esses limites de consistência. Quais partes do sistema são fortemente consistentes? Quais são eventualmente consistentes? Qual é o atraso de propagação esperado? O que acontece durante a janela de inconsistência?
Dead Letter Queues e Tratamento de Erros
Quando um consumidor de eventos falha ao processar uma mensagem, o evento tipicamente vai para uma dead letter queue (DLQ). Mas o que acontece depois? Quem monitora a DLQ? Qual é a estrategia de retry? Como mensagens envenenadas são tratadas?
Esses padrões de tratamento de erros são criticos para o comportamento do sistema mas raramente são documentados. Eles são parte da arquitetura e devem ser visíveis na documentação.
Modelando Sistemas Event-Driven com C4
O modelo C4 pode representar arquiteturas event-driven efetivamente com algumas adaptações em como você usa cada nível.
System Context: Foque em Fluxos de Dados, Não Chamadas
No nível de System Context, arquiteturas event-driven e síncronas parecem similares. Seu sistema interage com usuários e sistemas externos. A diferenca-chave está em como você rotula os relationships.
Em vez de "chama" ou "consulta", use labels que descrevam fluxo de dados:
- "Envia eventos de pedido para"
- "Recebe confirmações de pagamento de"
- "Publica eventos de analytics para"
Esses labels sugerem a natureza assíncrona da comunicação sem poluir a visão de alto nível com detalhes de implementação.
Diagrama de Container: Torne o Broker Visível
O diagrama de Container é onde a arquitetura event-driven se torna distinta. O message broker (Kafka, RabbitMQ, Amazon SQS/SNS, Google Pub/Sub) deve ser um container de primeira classe no seu diagrama, não um detalhe de implementação invisível.
Veja como um diagrama de Container para um sistema de e-commerce event-driven pode ser:
systems:
- name: E-Commerce Platform
type: software_system
containers:
- name: Order Service
type: service
technologies: [Go, PostgreSQL]
- name: Inventory Service
type: service
technologies: [Java, PostgreSQL]
- name: Notification Service
type: service
technologies: [Python, Redis]
- name: Analytics Service
type: service
technologies: [Python, ClickHouse]
- name: Event Bus
type: queue
technologies: [Apache Kafka]
relationships:
- from: Order Service
to: Event Bus
label: "Publica OrderCreated, OrderCancelled"
- from: Event Bus
to: Inventory Service
label: "Entrega eventos de pedido"
- from: Event Bus
to: Notification Service
label: "Entrega eventos de pedido e pagamento"
- from: Event Bus
to: Analytics Service
label: "Entrega todos os domain events"
- from: Inventory Service
to: Event Bus
label: "Publica InventoryReserved, InventoryReleased"
Note como o Event Bus está no centro do diagrama, e os relationships nomeiam explicitamente os tipos de evento que fluem através dele. Isso torna os fluxos de eventos visíveis sem criar setas diretas entre cada produtor e cada consumidor.
Event Channels: Um Conceito de Primeira Classe
Tópicos, filas e streams individuais dentro do message broker merecem sua própria documentação. Cada event channel tem propriedades que importam para entender o sistema:
- Nome do channel: O tópico Kafka, fila RabbitMQ ou fila SQS
- Tipos de evento: Quais eventos fluem por este channel
- Produtores: Quais serviços publicam neste channel
- Consumidores: Quais serviços consomem deste channel
- Serializacao: Como eventos são codificados (JSON, Avro, Protobuf)
- Estrategia de particionamento: Como eventos são distribuídos entre partições
- Politica de retenção: Por quanto tempo eventos são mantidos
- Garantias de ordenação: Se a ordem é preservada e em qual granularidade
No Archyl, event channels são um tipo de entidade dedicado. Você cria um event channel, especifica suas propriedades e o vincula aos serviços que produzem e consomem dele. Isso cria um modelo estruturado e consultável dos seus fluxos de eventos.
Por exemplo, um event channel "orders" pode ser documentado como:
- Nome: orders
- Broker: Kafka
- Produtores: Order Service
- Consumidores: Inventory Service, Notification Service, Analytics Service, Billing Service
- Tipos de Evento: OrderCreated, OrderUpdated, OrderCancelled, OrderCompleted
- Serializacao: Avro com Schema Registry
- Particionamento: Por order ID
- Retenção: 7 dias
Esse nível de detalhe torna a infraestrutura invisível visível e consultável. Quando um desenvolvedor precisa saber quem está consumindo eventos de pedido, a resposta está documentada e acessível.
Diagrama de Component: Event Handlers e Publishers
No nível de Component, serviços event-driven têm estruturas internas distintas que valem documentar para serviços complexos:
- Event Handlers: Componentes que consomem e processam tipos de evento específicos
- Event Publishers: Componentes que produzem eventos
- Sagas / Process Managers: Componentes que orquestram workflows multi-etapa através de eventos
- Projections: Componentes que constroem read models a partir de event streams
Um diagrama de Component para o Order Service pode incluir:
- Order Controller -- lida com requisições HTTP para gerenciamento de pedidos
- Order Processor -- logica de negocio principal para criação e validação de pedidos
- Event Publisher -- publica OrderCreated, OrderUpdated, OrderCancelled para o Kafka
- Payment Event Handler -- consome eventos PaymentProcessed e PaymentFailed
- Order Saga -- gerencia o workflow de cumprimento de pedidos entre serviços
Documente esses componentes quando o serviço e complexo o suficiente para justifica-lo -- particularmente para serviços que participam de padrões de coreografia ou orquestração.
Documentando Padrões Comuns de Event-Driven
Certos padrões aparecem repetidamente em sistemas event-driven. Documenta-los explicitamente evita que equipes tenham que fazer engenharia reversa dos padrões a partir do código.
Event Sourcing
Em sistemas event-sourced, o estado de uma entidade é derivado de uma sequencia de eventos em vez de armazenado como um snapshot. O event stream é a fonte de verdade, e o estado atual é uma projeção.
Documente event sourcing:
- Identificando quais entidades são event-sourced
- Listando os tipos de evento no event stream de cada entidade
- Documentando as projeções que derivam read models dos streams
- Anotando a estrategia de snapshotting (se houver)
CQRS (Command Query Responsibility Segregation)
CQRS separa operações de escrita (commands) de operações de leitura (queries), frequentemente usando eventos para manter o read model sincronizado com o write model.
Documente CQRS:
- Separando claramente containers do command-side dos containers do query-side no modelo C4
- Documentando o fluxo de eventos do write side para o read side
- Anotando o modelo de consistência (quão atrasado o read model pode ficar)
Coreografia vs. Orquestração
Na coreografia, serviços reagem a eventos independentemente. Nenhum coordenador central existe. Na orquestração, um serviço central (o orquestrador ou saga) coordena o workflow enviando commands e ouvindo respostas.
Documente qual padrão seu sistema usa para cada workflow. Se você usa coreografia, documente a sequencia esperada de eventos e os serviços que participam. Se você usa orquestração, documente a maquina de estados da saga e os commands que ela emite.
Dead Letter Queues e Padrões de Retry
Documente sua estrategia de tratamento de erros para processamento de eventos:
- Quais eventos têm dead letter queues?
- Qual é a politica de retry (quantidade, estrategia de backoff)?
- Quem é responsável por monitorar e reprocessar eventos da DLQ?
- Qual alerta está configurado para acumulação na DLQ?
No Archyl, você pode modelar DLQs como event channels adicionais vinculados aos channels primários. Isso torna a infraestrutura de tratamento de erros visível na documentação de arquitetura.
Documentando Schemas de Eventos
Schemas de eventos são contratos entre produtores e consumidores. Eles merecem o mesmo nível de documentação que contratos de API em sistemas síncronos.
Documentação de Schema
Para cada tipo de evento, documente:
- Nome do evento: Um nome claro e especifico do domínio (OrderCreated, não GenericEvent)
- Versão do schema: A versão atual do schema
- Campos: Todos os campos com seus tipos, descrições e se são obrigatórios ou opcionais
- Payload de exemplo: Um exemplo representativo em JSON/Avro/Protobuf
- Compatibilidade: Se o schema e forward-compatible, backward-compatible ou totalmente compatível
O recurso de API Contract do Archyl pode ser usado para documentar schemas de eventos junto com especificações REST e gRPC. Vincule o contrato ao event channel para criar uma conexão direta entre o schema e a infraestrutura.
Estrategia de Evolução de Schema
Documente a abordagem da sua equipe para evolução de schema:
- Você usa um schema registry (Confluent Schema Registry, AWS Glue)?
- Qual modo de compatibilidade é aplicado (backward, forward, full)?
- Como breaking changes são comunicadas aos consumidores?
- Qual é o processo de deprecação para versões antigas de schema?
Essa informação pertence a um ADR vinculado a sua infraestrutura de eventos. E uma decisão que afeta todo o sistema e deve ser documentada uma vez, claramente, e referenciada por todas as equipes.
Visualizando Fluxos de Eventos
Diagramas estáticos podem mostrar infraestrutura de eventos, mas tem dificuldade em mostrar fluxos de eventos -- a sequencia de eventos que implementa um processo de negocio.
Use Flows para Processos de Negocio
O recurso de Flow do Archyl permite documentar a sequencia de eventos que implementa um processo de negocio. Por exemplo, um flow de "Realização de Pedido" pode mostrar:
- Cliente submete pedido via Web App
- API Gateway encaminha requisição para o Order Service
- Order Service valida e persiste o pedido
- Order Service publica evento OrderCreated para o Kafka
- Inventory Service consome OrderCreated, reserva estoque
- Inventory Service publica evento InventoryReserved
- Payment Service consome InventoryReserved, processa pagamento
- Payment Service publica evento PaymentProcessed
- Notification Service consome PaymentProcessed, envia email de confirmação
Esse flow mostra o comportamento end-to-end que emerge da arquitetura event-driven. Nenhum código de um único serviço revela esse flow -- ele só existe no nível de arquitetura.
Use Overlays para Diferentes Visões
Crie overlays para mostrar diferentes aspectos da sua arquitetura event-driven:
- Overlay de Fluxo de Eventos: Destaca apenas os relationships relacionados a eventos, escondendo comunicação síncrona
- Overlay de Produtor/Consumidor: Colore serviços baseado em se produzem, consomem ou ambos
- Overlay de Tratamento de Erros: Mostra DLQs, caminhos de retry e monitoramento
Overlays permitem criar visões focadas a partir de um único modelo de arquitetura, evitando a necessidade de múltiplos diagramas redundantes.
Melhores Praticas
Nomeie Eventos com Acoes do Domínio, Não Operações Técnicas
Use nomes como OrderCreated, PaymentFailed, InventoryReserved -- não DataUpdated, MessageSent ou RecordInserted. Nomes específicos do domínio tornam os fluxos de eventos legíveis no nível de arquitetura.
Documente a Decisão "Por Que Não Síncrono"
Para cada interação event-driven, houve uma decisão de usar comunicação async em vez de sync. Documente essa decisão. Por que o Order Service publica um evento em vez de chamar o Inventory Service diretamente? A resposta (desacoplamento, resiliência, escalabilidade) deve ser capturada em um ADR.
Mantenha a Documentação de Event Channel Próxima ao Código
Se seus schemas de eventos são definidos em código (arquivos Protobuf, schemas Avro, JSON Schema), vincule a documentação de arquitetura a esses arquivos. Isso cria uma conexão entre a documentação abstrata e a implementação concreta.
Revise Fluxos de Eventos Durante Revisões de Arquitetura
Durante revisões de arquitetura trimestrais, percorra seus fluxos de eventos documentados. Pergunte:
- Há novos tipos de evento que não estão documentados?
- Há tipos de evento documentados que não são mais usados?
- Novos consumidores foram adicionados sem atualizar a documentação?
- Os schemas documentados ainda estão precisos?
A detecção de drift do Archyl ajuda a responder essas perguntas automaticamente, mas revisão humana periódica captura coisas que verificações automatizadas não pegam.
Conclusão
Documentação de arquitetura event-driven requer esforço intencional para tornar o invisível visível. Eventos, por design, desacoplam produtores de consumidores. Essa é uma forca arquitetural mas um desafio de documentação.
O modelo C4 fornece o framework: System Context para o panorama geral, diagramas de Container com o message broker como elemento de primeira classe, event channels para documentação detalhada de tópicos e filas, e diagramas de Component para event handlers e sagas complexos.
O Archyl fornece as ferramentas: event channels como entidades de primeira classe, flows para documentar processos de negocio event-driven, contratos de API para schemas de eventos, overlays para visões focadas e detecção de drift para capturar mudanças não documentadas.
Documente sua arquitetura event-driven da mesma forma que você a projeta: com intenção, estrutura e o entendimento de que o comportamento do sistema emerge das interações entre serviços, não de qualquer serviço isolado.
Comece com o Archyl e torne sua arquitetura event-driven visível, documentada e compreendida.