Relacionamento Digitalcom o Cidadão
Parte III — Arquitetura
Parte III — ArquiteturaCapítulo 13

Capítulo 13 — Arquitetura de Eventos e Mensageria

Este capítulo apresenta a Arquitetura de Mensageria e RabbitMQ da Plataforma de Relacionamento Digital com o Cidadão.

13.1 Objetivo do Capítulo

Este capítulo apresenta a Arquitetura de Mensageria e RabbitMQ da Plataforma de Relacionamento Digital com o Cidadão.

A adoção do RabbitMQ é uma decisão arquitetural confirmada. Ele não é utilizado apenas como mecanismo de tarefas em background — constitui a infraestrutura transversal de comunicação assíncrona da plataforma, cobrindo: publicação de eventos de domínio, execução de comandos assíncronos, distribuição de trabalhos, integração entre serviços, ingestão no Data Lake, processamento documental e ativação de capacidades não interativas de inteligência artificial.

Este capítulo define: topologia de exchanges e filas, convenções de nomenclatura, envelope de mensagens, versionamento, Publisher Confirms, Transactional Outbox, política de acknowledgment, classificação de falhas, retry, Dead Letter Queues, idempotência, segurança, isolamento multi-tenant, observabilidade e catálogo inicial de eventos.


13.2 Papel da Mensageria na Plataforma

A mensageria desacopla serviços que não precisam de resposta imediata, absorve picos de carga e habilita processamentos paralelos sem acoplamento de chamada.

Exemplo do fluxo de uma submissão de solicitação:

Request Service publica request.submitted.v1
    │
    ▼
RabbitMQ
    │
    ├──▶ Workflow Service       → inicia instância de processo
    ├──▶ Communication Service → envia confirmação ao cidadão
    ├──▶ Analytics Service     → atualiza projeção analítica
    └──▶ Data Lake Ingestion   → ingere evento na partição do tenant

O Request Service registra o fato sem executar diretamente nenhuma dessas ações. Cada consumidor processa o evento conforme sua responsabilidade, no seu próprio ritmo, com sua própria política de falha.


13.3 Classificação de Mensagens

A arquitetura distingue três categorias de mensagens com características e regras diferentes.

13.3.1 Eventos de Domínio

Representam fatos que já ocorreram no domínio de negócio. São imutáveis, versionsados e publicados para múltiplos consumidores independentes.

Exemplos:

request.submitted.v1
citizen.updated.v1
appointment.scheduled.v1
document.uploaded.v1

13.3.2 Comandos Assíncronos

Representam solicitações explícitas de execução direcionadas a um consumidor lógico conhecido. São processados por um único consumidor por vez.

Exemplos:

communication.send.v1
workflow.start.v1
document.process.v1
integration.sei.register.v1
ai.knowledge.index.v1

13.3.3 Trabalhos Distribuídos

Processamentos que escalam horizontalmente por workers, sem remetente único esperando resultado imediato.

Exemplos:

document.ocr.v1
document.metadata.extract.v1
ai.embedding.generate.v1
datalake.ingest.v1
report.export.v1

13.4 Topologia de Exchanges

A plataforma utiliza exchanges com responsabilidade definida. Nenhuma exchange acumula finalidades incompatíveis.

platform.events      → eventos de domínio (topic)
platform.commands    → comandos assíncronos (direct)
platform.work        → trabalhos distribuídos (direct)
platform.dead-letter → DLX para mensagens não processáveis (fanout)

Os nomes são a referência de arquitetura. A nomenclatura definitiva por ambiente é registrada como ADR-066.

13.4.1 Exchange de Eventos (platform.events)

Tipo topic. Recebe eventos publicados pelos serviços de domínio com routing keys no formato <domínio>.<evento>.<versão>.

Bindings de consumidores usam padrão específico ou wildcard controlado:

# fila que consome só eventos de solicitação submetida
routing key: request.submitted.v1

# fila que consome qualquer evento do domínio de solicitações
routing key: request.#

Wildcards amplos como # são avaliados com cautela — bindings excessivamente abrangentes geram consumo desnecessário e dificultam rastreabilidade.

13.4.2 Exchange de Comandos (platform.commands)

Tipo direct. Direciona comandos a consumidores específicos. A routing key identifica o consumidor lógico esperado.

13.4.3 Exchange de Trabalhos (platform.work)

Tipo direct. Distribui trabalhos entre workers que escalam horizontalmente. Múltiplas instâncias do mesmo worker consomem competitivamente a mesma fila (competing consumers).

13.4.4 Dead Letter Exchange (platform.dead-letter)

Tipo fanout ou direct. Recebe mensagens após esgotamento da política de retry. Roteia para filas de DLQ identificáveis por consumidor — nunca para uma fila global única.


13.5 Filas

13.5.1 Fila por Consumidor Lógico

Quando um evento precisa ser processado por múltiplos serviços distintos, cada um possui sua própria fila vinculada ao mesmo exchange com o mesmo routing key.

Exemplo para request.submitted.v1:

workflow.request-submitted     → Workflow Service
communication.request-events   → Communication Service
datalake.request-events        → Data Lake Ingestion
analytics.request-events       → Analytics Service

Cada consumidor recebe sua cópia independente. Nenhum "compete" com os demais pelo mesmo evento.

13.5.2 Competing Consumers

Múltiplas instâncias do mesmo consumidor podem consumir competitivamente a mesma fila. Isso é o mecanismo de escala horizontal de consumers.

document.processing  ← instância 1 do Document Worker
document.processing  ← instância 2 do Document Worker
document.processing  ← instância 3 do Document Worker

Para que funcione corretamente com competing consumers, os processadores devem ser idempotentes.

13.5.3 Quorum Queues

Quorum Queues são o tipo recomendado para filas de negócio crítico. Oferecem replicação entre nós do cluster e maior durabilidade frente a falhas de nó. Classic Queues são avaliadas apenas para casos com justificativa técnica específica.


13.6 Convenções de Nomenclatura

A nomenclatura é previsível e derivável da responsabilidade.

Routing Keys de Eventos

<domínio>.<evento>.<versão>

request.submitted.v1
citizen.updated.v1
document.uploaded.v1
appointment.cancelled.v1
task.sla-breached.v1

Routing Keys de Comandos e Trabalhos

<capacidade>.<ação>.<versão>

communication.send.v1
workflow.start.v1
document.process.v1
ai.knowledge.index.v1
datalake.ingest.v1

Nomes de Filas

<consumidor>.<propósito>

workflow.request-submitted
communication.request-submitted
datalake.request-submitted
document.processing
ai.knowledge-builder

Nomes de DLQs

<consumidor>.<propósito>.dlq

workflow.request-submitted.dlq
communication.send.dlq
document.processing.dlq
datalake.ingestion.dlq
ai.embedding.dlq

13.7 Envelope de Mensagem

Todo evento e comando publicado no RabbitMQ carrega envelope padronizado no payload JSON:

{
  "id": "01956c3e-b5f2-7b3a-a4d1-8e2f0c1d9a47",
  "type": "request.submitted.v1",
  "version": "1",
  "occurredAt": "2026-07-15T10:30:00.000Z",
  "tenantId": "org-minas-secretaria-educacao",
  "correlationId": "corr-a7f2-4b81-9c3d-e5f6a2b1c8d0",
  "causationId": "evt-anterior-que-causou-este",
  "producer": "request-service",
  "schemaVersion": "1",
  "payload": {
    "requestId": "req-uuid",
    "serviceId": "svc-uuid",
    "citizenId": "cit-uuid",
    "formId": "form-uuid",
    "formVersion": 7,
    "channel": "WEB",
    "submittedAt": "2026-07-15T10:30:00.000Z"
  }
}

Campos obrigatórios:

CampoDescrição
idIdentificador único e imutável do evento
typeTipo com versão (domínio.evento.v1)
versionVersão do envelope (para evolução do próprio envelope)
occurredAtInstante em que o fato ocorreu, em UTC
tenantIdTenant de origem — obrigatório em toda mensagem da plataforma
correlationIdIdentificador de rastreabilidade da cadeia de operações
causationIdID do evento ou comando que causou este
producerNome do serviço produtor
payloadDados específicos do evento ou comando

O tenantId no envelope garante que consumidores multi-tenant apliquem isolamento sem depender do payload de negócio. Um consumer que recebe mensagem sem tenantId válido rejeita sem processar.


13.8 Serialização

JSON é o formato padrão de serialização. A escolha equilibra legibilidade, diagnóstico e interoperabilidade entre serviços Java e serviços de IA.

A adoção de formato binário (Avro, Protobuf) pode ser avaliada quando houver evidência mensurável de gargalo de performance. Não se introduz complexidade de serialização binária sem necessidade demonstrada. A decisão é registrada como ADR-069.


13.9 Versionamento de Eventos

Eventos incluem versão explícita no tipo. Alterações de contrato seguem regras de compatibilidade:

Compatível — não requer nova versão:

  • adicionar campo opcional ao payload;
  • adicionar novo valor a enumeração quando consumidores suportam extensão;
  • adicionar metadado ao envelope.

Incompatível — requer nova versão:

  • remover campo existente;
  • mudar tipo de campo;
  • mudar semântica de campo;
  • tornar campo opcional obrigatório;
  • mudar unidade ou timezone sem contrato explícito.

Durante migração para nova versão, o produtor publica ambas (v1 e v2) simultaneamente por período de transição até que todos os consumidores evoluam. Consumidores antigos ignoram a nova versão; consumidores novos processam a nova e ignoram a antiga via binding específico.


13.10 Publicação

13.10.1 Componente de Publicação

O código de domínio não manipula diretamente canais RabbitMQ. Um componente de publicação padronizado é responsável por:

  • serializar o payload;
  • validar o envelope (campos obrigatórios);
  • propagar Tenant Context e correlationId;
  • definir propriedades da mensagem;
  • publicar;
  • tratar confirmação (Publisher Confirms);
  • registrar métricas de publicação.

Fluxo lógico:

Use Case de Domínio
       │
Integration Event Publisher
       │
RabbitMQ Adapter
       │
RabbitMQ

13.10.2 Publisher Confirms

Publicações críticas utilizam Publisher Confirms. Uma chamada de publicação que não lança exceção local não significa que a mensagem foi confirmada pelo broker — RabbitMQ pode ter falhado internamente entre o recebimento e a persistência.

Publish
    │
    ▼
RabbitMQ
    │
ACK confirmado  → mensagem persistida e roteada
NACK ou timeout → tratar como falha

A integração de Publisher Confirms com o Transactional Outbox garante que a confirmação de entrega ao broker seja registrada antes de considerar o evento publicado com sucesso.

13.10.3 Mandatory Publishing

Mensagens críticas ativam mandatory=true para detectar routing sem destino. Uma mensagem publicada sem fila correspondente retorna ao produtor com basic.return. Sem esse mecanismo, a mensagem desaparece silenciosamente. Alertas são configurados para retornos de mandatory publishing.


13.11 Transactional Outbox

O padrão Transactional Outbox elimina a inconsistência entre transação confirmada e evento não publicado. É aplicado em eventos críticos originados de alterações no banco operacional.

Fluxo:

Client → Request Service

BEGIN TRANSACTION
  UPDATE request SET status = 'SUBMITTED'
  INSERT INTO outbox_event (id, tenant_id, type, payload, occurred_at)
COMMIT
→ resposta ao cliente: protocolo gerado

Outbox Publisher (background)
  SELECT * FROM outbox_event WHERE published_at IS NULL
  Publish to RabbitMQ
  Publisher Confirm ACK
  UPDATE outbox_event SET published_at = NOW()

Estrutura conceitual da tabela outbox:

outbox_event
  id                  UUID
  tenant_id           VARCHAR
  aggregate_type      VARCHAR
  aggregate_id        UUID
  event_type          VARCHAR
  event_version       VARCHAR
  payload             JSONB
  occurred_at         TIMESTAMPTZ
  created_at          TIMESTAMPTZ
  published_at        TIMESTAMPTZ
  publication_attempts INT

Publicador da Outbox:

O publicador opera por polling periódico da tabela outbox. Em ambientes com múltiplas instâncias do serviço, SKIP LOCKED (quando suportado pelo banco) ou lock controlado garante que cada registro seja publicado por apenas uma instância por vez. Duplicidade de publicação pode ocorrer em cenários de falha após commit do banco mas antes do registro de published_at — por isso consumidores são idempotentes. Eventos publicados são removidos ou arquivados por job periódico conforme política de retenção.


13.12 Consumidores

13.12.1 Acknowledgment Manual

Consumidores de negócio crítico não usam auto-acknowledgment. O ACK ocorre após processamento confirmado e resultado persistido:

Receive message
    │
Validate envelope (tenantId, type, version)
    │
Apply domain logic
    │
Persist result
    │
ACK

ACK antes do processamento significa que a mensagem pode ser perdida se o consumer falhar depois do ACK e antes de persistir o resultado.

13.12.2 Prefetch

O prefetch é configurado por perfil de consumer:

PerfilPrefetchJustificativa
Processamento rápido (eventos de estado)Alto (50–200)Baixa latência, alta throughput
Processamento pesado (OCR, embedding)Baixo (1–5)Evita sobrecarregar o consumer
Integração com sistema externo com rate limitCompatível com bulkheadRespeita limite do sistema externo
Ingestão no Data LakeMédio (10–50)Balanceia throughput e memória

O valor definitivo é derivado de testes de carga.

13.12.3 Classificação de Falhas

O consumer classifica a falha antes de decidir a ação:

Falha transitória — timeout de banco, HTTP 502/503, storage temporariamente indisponível: → retry com backoff

Falha permanente de negócio — estado inválido, recurso definitivamente inexistente, operação não permitida: → reject sem requeue, registro funcional de falha, DLQ quando necessário

Mensagem inválida — JSON malformado, schema incompatível, versão não suportada, tenantId ausente: → DLQ imediato, alerta, sem retry repetitivo

Falha desconhecida: → retry limitado, DLQ após esgotamento

13.12.4 NACK e Requeue

NACK requeue=true sem limite cria ciclo infinito de tentativas. A política de retry controla o redirecionamento — o consumer nunca reenfileira indefinidamente.


13.13 Estratégia de Retry

O retry é limitado, orientado ao tipo de falha e usa atraso progressivo.

Política de referência (valores ajustáveis por categoria):

Tentativa 1 → processamento normal

Falha transitória
    │
Retry 1 → aguardar 30 segundos (TTL em retry queue 1)
    │
Falha transitória
    │
Retry 2 → aguardar 5 minutos (TTL em retry queue 2)
    │
Falha transitória
    │
Retry 3 → aguardar 30 minutos (TTL em retry queue 3)
    │
Falha
    │
DLQ

A implementação usa filas de retry com TTL e dead-letter configurado de volta à exchange original:

Main Queue → falha → Retry Queue 1 (TTL=30s, DLX→platform.events) → Main Queue
                                                      ↓ (se falhar de novo)
                     Retry Queue 2 (TTL=5m, DLX→platform.events)  → Main Queue
                                                      ↓ (se falhar de novo)
                     DLQ

Retry imediato dentro do consumer (sem sair da thread) é usado apenas para falhas com latência muito curta — nunca para manter thread aguardando minutos.


13.14 Poison Messages e Dead Letter Queues

13.14.1 Poison Messages

Uma poison message falha repetidamente de forma determinística. A arquitetura impede requeue infinito. Após o limite de retentativas, a mensagem é encaminhada à DLQ correspondente. A fila principal não é bloqueada.

13.14.2 DLQs por Consumidor

Cada consumidor lógico tem sua própria DLQ. Não existe DLQ global para toda a plataforma — uma DLQ única dificultaria investigação, autorização, reprocessamento e atribuição de responsabilidade.

workflow.request-submitted.dlq     → responsável: Workflow Service
communication.send.dlq             → responsável: Communication Service
document.processing.dlq            → responsável: Document Worker
datalake.ingestion.dlq             → responsável: Data Lake Ingestion
ai.embedding.dlq                   → responsável: AI Builder

13.14.3 Operação de DLQ

Cada DLQ possui: responsável definido, dashboard de monitoramento, alerta de acúmulo acionável, política de retenção, processo formal de investigação e replay auditado.

O replay é uma ação deliberada, autenticada e registrada em auditoria — não uma reexecução automática sem verificação. O reprocessamento ocorre após análise da causa raiz e garantia de que a condição de falha foi resolvida.


13.15 Idempotência

13.15.1 Princípio

A plataforma assume semântica at-least-once. Uma mensagem pode ser entregue mais de uma vez em cenários de falha ou retry. Consumidores críticos são projetados para processar a mesma mensagem múltiplas vezes sem efeito duplicado.

13.15.2 Inbox Pattern

Para consumidores que exigem garantia forte de idempotência:

BEGIN TRANSACTION
  INSERT INTO inbox_message (event_id, event_type, received_at)
    ON CONFLICT (event_id) DO NOTHING
    RETURNING id
  -- se nenhuma linha retornou: mensagem já processada
  APPLY domain change
COMMIT
ACK

A tabela inbox tem retenção definida conforme a janela de redelivery esperada.

13.15.3 Idempotência por Regra de Negócio

Nem toda idempotência exige tabela Inbox. Exemplos de idempotência natural:

  • aplicar cancelamento a agendamento já cancelado é no-op por regra de estado;
  • INSERT ... ON CONFLICT DO NOTHING em tabela com constraint de unicidade por command_id;
  • verificar versão do agregado antes de aplicar mudança.

A escolha entre Inbox formal e idempotência por regra de negócio é feita por domínio, com o critério de robustez da garantia esperada.


13.16 Tenant Context em Mensagens

O tenantId é campo obrigatório do envelope. Consumidores multi-tenant estabelecem o Tenant Context a partir do envelope antes de processar o payload — nunca confiam em campo dentro do payload de negócio como única fonte de contexto.

O trace ID e o correlation ID são propagados via properties da mensagem RabbitMQ, permitindo rastreamento distribuído entre a publicação do evento e o processamento do consumer, sem repetição no payload de negócio.

Message Properties:
  x-correlation-id: corr-xyz
  x-trace-parent: 00-traceid-spanid-01   (W3C Trace Context)
  x-tenant-id: tenant-abc                (propagado para validação)

13.17 Integração com o Data Lake

O Data Lake é alimentado exclusivamente por eventos RabbitMQ. Nenhum serviço de domínio escreve diretamente no Data Lake.

Domínio de Negócio publica evento
    │
RabbitMQ platform.events
    │
datalake.<domínio>-events (fila de ingestão)
    │
Data Lake Ingestion Consumer
    │
  Valida contrato e idempotência
    │
  Transforma para formato analítico
    │
  Persiste na partição do tenant
    │
  Registra linhagem

A indisponibilidade do Data Lake não bloqueia transações de negócio. O acúmulo na fila de ingestão é monitorado com alerta de backlog. O processamento é retomado quando o Data Lake se recupera, com as mensagens reprocessadas na ordem da fila.


13.18 Integração com Inteligência Artificial

13.18.1 Processamentos Não Interativos

Fluxos assíncronos de IA utilizam RabbitMQ para desacoplar o acionamento do processamento:

Document Service publica document.uploaded.v1
    │
AI Builder consome: ai.knowledge.index.v1
    │
  Extrai conteúdo
    │
  Gera embeddings
    │
  Indexa na base vetorial do tenant
    │
Publica: ai.knowledge-indexed.v1

13.18.2 Chat Interativo

O chat e a busca semântica interativos permanecem síncronos (API REST ao AI Gateway). RabbitMQ não é usado para respostas onde o cidadão ou o atendente aguarda resultado imediato.

13.18.3 Isolamento por Tenant

O tenantId do envelope garante que os workers de IA processem conteúdo e escrevam em bases vetoriais do tenant correto. Um worker não mistura conteúdo de tenants diferentes mesmo consumindo a mesma fila.


13.19 Segurança

13.19.1 Autenticação por Serviço

Cada serviço usa credenciais específicas para conectar ao RabbitMQ. Não existe credencial compartilhada entre serviços. O princípio de menor privilégio define quais exchanges e filas cada serviço pode publicar e consumir.

13.19.2 TLS

O tráfego entre serviços e RabbitMQ usa TLS. mTLS é avaliado para autenticação mútua em ambientes de produção.

13.19.3 Segredos

Credenciais do RabbitMQ são gerenciadas pelo cofre de segredos. Nenhuma credencial em variável de ambiente hardcoded, arquivo de configuração versionado ou log.

13.19.4 Dados no Payload

O payload não inclui dados pessoais sensíveis além do necessário ao processamento. Identificadores são usados no lugar de dados pessoais quando o consumer pode obter o dado diretamente do serviço responsável. Payloads de IA não incluem CPF, nome completo ou dados de saúde sem necessidade funcional explícita.


13.20 Observabilidade

13.20.1 Métricas do Broker

Métricas monitoradas continuamente:

MétricaDescriçãoAlerta
Queue depthQuantidade de mensagens em filaCrescimento sustentado
Oldest message ageIdade da mensagem mais antiga na filaSupera SLA do consumer
Publish rateTaxa de publicação por exchangeAnomalia em relação ao baseline
Consume rateTaxa de consumo por filaQueda em relação ao publish rate
Unacked messagesMensagens entregues e não confirmadasAcúmulo excessivo
DLQ depthMensagens na DLQQualquer acúmulo acima do baseline
Redelivery rateTaxa de reentregaAcima do esperado
Consumer countQuantidade de consumers ativosZero consumers em fila ativa

13.20.2 Métricas do Consumer

Cada consumer emite métricas:

  • tempo de processamento por tipo de mensagem;
  • taxa de sucesso e falha;
  • retentativas por evento;
  • DLQs enviadas;
  • lag estimado (oldest message age na fila).

13.20.3 Rastreamento Distribuído

O trace iniciado na requisição HTTP que gerou o evento é propagado através da mensagem RabbitMQ para o consumer. O span do consumer pertence ao mesmo trace, permitindo rastreamento ponta a ponta:

HTTP Request (Portal → API Gateway → Request Service)
  [span: http-request]
       │
  publica evento com traceparent
       │
RabbitMQ
       │
Consumer (Workflow Service)
  [span: amqp-consume, parent: http-request]

13.20.4 Alertas

Alertas priorizados para operação:

  • DLQ com mensagens acima do baseline;
  • fila sem consumers ativos;
  • oldest message age acima do SLA do serviço;
  • taxa de redelivery acima de threshold;
  • mandatory publishing com retornos não esperados;
  • consumer com taxa de falha acima do normal.

13.21 Disponibilidade e Resiliência do Broker

O cluster RabbitMQ é configurado com múltiplos nós para redundância. Quorum Queues garantem que dados de filas críticas sobrevivam à falha de um nó. A topologia de cluster (número de nós, distribuição, estratégia de storage) é registrada como parte da arquitetura de infraestrutura no Capítulo 20.

Em caso de indisponibilidade temporária do RabbitMQ:

  • o Transactional Outbox retém eventos no banco operacional até que o broker se recupere;
  • publishers com retry aguardam com backoff antes de desistir;
  • a operação transacional do serviço não é bloqueada pelo Outbox — o evento será publicado quando o broker voltar.

13.22 Catálogo Inicial de Eventos

DomínioEventoProdutor
Identityidentity.user.created.v1Identity Service
Identityidentity.user.blocked.v1Identity Service
Identityidentity.federated-linked.v1Identity Service
Identityidentity.authentication-succeeded.v1Identity Service
Tenanttenant.created.v1Tenant Service
Tenanttenant.activated.v1Tenant Service
Tenanttenant.suspended.v1Tenant Service
Tenanttenant.modules-changed.v1Tenant Service
Citizencitizen.created.v1Citizen Service
Citizencitizen.updated.v1Citizen Service
Citizencitizen.preferences-changed.v1Citizen Service
Citizencitizen.consent-changed.v1Citizen Service
Service Catalogcatalog.service.published.v1Catalog Service
Service Catalogcatalog.service.suspended.v1Catalog Service
Formsform.version-published.v1Forms Service
Requestrequest.created.v1Request Service
Requestrequest.submitted.v1Request Service
Requestrequest.status-changed.v1Request Service
Requestrequest.complement-requested.v1Request Service
Requestrequest.complement-submitted.v1Request Service
Requestrequest.cancelled.v1Request Service
Requestrequest.completed.v1Request Service
Workflowworkflow.instance-started.v1Workflow Service
Workflowworkflow.step-completed.v1Workflow Service
Workflowworkflow.instance-completed.v1Workflow Service
Workflowworkflow.instance-failed.v1Workflow Service
Tasktask.created.v1Task Service
Tasktask.assigned.v1Task Service
Tasktask.sla-warning.v1Task Service
Tasktask.sla-breached.v1Task Service
Tasktask.completed.v1Task Service
CRMcrm.interaction-created.v1CRM Service
CRMcrm.interaction-assigned.v1CRM Service
CRMcrm.interaction-closed.v1CRM Service
CRMcrm.human-assistance-requested.v1CRM Service
Communicationcommunication.sent.v1Communication Service
Communicationcommunication.delivered.v1Communication Service
Communicationcommunication.failed.v1Communication Service
Communicationcommunication.received.v1Communication Service
Documentdocument.uploaded.v1Document Service
Documentdocument.processed.v1Document Service
Documentdocument.processing-failed.v1Document Service
Schedulingappointment.scheduled.v1Scheduling Service
Schedulingappointment.rescheduled.v1Scheduling Service
Schedulingappointment.cancelled.v1Scheduling Service
Ombudsmanombudsman.manifestation-created.v1Ombudsman Service
Ombudsmanombudsman.manifestation-closed.v1Ombudsman Service
Satisfactionsatisfaction.feedback-received.v1Satisfaction Service
Segmentationsegment.calculated.v1Segmentation Service
Campaigncampaign.started.v1Campaign Service
Campaigncampaign.completed.v1Campaign Service
Data Qualitydata-quality.issue-detected.v1Data Quality Service
AIai.chat-completed.v1AI Gateway
AIai.feedback-received.v1AI Gateway
AIai.knowledge-indexed.v1AI Builder

13.23 Catálogo Inicial de Comandos

CapacidadeComandoConsumidor Lógico
Comunicaçãocommunication.send.v1Communication Service
Workflowworkflow.start.v1Workflow Service
Documentodocument.process.v1Document Worker
Documentodocument.ocr.v1OCR Worker
IAai.knowledge.index.v1AI Builder
IAai.knowledge.reindex.v1AI Builder
IAai.summarize.v1AI Service
Integraçãointegration.sei.register.v1SEI Adapter
Data Lakedatalake.ingest.v1Ingestion Consumer
Relatórioreport.export.v1Export Worker

13.24 Decisões Confirmadas

  1. RabbitMQ é a infraestrutura de mensageria da plataforma;
  2. eventos são diferenciados de comandos e de trabalhos;
  3. o Tenant Context é propagado em todas as mensagens via envelope;
  4. eventos críticos possuem identificador único e imutável;
  5. consumidores críticos são idempotentes;
  6. retry infinito não é permitido — DLQ após esgotamento;
  7. o Data Lake é alimentado exclusivamente por eventos RabbitMQ;
  8. processamentos não interativos de IA usam filas;
  9. chat interativo permanece síncrono;
  10. arquivos binários não são transportados no payload — apenas referências;
  11. mensagens são versionadas com versão no tipo;
  12. Publisher Confirms são usados em fluxos críticos;
  13. Transactional Outbox garante consistência entre banco e evento;
  14. a semântica de entrega é at-least-once;
  15. observabilidade é aplicada ao broker e a cada consumer.

13.25 Benefícios da Arquitetura de Mensageria

  • desacoplamento entre produtores e consumidores;
  • absorção de picos sem pressão sobre serviços de domínio;
  • processamento paralelo por múltiplos consumidores independentes;
  • escalabilidade horizontal de workers por fila;
  • resiliência por retry e DLQ sem bloqueio da fila principal;
  • rastreabilidade ponta a ponta por correlationId e trace propagados;
  • isolamento de tenant em toda a cadeia assíncrona;
  • alimentação desacoplada do Data Lake;
  • separação entre fluxos interativos (síncronos) e não interativos (assíncronos) de IA.

13.26 Riscos e Mitigações

RiscoConsequênciaMitigação
Consumer não idempotenteDuplicidade de protocolos, comunicações e tarefasInbox Pattern ou idempotência por regra de negócio em todos os consumers críticos
Evento sem tenantIdProcessamento em contexto errado ou rejeição silenciosaValidação obrigatória de tenantId no consumer antes de processar
DLQ sem processo operacionalMensagens acumulam sem investigação ou resoluçãoOwner, dashboard, alerta e runbook para cada DLQ
Retry stormCascata de falhas amplificada por retentativasRetry budget, backoff exponencial com jitter, circuit breaker no consumer
Poison message bloqueando filaConsumer parado, backlog crescenteLimite de retentativas, DLQ automático, alerta de consumer count zero
Mensagem sem fila correspondentePerda silenciosa de evento críticoMandatory publishing com alerta de retorno
Outbox não publicado após falhaEvento perdido após commit do bancoPublisher com retry, monitoramento da tabela outbox por mensagens antigas
Dados pessoais no payloadExposição desnecessária em logs e tracesPolítica de payload mínimo, revisão de contrato no pipeline

13.27 Decisões Arquiteturais

ADRTema
ADR-064RabbitMQ como barramento assíncrono da plataforma
ADR-065Separação entre eventos, comandos e trabalhos
ADR-066Topologia de exchanges e convenção de nomenclatura
ADR-067Formato de routing keys e convenção de nomes de filas
ADR-068Envelope padrão de mensagens
ADR-069Serialização JSON vs. formato binário
ADR-070Política de versionamento de eventos e compatibilidade
ADR-071Publisher Confirms — escopo de aplicação
ADR-072Transactional Outbox — implementação e publisher
ADR-073Inbox Pattern — escopo de aplicação por consumer
ADR-074Política de retry por categoria de consumer
ADR-075Dead Letter Queues — topologia e processo operacional
ADR-076Processo de replay de mensagens em DLQ
ADR-077Quorum Queues vs. Classic Queues por categoria
ADR-078Propagação de Tenant Context em mensagens
ADR-079Propagação de Trace Context (W3C) em RabbitMQ
ADR-080Segurança de acesso ao broker (credenciais, TLS, mTLS)
ADR-081Integração entre RabbitMQ e Data Lake
ADR-082RabbitMQ nos fluxos assíncronos de IA

13.28 Rastreabilidade com o Anexo III

  • Bloco 1 — Relacionamento e Atendimento: eventos de interação (CRM), comandos de comunicação, callbacks de canais externos, distribuição de atendimento.
  • Bloco 2 — BPM: request.submitted.v1workflow.start.v1; eventos de tarefas; timers de SLA; integração assíncrona com sistemas externos.
  • Bloco 3 — Gestão Documental: document.uploaded.v1 → workers de OCR e extração; ai.knowledge.index.v1 → builder de RAG.
  • Bloco 4 — Dados e Inteligência: ingestão no Data Lake por eventos de todos os domínios; indexação de bases de conhecimento; métricas de consumo de IA.
  • Bloco 5 — Integração: comandos assíncronos para adaptadores externos; replay de integrações falhas; desacoplamento por DLQ.
  • Bloco 6 — Infraestrutura e Governança: segregação por ambiente, credenciais por serviço, menor privilégio, contratos versionados, observabilidade, auditoria de replay.

13.29 Considerações Finais

RabbitMQ é o eixo da comunicação assíncrona da plataforma. A topologia de exchanges diferenciadas por categoria, o envelope padronizado com Tenant Context obrigatório, o Transactional Outbox para consistência, a política de retry com classificação de falhas, as DLQs por consumidor com processo operacional definido e a observabilidade end-to-end constituem a base que garante resiliência, isolamento multi-tenant e rastreabilidade em toda a cadeia assíncrona.

O Capítulo 14 detalha a Arquitetura de APIs e Integrações, descrevendo os contratos HTTP, o API Gateway, os padrões REST e os adaptadores para sistemas governamentais externos.


13.30 Controle de Versão

CampoValor
DocumentoDocumento Mestre — Plataforma de Relacionamento Digital com o Cidadão
Capítulo13 — Arquitetura de Mensageria e RabbitMQ
Versão1.0
SituaçãoConcluído
Última atualização15/07/2026

13.31 Rastreabilidade PRODEMGE

  • [ANX-IV] — Capacidades técnicas de mensageria, processamento assíncrono, resiliência e escalabilidade horizontal atendidas por RabbitMQ.
  • [ANX-V] — Sustentabilidade: contratos versionados, Transactional Outbox, padrões corporativos de consumer, observabilidade integrada e evolução incremental da topologia.
  • [PNR] — Plano de Negócio Referencial: integração com sistemas governamentais (SEI!MG, MG-Ouv) por adaptadores acionados por comandos assíncronos; Data Lake alimentado por eventos; IA com processamentos não interativos desacoplados.
  • [EDITAL] — Edital CP001/2026: arquitetura distribuída, escalável, resiliente e interoperável — propriedades sustentadas pela mensageria descrita neste capítulo.

Nesta página

13.1 Objetivo do Capítulo13.2 Papel da Mensageria na Plataforma13.3 Classificação de Mensagens13.3.1 Eventos de Domínio13.3.2 Comandos Assíncronos13.3.3 Trabalhos Distribuídos13.4 Topologia de Exchanges13.4.1 Exchange de Eventos (platform.events)13.4.2 Exchange de Comandos (platform.commands)13.4.3 Exchange de Trabalhos (platform.work)13.4.4 Dead Letter Exchange (platform.dead-letter)13.5 Filas13.5.1 Fila por Consumidor Lógico13.5.2 Competing Consumers13.5.3 Quorum Queues13.6 Convenções de NomenclaturaRouting Keys de EventosRouting Keys de Comandos e TrabalhosNomes de FilasNomes de DLQs13.7 Envelope de Mensagem13.8 Serialização13.9 Versionamento de Eventos13.10 Publicação13.10.1 Componente de Publicação13.10.2 Publisher Confirms13.10.3 Mandatory Publishing13.11 Transactional Outbox13.12 Consumidores13.12.1 Acknowledgment Manual13.12.2 Prefetch13.12.3 Classificação de Falhas13.12.4 NACK e Requeue13.13 Estratégia de Retry13.14 Poison Messages e Dead Letter Queues13.14.1 Poison Messages13.14.2 DLQs por Consumidor13.14.3 Operação de DLQ13.15 Idempotência13.15.1 Princípio13.15.2 Inbox Pattern13.15.3 Idempotência por Regra de Negócio13.16 Tenant Context em Mensagens13.17 Integração com o Data Lake13.18 Integração com Inteligência Artificial13.18.1 Processamentos Não Interativos13.18.2 Chat Interativo13.18.3 Isolamento por Tenant13.19 Segurança13.19.1 Autenticação por Serviço13.19.2 TLS13.19.3 Segredos13.19.4 Dados no Payload13.20 Observabilidade13.20.1 Métricas do Broker13.20.2 Métricas do Consumer13.20.3 Rastreamento Distribuído13.20.4 Alertas13.21 Disponibilidade e Resiliência do Broker13.22 Catálogo Inicial de Eventos13.23 Catálogo Inicial de Comandos13.24 Decisões Confirmadas13.25 Benefícios da Arquitetura de Mensageria13.26 Riscos e Mitigações13.27 Decisões Arquiteturais13.28 Rastreabilidade com o Anexo III13.29 Considerações Finais13.30 Controle de Versão13.31 Rastreabilidade PRODEMGE