# Consistência eventual: quando aceitar dados temporariamente inconsistentes é a decisão correta

Muitos desenvolvedores tratam qualquer inconsistência de dados como bug. Mas aceitar alguns milissegundos de divergência entre réplicas, em troca de latência menor e mais disponibilidade, muitas vezes é a decisão certa. A questão é saber **onde** fazer essa troca.

## O que é consistência eventual

É a garantia de que, se não houver novas escritas, todas as réplicas vão convergir para o mesmo valor em algum momento. Não diz *quando*. No outro extremo está a consistência forte (linearizabilidade): toda leitura vê a escrita mais recente, como se houvesse uma única cópia do dado.

## CAP e PACELC

O teorema CAP diz que, durante uma **partição de rede**, um sistema distribuído precisa escolher entre **consistência** (recusar requisições para não retornar dados velhos) e **disponibilidade** (responder mesmo arriscando divergência). O famoso "escolha 2 de 3" engana: partições acontecem, então a escolha real é entre C e A quando elas ocorrem.

O problema é que partições são raras. O **PACELC** completa o quadro: *se houver Partição, escolha A ou C; senão (Else), escolha entre Latência e Consistência*. Essa segunda metade afeta seu sistema todos os dias, porque garantir consistência entre réplicas exige esperar confirmação de outros nós.

| Sistema | Com partição | Operação normal |
| --- | --- | --- |
| Dynamo / Cassandra | Disponibilidade | Latência |
| Google Spanner | Consistência | Consistência |
| PostgreSQL + réplicas assíncronas | Depende de onde a leitura vai | Latência nas réplicas |

## Replicação: onde a inconsistência nasce

Na prática, você encontra consistência eventual ao adicionar réplicas de leitura. Na **replicação síncrona**, o primário só confirma a escrita após uma réplica gravar: mais seguro, mais lento. Na **assíncrona**, o primário confirma na hora e replica em segundo plano: rápido, mas as réplicas ficam atrás por um intervalo chamado *replication lag*. Normalmente milissegundos; sob carga pesada ou durante uma migração, segundos ou minutos.

## Read-after-write: o problema que o usuário vê

Se um cliente vê um preço antigo por 200 ms, ninguém percebe. Mas quando o **próprio autor** da alteração não a vê, parece bug: o lojista edita um prato, salva, é redirecionado para a listagem e o nome antigo aparece. A escrita foi para o primário; a leitura, para uma réplica atrasada.

A garantia que resolve isso é **read-your-writes**: cada usuário sempre vê as próprias escritas. Ela é bem mais barata que consistência forte, porque só vale para quem escreveu. Algumas formas de implementar:

**1\. Ler do primário após escrever.** No Laravel, a opção `sticky` faz isso dentro da mesma requisição:

```php
'pgsql' => [
    'read'  => ['host' => ['replica-1.internal']],
    'write' => ['host' => ['primary.internal']],
    'sticky' => true,
],
```

O limite: não cobre o padrão "salvar e redirecionar", que gera uma requisição nova.

**2\. Janela por usuário.** Após escrever, marque na sessão ou no Redis que aquele usuário lê do primário pelos próximos N segundos. Simples, mas N é um palpite.

**3\. Rastrear a posição de replicação.** No PostgreSQL, guarde o LSN da escrita e só leia de uma réplica que já chegou nele:

```sql
-- no primário, após a escrita
SELECT pg_current_wal_lsn();

-- na réplica, antes de ler
SELECT pg_last_wal_replay_lsn() >= '0/3A1B2C8'::pg_lsn;
```

**4\. UI otimista.** Com React Query, atualize o cache local com o valor que o usuário enviou e evite refazer a busca na hora.

## Quando consistência forte é desnecessária

A pergunta certa é: **qual o custo de alguém ver este dado desatualizado por alguns segundos?** Quando é quase zero, consistência eventual vence. Exemplos: contadores e métricas de dashboard, cardápios e catálogos (lidos por muitos, editados por poucos), índices de busca, feeds e notificações.

Já estes casos pedem consistência forte no ponto crítico:

*   **Dinheiro:** cobranças e reembolsos, sempre com idempotência para evitar cobrança dupla em retentativas.
    
*   **Recursos escassos:** o último item do estoque, cupons limitados. Use transação no primário ou `SELECT ... FOR UPDATE`.
    
*   **Unicidade:** e-mail, slug da loja. Constraint no banco.
    
*   **Permissões:** acesso revogado não pode continuar valendo numa réplica atrasada.
    

A decisão é **por operação**, não por sistema. O mesmo app pode servir o cardápio de uma réplica e debitar o estoque com lock no primário.

## Conclusão

Consistência eventual não é gambiarra: é como boa parte da internet se mantém rápida e resiliente. O trabalho do engenheiro é proteger os poucos pontos onde a consistência forte é inegociável e deixar o resto fluir, garantindo sempre que o usuário veja o que ele mesmo acabou de fazer.

* * *

## Referências

1.  VOGELS, W. Eventually Consistent. *Communications of the ACM*, v. 52, n. 1, 2009.
    
2.  BREWER, E. Towards Robust Distributed Systems. Keynote, *PODC*, 2000.
    
3.  GILBERT, S.; LYNCH, N. Brewer's Conjecture and the Feasibility of Consistent, Available, Partition-Tolerant Web Services. *ACM SIGACT News*, v. 33, n. 2, 2002.
    
4.  BREWER, E. CAP Twelve Years Later: How the "Rules" Have Changed. *IEEE Computer*, v. 45, n. 2, 2012.
    
5.  ABADI, D. Consistency Tradeoffs in Modern Distributed Database System Design. *IEEE Computer*, v. 45, n. 2, 2012.
    
6.  KLEPPMANN, M. *Designing Data-Intensive Applications*. O'Reilly, 2017. Cap. 5.
    
7.  TERRY, D. B. et al. Session Guarantees for Weakly Consistent Replicated Data. *PDIS*, 1994.
    
8.  [Laravel: Read and Write Connections](https://laravel.com/docs/12.x/database#read-and-write-connections)
    
9.  [PostgreSQL: System Administration Functions](https://www.postgresql.org/docs/current/functions-admin.html)
    
10.  [Stripe: Idempotent Requests](https://docs.stripe.com/api/idempotent_requests)
