Como sincronizar dados entre sistemas legados e modernos com event bridges

1. O desafio da sincronização entre mundos tecnológicos distintos

1.1. Sistemas legados: características, limitações e a importância de mantê-los operacionais

Sistemas legados são a espinha dorsal de muitas organizações. Construídos ao longo de décadas, eles armazenam dados críticos de clientes, transações financeiras e inventários. Suas características típicas incluem bancos de dados relacionais monolíticos, interfaces baseadas em arquivos (CSV, XML) e APIs REST antigas com documentação escassa. Apesar de sua estabilidade, esses sistemas apresentam limitações severas: baixa escalabilidade horizontal, dificuldade de integração com tecnologias modernas e processos de deploy manuais. No entanto, substituí-los completamente é inviável financeira e operacionalmente.

1.2. Sistemas modernos: microsserviços, APIs assíncronas e a necessidade de dados em tempo real

Do outro lado, temos os sistemas modernos — construídos com microsserviços, containers e filas de mensagens. Eles exigem dados em tempo real para alimentar dashboards, motores de recomendação e aplicações mobile. APIs síncronas não são suficientes; o modelo assíncrono, baseado em eventos, tornou-se padrão para garantir desacoplamento e resiliência.

1.3. Problemas comuns: inconsistência de dados, latência, acoplamento e retrabalho manual

A integração direta entre esses mundos gera problemas clássicos:

  • Inconsistência de dados: o sistema legado atualiza um registro, mas o moderno fica desatualizado por minutos ou horas.
  • Latência: consultas frequentes ao banco legado geram lentidão generalizada.
  • Acoplamento forte: alterações na API do legado quebram o sistema moderno.
  • Retrabalho manual: equipes criam scripts de sincronização periódica que falham silenciosamente.

2. Fundamentos de Event Bridges e o padrão de integração assíncrona

2.1. O que é um Event Bridge: conceito, componentes e casos de uso

Um Event Bridge é um intermediário que conecta produtores de eventos (fontes de dados) a consumidores (sistemas que precisam desses dados). Seus componentes principais são:

  • Produtores: sistemas que emitem eventos (ex: "cliente_atualizado", "pedido_criado").
  • Barramento: canal central que roteia eventos para os consumidores corretos.
  • Consumidores: serviços que processam eventos e atualizam seus estados.

Casos de uso típicos incluem sincronização de catálogos de produtos, replicação de dados de clientes entre CRM e ERP, e atualização de dashboards em tempo real.

2.2. Diferenças entre Event Bridge, filas de mensagens e ETL tradicional

Característica Event Bridge Filas (RabbitMQ, SQS) ETL Tradicional
Processamento Tempo real Tempo real Batch (horário)
Roteamento Baseado em conteúdo Fila única Pré-definido
Persistência Curta/média duração Curta duração Longa duração
Acoplamento Baixo Médio Alto

2.3. Vantagens do modelo orientado a eventos para sincronização

O modelo orientado a eventos oferece:

  • Desacoplamento: produtores e consumidores não precisam se conhecer.
  • Escalabilidade: consumidores podem ser escalados independentemente.
  • Resiliência: falhas em um consumidor não afetam os demais.

3. Mapeamento e modelagem de eventos entre sistemas legados e modernos

3.1. Identificando fontes de dados no sistema legado

As fontes típicas incluem:

  • Tabelas de bancos relacionais (Oracle, SQL Server, DB2)
  • Arquivos de log ou flat files gerados por processos batch
  • APIs REST antigas com endpoints limitados

3.2. Desenho de eventos canônicos: schema unificado, versionamento e campos obrigatórios

Crie um schema canônico que represente o dado de forma neutra:

{
  "eventId": "uuid",
  "eventVersion": "1.0",
  "eventType": "ClienteAtualizado",
  "timestamp": "2025-03-21T14:30:00Z",
  "data": {
    "id": "12345",
    "nome": "Maria Silva",
    "email": "maria@exemplo.com",
    "telefone": "+5511999999999"
  }
}

Campos obrigatórios: eventId (único), eventVersion, eventType, timestamp, data. Versionamento permite evolução sem quebrar consumidores antigos.

3.3. Estratégias de transformação: adaptadores, normalização e enriquecimento

Adaptadores convertem dados do formato legado para o canônico:

// Adaptador para sistema legado em COBOL
function transformarClienteLegado(registroLegado) {
  return {
    id: registroLegado.cod_cliente,
    nome: registroLegado.nm_cliente.trim(),
    email: registroLegado.email_cliente?.toLowerCase(),
    telefone: formatarTelefone(registroLegado.tel_contato)
  };
}

Normalização: remover duplicatas, padronizar formatos. Enriquecimento: adicionar dados de contexto (geolocalização, segmentação).

4. Arquitetura prática de um Event Bridge híbrido

4.1. Componentes essenciais: change data capture (CDC) no legado, barramento de eventos e filas de retry

A arquitetura típica inclui:

  1. CDC (Change Data Capture): ferramenta como Debezium que monitora o log de transações do banco legado e emite eventos a cada INSERT, UPDATE ou DELETE.
  2. Barramento de eventos: AWS EventBridge, Apache Kafka ou RabbitMQ roteiam eventos.
  3. Filas de retry: eventos que falham vão para uma fila separada para reprocessamento.

4.2. Roteamento inteligente: filtros, tópicos e roteamento baseado em conteúdo

Configure regras de roteamento:

Regra 1: Se eventType = "ClienteAtualizado" E data.pais = "BR"
         -> Enviar para tópico "clientes-brasil"

Regra 2: Se eventType = "PedidoCriado" E data.valor > 10000
         -> Enviar para tópico "pedidos-vip"

4.3. Garantia de entrega: idempotência, exactly-once processing e dead letter queues

  • Idempotência: cada evento deve ter um eventId único; consumidores verificam se já processaram aquele ID.
  • Exactly-once: combinação de idempotência + confirmação de consumo (commit offset).
  • Dead Letter Queue (DLQ): eventos que falham após N tentativas vão para uma fila de análise manual.

5. Implementação passo a passo com exemplos concretos

5.1. Captura de mudanças no sistema legado: polling vs. triggers vs. CDC (exemplo com Debezium)

Polling: consulta periódica ao banco (ineficiente para dados em tempo real).
Triggers: gatilhos no banco que chamam uma API (impactam performance).
CDC: ideal. Exemplo com Debezium conectado a um banco PostgreSQL legado:

// Configuração Debezium (JSON)
{
  "name": "conector-legado-clientes",
  "config": {
    "connector.class": "io.debezium.connector.postgresql.PostgresConnector",
    "database.hostname": "192.168.1.100",
    "database.port": "5432",
    "database.user": "debezium",
    "database.password": "senha",
    "database.dbname": "erp_legado",
    "table.include.list": "public.clientes",
    "topic.prefix": "legado"
  }
}

A cada mudança na tabela clientes, Debezium publica um evento no tópico legado.public.clientes.

5.2. Configuração do barramento de eventos: AWS EventBridge, Kafka ou RabbitMQ (exemplo de roteamento)

Exemplo com AWS EventBridge:

// Regra de roteamento (JSON)
{
  "EventPattern": {
    "source": ["legado.clientes"],
    "detail-type": ["ClienteAtualizado"]
  },
  "Targets": [
    {
      "Arn": "arn:aws:sqs:us-east-1:123456789012:fila-modernizacao",
      "InputTransformer": {
        "InputPathsMap": {
          "id": "$.detail.after.id",
          "nome": "$.detail.after.nome"
        },
        "InputTemplate": "{\"eventId\": \"<id>\", \"nome\": \"<nome>\"}"
      }
    }
  ]
}

5.3. Consumo no sistema moderno: handlers assíncronos, validação e atualização do estado final

Handler em Node.js consumindo da fila SQS:

async function handler(event) {
  const body = JSON.parse(event.Records[0].body);

  // Validação
  if (!body.eventId || !body.nome) {
    throw new Error('Evento inválido');
  }

  // Idempotência
  const jaProcessado = await redis.get(body.eventId);
  if (jaProcessado) return;

  // Atualização no banco moderno
  await db.clientes.upsert({
    where: { id: body.id },
    update: { nome: body.nome },
    create: { id: body.id, nome: body.nome }
  });

  // Marca como processado
  await redis.set(body.eventId, 'processed', 'EX', 86400);
}

6. Tratamento de falhas, consistência e monitoramento

6.1. Estratégias para lidar com falhas de rede, downtime do legado e eventos duplicados

  • Falhas de rede: retry exponencial (3, 9, 27 segundos) com máximo de 5 tentativas.
  • Downtime do legado: fila de retry separada; eventos são reprocessados quando o legado volta.
  • Eventos duplicados: idempotência via eventId único.

6.2. Consistência eventual vs. consistência forte: trade-offs e compensações

  • Consistência eventual: aceita que o sistema moderno fique momentaneamente desatualizado (segundos). Ideal para catálogos de produtos.
  • Consistência forte: todas as réplicas são atualizadas antes de confirmar. Mais lenta, mas necessária para dados financeiros.

6.3. Observabilidade: logs estruturados, métricas de latência, dashboards e alertas

Métricas essenciais:

# Métricas Prometheus
event_bridge_eventos_recebidos_total{source="legado"} 1500
event_bridge_eventos_processados_total{consumer="moderno"} 1495
event_bridge_latencia_segundos{percentil="99"} 2.3
event_bridge_dlq_contagem{queue="clientes"} 5

Dashboards no Grafana mostram throughput, latência e taxa de erro. Alertas no PagerDuty para DLQ > 0.

7. Boas práticas e armadilhas comuns em projetos reais

7.1. Versionamento de eventos: como evoluir schemas sem quebrar consumidores existentes

Use versionamento semântico no schema:

// Versão 1.0
{ "eventVersion": "1.0", "data": { "nome": "string" } }

// Versão 2.0 (adiciona campo email)
{ "eventVersion": "2.0", "data": { "nome": "string", "email": "string" } }

Consumidores antigos ignoram campos desconhecidos. Consumidores novos usam o campo email.

7.2. Evitando a "bola de neve": limites de throughput, backpressure e circuit breakers

  • Limites de throughput: configure throttling no barramento (ex: 100 eventos/segundo por consumidor).
  • Backpressure: se o consumidor está lento, o barramento acumula eventos na fila (visível no dashboard).
  • Circuit breaker: se a taxa de erro ultrapassar 50% em 1 minuto, pausa o consumo e alerta.

7.3. Casos de sucesso e erros frequentes: migração gradual, testes de integração e rollback planejado

Caso de sucesso: empresa de logística migrou dados de 20 tabelas legadas para microsserviços em 3 meses, usando CDC + EventBridge. Zero downtime.

Erro frequente: esquecer de configurar idempotência. Resultado: registros duplicados no banco moderno.

Migração gradual: sincronize primeiro dados de clientes (baixo risco), depois pedidos (médio risco), por último transações financeiras (alto risco). Cada etapa com rollback planejado (voltar a sincronização manual).

Referências