System Design/04 - Cloud Design Patterns/Messaging2 min
Sequential Convoy
- Que problema isso resolve?
- Quando usar / quando NÃO usar?
- Qual o principal trade-off?
- Como isso falha em produção?
Conceito
Garantir ordem dentro de um grupo de mensagens relacionadas, mantendo paralelismo entre grupos.
cliente-A: A1 → A2 → A3 processados em ordem
cliente-B: B1 → B2 em paralelo com A, e em ordem entre si
cliente-C: C1 idem
A chave de agrupamento é o mecanismo: Message Group ID no SQS FIFO, partition key no Kafka e no Kinesis, session ID no Service Bus. Mensagens com a mesma chave vão para a mesma partição e são processadas sequencialmente por um único consumidor.
Trade-offs
É o meio-termo entre dois extremos ruins.
Ordem global (uma fila, um consumidor) garante tudo e elimina o paralelismo — o throughput fica limitado a um consumidor, independentemente de quanta capacidade exista.
Sem ordem (Competing Consumers puro) escala perfeitamente e permite que a atualização de um registro seja processada antes da criação dele.
O convoy sequencial dá ordem onde ela importa e paralelismo onde ela não importa. O limite fica sendo o número de chaves distintas: com 10 mil clientes, há até 10 mil fluxos paralelos.
Os custos:
Uma mensagem lenta bloqueia seu grupo inteiro. É head-of-line blocking por chave. Se o processamento de A1 trava, A2 e A3 esperam — mesmo com workers ociosos. Timeout por mensagem é obrigatório.
Mensagem venenosa é pior aqui. Sem DLQ, uma mensagem que sempre falha bloqueia permanentemente todo o grupo, não apenas a si mesma.
Chave mal escolhida desbalanceia. Uma chave que concentra a maior parte do tráfego cria uma partição quente, e o paralelismo teórico não se realiza. É o mesmo problema de shard key em Sharding.
E há um limite estrutural: a ordem só é garantida dentro da chave. Se a lógica de negócio precisa de ordem entre chaves diferentes, o padrão não resolve.
Exemplo prático
Eventos de conta bancária, onde a ordem por conta é indispensável e a ordem entre contas é irrelevante.
MessageGroupId = conta_id
Depósito e saque da mesma conta são processados na ordem correta. Contas diferentes são processadas simultaneamente por workers diferentes.
Sem o agrupamento, um saque poderia ser processado antes do depósito que o cobre — e o saldo ficaria negativo por uma questão de escalonamento, não de negócio.
Com ordem global, o sistema processaria uma conta por vez: correto e inutilizável em qualquer escala.
Relacionado
Parte de Messaging · roadmap.sh/system-design