11 de jun. de 2025·8 min de leitura

Bloqueio otimista para ferramentas administrativas: previna sobrescritas silenciosas

Aprenda bloqueio otimista para painéis administrativos com colunas de versão e checagens updated_at, além de padrões simples de UI para resolver conflitos de edição sem sobrescritas silenciosas.

Bloqueio otimista para ferramentas administrativas: previna sobrescritas silenciosas

O problema: sobrescritas silenciosas quando muitas pessoas editam

Uma “sobrescrita silenciosa” acontece quando duas pessoas abrem o mesmo registro, ambas fazem mudanças e a última pessoa a clicar em Salvar vence. As edições da primeira pessoa desaparecem sem aviso e frequentemente sem uma maneira fácil de recuperar.

Em um painel administrativo movimentado, isso pode acontecer o dia todo sem que ninguém perceba. Pessoas mantêm várias abas abertas, pulam entre tickets e voltam a um formulário que ficou aberto por 20 minutos. Quando finalmente salvam, não estão atualizando a versão mais recente do registro. Estão sobrescrevendo.

Isso aparece mais em ferramentas internas do que em apps públicos porque o trabalho é colaborativo e baseado em registros. Equipes internas editam os mesmos clientes, pedidos, produtos e solicitações repetidamente, muitas vezes em rajadas curtas. Apps públicos costumam ser “um usuário edita suas próprias coisas”, enquanto ferramentas administrativas são “muitos usuários editam coisas compartilhadas”.

O dano raramente é dramático no momento, mas acumula rápido:

  • O preço de um produto volta a um valor antigo logo após uma atualização de promoção.
  • A nota interna de um agente de suporte desaparece, então o próximo agente repete o mesmo troubleshooting.
  • O status de um pedido volta (por exemplo, “Enviado” para “Empacotado”), acionando o acompanhamento errado.
  • O telefone ou endereço de um cliente é substituído por informações desatualizadas.

Sobrescritas silenciosas são dolorosas porque todo mundo acha que o sistema salvou corretamente. Não há um momento claro de “algo deu errado”, apenas confusão depois quando relatórios ficam estranhos ou um colega pergunta: “Quem mudou isto?”

Conflitos assim são normais. São um sinal de que a ferramenta é compartilhada e útil, não de que sua equipe está errando. O objetivo não é impedir duas pessoas de editar. É detectar quando o registro mudou enquanto alguém estava editando e então lidar com esse momento com segurança.

Se você está construindo uma ferramenta interna em uma plataforma no-code como AppMaster, vale planejar isso cedo. Ferramentas administrativas tendem a crescer rápido, e uma vez que as equipes dependem delas, perder dados “às vezes” vira uma fonte constante de desconfiança.

Bloqueio otimista em linguagem simples

Quando duas pessoas abrem o mesmo registro e ambas apertam Salvar, você tem concorrência. Cada pessoa partiu de uma versão antiga, mas só uma pode ser “a mais recente” quando os salvamentos ocorrem.

Sem proteção, o último salvamento vence. É assim que você obtém sobrescritas silenciosas: o segundo salvamento substitui sem alarde as mudanças da primeira pessoa.

Bloqueio otimista é uma regra simples: “Eu vou salvar minhas mudanças apenas se o registro ainda estiver no mesmo estado de quando comecei a editar.” Se o registro mudou no meio tempo, o salvamento é rejeitado e o usuário vê um conflito.

Isso é diferente de bloqueio pessimista, que seria mais “estou editando isto, então ninguém mais pode”. Bloqueio pessimista geralmente significa locks pesados, timeouts e pessoas bloqueadas. Pode ser útil em casos raros (como mover dinheiro entre contas), mas frequentemente é frustrante em ferramentas administrativas movimentadas onde muitas pequenas edições acontecem o dia todo.

Bloqueio otimista costuma ser o padrão melhor porque mantém o fluxo de trabalho. Pessoas podem editar em paralelo e o sistema só intervém quando há uma colisão real.

Ele se encaixa melhor quando:

  • Conflitos são possíveis, mas não constantes.
  • Edições são rápidas (poucos campos, formulário curto).
  • Bloquear outros atrasaria muito a equipe.
  • Você pode mostrar uma mensagem clara “alguém atualizou isto”.
  • Sua API pode checar uma versão (ou timestamp) em cada atualização.

O que ele previne é o problema do “sobrescrever silencioso”. Em vez de perder dados, você tem uma parada limpa: “Este registro mudou desde que você o abriu.”

O que ele não faz também é importante. Não vai impedir duas pessoas de tomar decisões diferentes (mas válidas) baseadas na mesma informação antiga, e não vai mesclar mudanças magicamente. E se você pular a checagem no lado do servidor, na prática não terá resolvido nada.

Limites comuns a considerar:

  • Não resolve conflitos automaticamente (ainda é necessária uma escolha).
  • Não ajuda se usuários editam offline e sincronizam depois sem checagens.
  • Não corrige permissões ruins (alguém ainda pode editar o que não deveria).
  • Não detecta conflitos se a checagem for feita apenas no cliente.

Na prática, bloqueio otimista é apenas um valor extra enviado com a edição, mais uma regra server-side “só atualize se casar”. Se você está montando um painel administrativo no AppMaster, essa checagem normalmente vive na sua lógica de negócio exatamente onde as atualizações são executadas.

Duas abordagens comuns: coluna de versão vs updated_at

Para detectar que um registro mudou enquanto alguém o editava, você geralmente escolhe um de dois sinais: um número de versão ou um timestamp updated_at.

Abordagem 1: Coluna de versão (inteiro incrementante)

Adicione um campo version (geralmente inteiro). Quando você carrega o formulário de edição, também carrega a version atual. Ao salvar, você envia esse mesmo valor de volta.

A atualização só sucede se a versão armazenada ainda bater com o que o usuário viu ao começar. Se casar, você atualiza o registro e incrementa version em 1. Se não casar, você retorna um conflito em vez de sobrescrever.

Isso é fácil de entender: versão 12 significa “esta é a 12ª alteração”. Também evita problemas relacionados a tempo.

Abordagem 2: updated_at (comparação de timestamp)

A maioria das tabelas já tem um campo updated_at. A ideia é a mesma: leia o updated_at quando o formulário abre e inclua ele no salvamento. O servidor só atualiza se o updated_at estiver inalterado.

Pode funcionar bem, mas timestamps têm armadilhas. Bancos diferentes armazenam precisões diferentes. Alguns arredondam para segundos, o que pode perder edições rápidas. Se múltiplos sistemas escrevem no mesmo banco, drift de relógio e fuso-horário também podem criar casos confusos.

Uma forma simples de comparar:

  • Coluna de versão: comportamento mais claro, portátil entre bancos, sem problemas de relógio.
  • updated_at: frequentemente “gratuito” porque já existe, mas precisão e tratamento de relógio podem causar surpresas.

Para a maioria das equipes, uma coluna de versão é o melhor sinal primário. É explícita, previsível e fácil de referenciar em logs e tickets de suporte.

Se você está construindo no AppMaster, isso normalmente significa adicionar um campo inteiro version no Data Designer e garantir que sua lógica de atualização o verifique antes de salvar. Você pode manter updated_at para auditoria, mas deixe o número de versão decidir se uma edição é segura de aplicar.

O que armazenar e o que enviar em cada edição

Bloqueio otimista só funciona se cada edição carregar um marcador “visto por último” do momento em que o usuário abriu o formulário. Esse marcador pode ser um número version ou um timestamp updated_at. Sem ele, o servidor não consegue saber se o registro mudou enquanto o usuário digitava.

No próprio registro, mantenha seus campos de negócio normais mais um campo de concorrência controlado pelo servidor. O conjunto mínimo é:

  • id (identificador estável)
  • campos de negócio (nome, status, preço, notas etc.)
  • version (inteiro que incrementa a cada atualização bem-sucedida) ou updated_at (timestamp escrito pelo servidor)

Quando a tela de edição carrega, o formulário deve armazenar o valor visto por último desse campo de concorrência. Usuários não devem editá-lo, então mantenha-o oculto ou no estado do formulário. Exemplo: a API retorna version: 12 e o formulário mantém 12 até o Salvar.

Quando o usuário clica em Salvar, envie duas coisas: as mudanças e o marcador visto por último. A forma mais simples é incluí-lo no corpo da requisição de atualização, como id, campos alterados e expected_version (ou expected_updated_at). Se você está montando a UI no AppMaster, trate isso como qualquer outro valor vinculado: carregue com o registro, mantenha inalterado e envie junto no update.

No servidor, a atualização deve ser condicional. Você só atualiza se o marcador esperado casar com o que está atualmente no banco. Se não casar, não faça “merge” silencioso.

Uma resposta de conflito deve ser clara e fácil de tratar na UI. Uma resposta prática inclui:

  • status HTTP 409 Conflict
  • uma mensagem curta como “Este registro foi atualizado por outra pessoa.”
  • o valor atual do servidor (current_version ou current_updated_at)
  • opcionalmente, o registro atual do servidor (para a UI mostrar o que mudou)

Exemplo: Sam abre um registro de Cliente na versão 12. Priya salva uma mudança, tornando-a versão 13. Sam depois clica em Salvar com expected_version: 12. O servidor retorna 409 com o registro atual na versão 13. Agora a UI pode pedir para Sam revisar os valores mais recentes em vez de sobrescrever a edição da Priya.

Passo a passo: implementar bloqueio otimista de ponta a ponta

Envie telas de conflito melhores
Crie um diálogo simples de recarregar-e-continuar no construtor de UI para salvamentos obsoletos.
Prototipar UI

Bloqueio otimista basicamente se resume a uma regra: cada edição deve provar que se baseia na versão mais recente salva do registro.

1) Adicione um campo de concorrência

Escolha um campo que mude em cada gravação.

Um version inteiro dedicado é o mais fácil de entender. Comece em 1 e incremente a cada atualização. Se você já tem um updated_at confiável que sempre muda, pode usá-lo, mas garanta que ele atualize em toda escrita (incluindo jobs em background).

2) Envie esse valor ao cliente na leitura

Quando a UI abre uma tela de edição, inclua a version (ou updated_at) atual na resposta. Armazene-a no estado do formulário como um valor oculto.

Pense nisso como um recibo que diz: “Estou editando aquilo que eu li por último.”

3) Exija o valor na atualização

No Salvar, o cliente envia os campos editados mais o valor de concorrência visto por último.

No servidor, torne a atualização condicional. Em termos SQL, é:

UPDATE tickets
SET status = $1,
    version = version + 1
WHERE id = $2
  AND version = $3;

Se a atualização afetar 1 linha, o salvamento teve sucesso. Se afetar 0 linhas, alguém já mudou o registro.

4) Retorne o novo valor após o sucesso

Depois de um salvamento bem-sucedido, retorne o registro atualizado com a nova version (ou novo updated_at). O cliente deve substituir o estado do formulário pelo que o servidor retornar. Isso evita “salvar duas vezes” com uma versão antiga.

5) Trate conflitos como um resultado normal

Quando a atualização condicional falha, retorne uma resposta de conflito clara (frequentemente HTTP 409) que inclua:

  • o registro atual como está agora
  • as mudanças que o cliente tentou (ou informação suficiente para reconstruí-las)
  • quais campos diferem (se você puder calcular isso)

No AppMaster, isso mapeia bem para um campo de modelo PostgreSQL no Data Designer, um endpoint de leitura que retorna a versão e um Business Process que faz a atualização condicional e ramifica para sucesso ou conflito.

Padrões de UI que tratam conflitos sem irritar usuários

Adicione bloqueio otimista rapidamente
Adicione um campo de versão no Data Designer e mantenha cada atualização segura.
Comece a criar

Bloqueio otimista é só metade do trabalho. A outra metade é o que a pessoa vê quando o salvamento é rejeitado porque outra pessoa mudou o registro.

Boa UI para conflitos tem dois objetivos: impedir sobrescritas silenciosas e ajudar o usuário a concluir a tarefa rápido. Bem feito, parece uma proteção útil, não um bloqueio.

Padrão 1: Diálogo bloqueante simples (mais rápido)

Use quando as edições são pequenas e os usuários podem reaplicar suas mudanças depois de recarregar.

Mantenha a mensagem curta e específica: “Este registro mudou enquanto você editava. Recarregue para ver a versão mais recente.” Então ofereça duas ações claras:

  • Recarregar e continuar (primária)
  • Copiar minhas mudanças (opcional, mas útil)

“Copiar minhas mudanças” pode colocar os valores não salvos na área de transferência ou mantê-los no formulário após o recarregamento, para que as pessoas não precisem lembrar o que digitavam.

Funciona bem para atualizações de um campo, toggles, mudanças de status ou notas curtas. Também é o mais fácil de implementar em construtores, incluindo telas AppMaster.

Padrão 2: “Revisar mudanças” (melhor para registros de alto valor)

Use quando o registro é importante (preços, permissões, pagamentos) ou o formulário é longo. Em vez de um erro sem saída, leve o usuário para uma tela de conflito que compare:

  • “Suas edições” (o que ele tentou salvar)
  • “Valores atuais” (o mais recente no banco)
  • “O que mudou desde que você abriu” (os campos em conflito)

Mantenha o foco. Não mostre todo campo se apenas três estão em conflito.

Para cada campo em conflito, ofereça escolhas simples:

  • Manter o meu
  • Aceitar o deles
  • Mesclar (apenas quando fizer sentido, como tags ou notas)

Após o usuário resolver, salve de novo com o valor de versão mais novo. Se você suporta rich text ou notas longas, mostre um diff simples (adicionado/removido) para ajudar a decidir rápido.

Quando permitir sobrescrita forçada (e quem pode fazê-la)

Às vezes um overwrite forçado é necessário, mas deve ser raro e controlado. Se adicionar, torne deliberado: exija uma razão curta, registre quem fez e limite a papéis como admins ou supervisores.

Para usuários normais, padrão para “Revisar mudanças”. Sobrescrita forçada é mais defensável quando o usuário é proprietário do registro, o registro é de baixo risco ou o sistema está corrigindo dados ruins sob supervisão.

Exemplo: dois colegas editam o mesmo registro

Dois agentes de suporte, Maya e Jordan, trabalham na mesma ferramenta administrativa. Ambos abrem o mesmo perfil de cliente para atualizar o status e adicionar notas após ligações separadas.

Linha do tempo (com bloqueio otimista usando version ou checagem updated_at):

  • 10:02 - Maya abre o Cliente #4821. O formulário carrega Status = "Needs follow-up", Notas = "Called yesterday" e Version = 7.
  • 10:03 - Jordan abre o mesmo cliente. Ele vê os mesmos dados, também Version = 7.
  • 10:05 - Maya muda Status para "Resolved" e adiciona uma nota: "Issue fixed, confirmed by customer." Ela clica em Salvar.
  • 10:05 - O servidor atualiza o registro, incrementa Version para 8 (ou atualiza updated_at) e guarda uma entrada de auditoria: quem mudou o quê e quando.
  • 10:09 - Jordan digita uma nota diferente: "Customer asked for a receipt" e clica em Salvar.

Sem checagem de concorrência, o salvamento de Jordan poderia sobrescrever silenciosamente o status e a nota da Maya, dependendo de como a atualização foi construída. Com bloqueio otimista, o servidor rejeita a atualização de Jordan porque ele tenta salvar com Version = 7 enquanto o registro já está em Version = 8.

Jordan vê uma mensagem de conflito clara. A UI mostra o que aconteceu e dá um próximo passo seguro:

  • Recarregar o registro mais recente (descartar minhas edições)
  • Aplicar minhas mudanças em cima do registro mais recente (recomendado quando possível)
  • Revisar diferenças (mostrar “Meu” vs “Mais Recente”) e escolher o que manter

Uma tela simples pode mostrar:

  • “Este cliente foi atualizado por Maya às 10:05”
  • Os campos que mudaram (Status e Notas)
  • Uma prévia da nota não salva de Jordan, para que ele possa copiá-la ou reaplicá-la

Jordan escolhe “Revisar diferenças”, mantém o Status de Maya = "Resolved" e anexa sua nota às notas existentes. Ele salva novamente, desta vez usando Version = 8, e a atualização tem sucesso (agora Version = 9).

Estado final: sem perda de dados, sem adivinhação sobre quem sobrescreveu quem, e uma trilha de auditoria limpa mostrando a mudança de status de Maya e ambas as notas como edições separadas e rastreáveis. Em uma ferramenta construída com AppMaster, isso mapeia a uma checagem no update mais um pequeno diálogo de resolução de conflitos na UI.

Erros comuns que ainda causam perda de dados

Escolha seu caminho de deploy
Faça deploy para AppMaster Cloud, AWS, Azure, Google Cloud ou exporte o código-fonte.
Fazer deploy

A maioria dos bugs de “bloqueio otimista” não é sobre a ideia, mas sobre a passagem entre UI, API e banco. Se qualquer camada esquecer as regras, você ainda pode ter sobrescritas silenciosas.

Um erro clássico é coletar a versão (ou timestamp) quando a tela de edição carrega, mas não enviá-la no salvamento. Isso acontece quando um formulário é reutilizado entre páginas e o campo oculto é perdido, ou quando um cliente de API só envia “campos alterados”.

Outra armadilha comum é fazer checagens de conflito apenas no navegador. O usuário pode ver um aviso, mas se o servidor aceitar a atualização mesmo assim, outro cliente (ou um retry) pode sobrescrever os dados. O servidor deve ser o guardião final.

Padrões que mais causam perda de dados:

  • Token de concorrência ausente na requisição de salvamento (version, updated_at ou ETag), de modo que o servidor não tem nada para comparar.
  • Aceitar atualizações sem uma condição atômica, por exemplo atualizando só por id em vez de “id + version”.
  • Usar updated_at com baixa precisão (segundos). Duas edições no mesmo segundo podem parecer idênticas.
  • Substituir campos grandes (notas, descrições) ou arrays inteiros (tags, itens) sem mostrar o que mudou.
  • Tratar qualquer conflito como “apenas tente de novo”, o que pode reaplicar valores antigos sobre dados mais novos.

Um exemplo concreto: dois leads de suporte abrem o mesmo registro de cliente. Um adiciona uma longa nota interna, o outro muda o status e salva. Se seu salvamento sobrescrever o payload inteiro do registro, a mudança de status pode apagar acidentalmente a nota.

Quando um conflito ocorrer, equipes ainda perdem dados se a resposta da API for muito enxuta. Não retorne só “409 Conflict”. Retorne o suficiente para um humano consertar:

  • A versão atual do servidor (ou updated_at)
  • Os valores mais recentes do servidor para os campos envolvidos
  • Uma lista clara de campos que diferem (mesmo nomes simples)
  • Quem mudou e quando (se você rastrear isso)

Se você está implementando isso no AppMaster, aplique a mesma disciplina: mantenha a versão no estado da UI, envie-a no update e faça a checagem dentro da lógica do backend antes de escrever no PostgreSQL.

Verificações rápidas antes de liberar

Torne edições de dados confiáveis
Construa ferramentas internas nas quais sua equipe possa confiar, mesmo com muitos editores e filas ativas.
Comece no AppMaster

Antes de liberar, faça uma passagem rápida pelos modos de falha que criam o efeito “salvou, mas sobrescreveu alguém”.

Verificações de dados e API

Garanta que o registro carregue um token de concorrência de ponta a ponta. Esse token pode ser um version inteiro ou um updated_at timestamp, mas precisa ser tratado como parte do registro, não como metadado opcional.

  • Leituras incluem o token (e a UI o armazena no estado do formulário, não apenas na tela).
  • Toda atualização envia o token visto por último, e o servidor verifica antes de escrever.
  • No sucesso, o servidor retorna o novo token para manter a UI sincronizada.
  • Edições em massa e edições inline seguem a mesma regra, sem atalhos.
  • Jobs em background que editam as mesmas linhas também checam o token (ou vão criar conflitos que parecem aleatórios).

Se você constrói no AppMaster, verifique que o campo existe no Data Designer (version ou updated_at) e que seu Business Process de atualização o compara antes de executar a escrita no banco.

Verificações de UI

Um conflito só é “seguro” se o próximo passo for óbvio.

Quando o servidor rejeitar uma atualização, mostre uma mensagem clara como: “Este registro mudou desde que você o abriu.” Então ofereça uma ação segura primeiro: recarregar os dados mais recentes. Se possível, adicione um caminho “recarregar e reaplicar” que mantenha as entradas não salvas do usuário e as reaplique ao registro atualizado, para que uma correção pequena não vire uma sessão de reescrever.

Se sua equipe realmente precisa, adicione uma opção controlada de “forçar salvamento”. Proteja-a por papel, confirme e registre quem forçou e o que mudou. Isso mantém emergências possíveis sem transformar perda de dados em padrão.

Próximos passos: adicione bloqueio a um fluxo e expanda

Comece pequeno. Escolha uma tela administrativa onde as pessoas frequentemente se trombam e adicione bloqueio otimista primeiro. Áreas de alto conflito são normalmente tickets, pedidos, preços e inventário. Se você tornar conflitos seguros em uma tela movimentada, verá rápido o padrão que pode repetir em outros lugares.

Escolha o comportamento padrão de conflito desde o início, pois ele molda tanto a lógica do backend quanto a UI:

  • Bloquear e recarregar: pare o salvamento, recarregue o registro mais recente e peça ao usuário para reaplicar a mudança.
  • Revisar e mesclar: mostre “suas mudanças” vs “últimas mudanças” e deixe o usuário decidir o que manter.

Bloquear-e-recarregar é mais rápido de construir e funciona bem quando as edições são curtas (status, atribuição, notas pequenas). Revisar-e-mesclar vale a pena quando registros são longos ou de alto risco (tabelas de preço, edições multi-campo de pedidos).

Depois implemente e teste um fluxo completo antes de expandir:

  • Escolha uma tela e liste os campos que os usuários mais editam.
  • Adicione um valor de versão (ou updated_at) ao payload do formulário e exija-o no Salvar.
  • Faça a atualização condicional na escrita ao banco (só atualize se a versão casar).
  • Projete a mensagem de conflito e a próxima ação (recarregar, copiar meu texto, abrir tela de comparação).
  • Teste com dois navegadores: salve na aba A, depois tente salvar dados obsoletos na aba B.

Adicione logging leve para conflitos. Mesmo um evento simples “aconteceu conflito” com tipo de registro, nome da tela e papel do usuário ajuda a identificar pontos quentes.

Se você constrói ferramentas administrativas com AppMaster (appmaster.io), as peças principais se mapeiam de forma clara: modele um campo de versão no Data Designer, imponha atualizações condicionais em Business Processes e adicione um pequeno diálogo de conflito no UI builder. Depois que o primeiro fluxo estiver estável, repita o padrão tela a tela e mantenha a UI de conflito consistente para que os usuários aprendam uma vez e confiem no comportamento em todo lugar.

FAQ

O que é uma “sobrescrita silenciosa” e por que ela acontece?

Uma sobrescrita silenciosa acontece quando duas pessoas editam o mesmo registro em abas ou sessões diferentes e o último salvamento substitui as mudanças anteriores sem aviso. O problema é que ambos os usuários veem um “salvo com sucesso”, então as edições perdidas só são notadas mais tarde.

O que o bloqueio otimista faz em termos simples?

Bloqueio otimista significa que o app só salva suas mudanças se o registro não tiver sido alterado desde que você o abriu. Se outra pessoa salvou primeiro, seu salvamento é rejeitado com um conflito para que você possa revisar os dados mais recentes em vez de sobrescrevê-los.

Por que não simplesmente bloquear o registro para que ninguém mais edite?

O bloqueio pessimista bloqueia outras pessoas enquanto você edita, o que frequentemente gera espera, timeouts e perguntas como “quem bloqueou isto?”. Bloqueio otimista costuma se encaixar melhor em painéis administrativos porque as pessoas podem trabalhar em paralelo e só lidam com colisões quando elas realmente ocorrem.

Devo usar um número de versão ou `updated_at` para verificações de conflito?

Uma coluna de versão é geralmente a opção mais simples e previsível porque evita problemas de precisão de timestamps e relógios. Um updated_at pode funcionar, mas pode perder edições rápidas se o timestamp tiver baixa precisão ou for tratado de forma inconsistente entre sistemas.

Que dados precisam ser incluídos para que o bloqueio otimista funcione?

Você precisa de um token de concorrência controlado pelo servidor no registro, tipicamente version (inteiro) ou updated_at (timestamp). O cliente deve lê-lo ao abrir o formulário, mantê-lo inalterado enquanto o usuário edita e enviá-lo na hora do Save como o valor “esperado”.

Por que a verificação de versão precisa ser feita no servidor, e não só na UI?

Porque o cliente não pode ser confiável para proteger dados compartilhados. O servidor deve aplicar uma atualização condicional como “update where id = X and version = Y”; caso contrário, outro cliente, uma tentativa de retry ou um job em background pode sobrescrever silenciosamente as mudanças.

O que o usuário deve ver quando ocorre um conflito?

Um bom padrão é mostrar uma mensagem bloqueante dizendo que o registro mudou e oferecer uma ação segura: recarregar os dados mais recentes. Se possível, mantenha as entradas não salvas do usuário para reaplicá-las após o recarregamento, evitando que ele precise reescrever tudo.

O que a API deve retornar num conflito para ajudar a UI a recuperar?

Retorne uma resposta de conflito clara (frequentemente 409) e contexto suficiente para recuperar: a versão atual do servidor e os valores mais recentes. Se puder, inclua quem atualizou e quando, para que o usuário entenda por que seu salvamento foi rejeitado e o que mudou.

Quais são os erros mais comuns que ainda levam à perda de dados?

Fique atento à ausência do token no salvamento, atualizações que filtram apenas por id em vez de id + version, e verificações de timestamp com baixa precisão. Outro problema comum é substituir o payload inteiro do registro (como notas ou arrays), o que aumenta a chance de apagar a edição de alguém.

Como implemento isso no AppMaster sem programar?

No AppMaster, adicione um campo version no Data Designer e inclua-o no registro que sua UI lê para o estado do formulário. Em seguida, force uma atualização condicional dentro do Business Process para que o gravar só tenha sucesso quando a versão esperada casar, e trate o ramo de conflito na UI com um fluxo de recarregar/revisar.

Fácil de começar
Criar algo espantoso

Experimente o AppMaster com plano gratuito.
Quando estiver pronto, você poderá escolher a assinatura adequada.

Comece
Bloqueio otimista para ferramentas administrativas: previna sobrescritas silenciosas | AppMaster