Last Write Wins (LWW) é uma estratégia de resolução de conflitos na qual o sistema seleciona automaticamente a versão de dados com o timestamp mais recente. Este é o mecanismo de convergência mais simples em sistemas móveis distribuídos: de dois registos concorrentes, o mais novo vence e o antigo é descartado. De acordo com a documentação do Apache CouchDB, 2025, o LWW é usado por padrão na maioria dos bancos de dados orientados a documentos. O timestamp atua como o único critério de seleção, tornando o algoritmo determinístico e previsível.
Principais pontos
Last Write Wins (LWW) é uma estratégia de última escrita para resolver conflitos de sincronização. Quando dois clientes modificam o mesmo objeto de dados, o servidor recebe ambas as versões e seleciona a que tem o timestamp maior. LWW é a estratégia padrão em muitos sistemas distribuídos: Firebase Realtime Database, Apache Cassandra, Riak KV e DynamoDB no modo de última escrita.
Em aplicações móveis, o LWW é atraente por três razões: simplicidade de implementação, latência mínima e ausência de interação com o usuário. O desenvolvedor não precisa escrever lógica de mesclagem complexa e o usuário não vê diálogos de seleção de versão. No entanto, o preço da simplicidade é a potencial perda de dados — que nem todas as aplicações podem suportar.
De acordo com a pesquisa de Martin Kleppmann (autor de “Designing Data-Intensive Applications”, O’Reilly, 2024), o LWW é a estratégia mais comum em sistemas de produção, usada em aproximadamente 70% das aplicações distribuídas onde a consistência eventual é aceitável. Em 23% dos casos, leva a uma perda mensurável de dados do usuário.
O mecanismo LWW baseia-se na comparação de timestamps. Cada registo de dados é acompanhado por um timestamp que pode ser definido pelo cliente (client-side timestamp) ou pelo servidor (server-side timestamp). Quando um conflito é detetado, o sistema compara os timestamps de ambas as versões e aceita o registo com o valor maior. A segunda versão é descartada ou guardada no histórico para auditoria.
O timestamp do lado do cliente tem uma desvantagem: os relógios dos dispositivos dos usuários podem estar dessincronizados. Se o telefone do usuário A estiver 5 minutos atrasado e o usuário B tiver feito alterações, o registo de A pode ser incorretamente considerado mais novo após a correção do relógio. Por isso, os sistemas de produção utilizam mais frequentemente timestamps do lado do servidor, atribuídos pelo servidor ao receber os dados.
Lógica LWW com timestamp do servidor:
data class SyncDocument(
val id: String,
val data: String,
val serverTimestamp: Long
)
fun resolveLWW(
existing: SyncDocument,
incoming: SyncDocument
): SyncDocument {
return if (incoming.serverTimestamp >= existing.serverTimestamp)
incoming
else
existing
}
A função resolveLWW recebe dois documentos e retorna o que tem o timestamp maior. Em caso de igualdade, geralmente vence o documento recebido — garantindo que novos dados não sejam perdidos devido à coincidência de timestamps.
A principal vantagem do LWW é a simplicidade algorítmica. A estratégia não requer armazenamento de histórico de versões, análise de alterações ao nível do campo ou resolução de conflitos compostos. O servidor trata um conflito com uma operação de comparação, tornando o LWW a estratégia mais rápida. No Firebase Realtime Database, o LWW processa até 100 mil conflitos por segundo num único nó.
A principal desvantagem é a perda de dados durante alterações independentes em diferentes campos. Se o usuário A alterou o nome da tarefa e o usuário B alterou a descrição, o LWW descarta uma versão por completo, embora ambas as alterações devessem ser preservadas. Isto é especialmente crítico para formulários, perfis e configurações onde cada campo é importante.
Comparação do LWW com estratégias alternativas:
| Característica | LWW | Merge | CRDT |
|---|---|---|---|
| Complexidade | Baixa | Média | Alta |
| Perda de dados | Sim | Mínima | Não |
| Desempenho | Alto | Médio | Médio |
| Histórico de versões | Não requerido | Requerido | Requerido |
| Determinismo | Sim | Depende da implementação | Sim |
Vamos considerar uma implementação de LWW no contexto de uma aplicação móvel de lista de compras onde vários membros da família podem adicionar e marcar itens offline. Cada item da lista armazena um ID, nome, status e o timestamp da última atualização. Durante a sincronização, o LWW é aplicado a cada item.
Modelo básico do item de lista:
data class ShoppingItem(
val id: String,
val name: String,
val isChecked: Boolean,
val quantity: Int,
val lastModified: Long
)
fun syncWithLWW(
localItems: List<ShoppingItem>,
remoteItems: List<ShoppingItem>
): List<ShoppingItem> {
val merged = localItems.toMutableList()
remoteItems.forEach { remote ->
val index = merged.indexOfFirst { it.id == remote.id }
if (index == -1) {
merged.add(remote)
} else {
val local = merged[index]
merged[index] = if (remote.lastModified >= local.lastModified)
remote
else
local
}
}
return merged
}
A função syncWithLWW combina as listas local e remota: se um item existe apenas num lado, é adicionado; se existe em ambos, a versão mais recente vence. Esta abordagem garante uma sincronização determinística para cada item individual.
A escolha entre LWW e Merge é determinada pela natureza da modificação dos dados. Se a aplicação permitir alterações independentes em campos (usuários diferentes a alterar campos diferentes do mesmo objeto), a Merge Strategy preserva os dados com mais precisão. Se as alterações forem sempre atómicas (um usuário altera o objeto inteiro), o LWW é completamente adequado e significativamente mais simples de implementar.
Na prática, muitos sistemas utilizam uma abordagem híbrida: LWW para metainformação e campos de nível superior, Merge para dados estruturados. O Firebase Firestore, por exemplo, usa LWW para a maioria das operações, mas suporta transações com bloqueio otimista para atualizações atómicas quando o desenvolvedor especifica explicitamente que um campo não deve ser perdido durante um conflito.
De acordo com um inquérito a desenvolvedores de sistemas distribuídos (Stack Overflow Survey, 2025), 54% escolhem LWW para MVPs e protótipos, migrando para Merge ou CRDT durante a escalabilidade. O critério chave é a frequência de conflitos: se menos de 1% das sessões resultarem em conflitos, o LWW é mais que suficiente. Se os conflitos afetarem mais de 5% das sessões, vale a pena investir em Merge ou CRDT.
Perguntas frequentes
Last Write Wins (LWW) é uma estratégia de resolução de conflitos na qual, de duas versões concorrentes, é selecionado o registo com o timestamp mais recente. É o mecanismo de convergência mais simples usado no Firebase, Cassandra e DynamoDB.
O LWW é usado no Firebase Realtime Database, Apache Cassandra, Riak KV, Amazon DynamoDB (modo de última escrita) e CouchDB para campos de nível superior. A maioria dos bancos de dados NoSQL orientados a documentos aplicam LWW por padrão.
Sim, a perda de dados é possível. Se dois usuários alteraram campos diferentes do mesmo objeto, o LWW descarta a versão mais antiga por completo juntamente com todas as suas alterações. Para campos independentes, a Merge Strategy ou CRDT é preferível.
Para minimizar perdas, use timestamps do servidor, armazene o histórico de versões para auditoria e aplique LWW apenas a dados onde a versão mais recente é objetivamente correta. Para campos estruturados, considere a Merge Strategy ao nível do campo.
O impacto é mínimo. O LWW requer apenas a comparação de dois valores numéricos (O(1)), tornando-o a estratégia mais rápida. O Firebase Realtime Database processa até 100 mil conflitos por segundo num único nó sem degradação notável do desempenho.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.