Radar Tech: o banco que prometia ACID, perdeu commit confirmado e mostrou por que "compatível" não é "garantia"
Um relatório adversarial independente encontrou dezenas de falhas em um banco multi-model pensado para aplicações de IA: filtros que retornam o conjunto errado, constraints que não bloqueiam nada e perda de transação confirmada em operação normal, no modo default. O que fica para a arquitetura: separar dado de registro de estado reconstruível e provar durabilidade antes de migrar.
O que apareceu nas últimas 24 horas
O assunto mais comentado do dia no noticiário técnico foi um relatório de auditoria adversarial, financiado pelo próprio fornecedor, sobre um banco de dados novo chamado ParticleDB — um engine "multi-model" em Rust, criado para aplicações de IA, que junta SQL transacional, chave-valor, busca vetorial e analítico em um só lugar. Ele é desenvolvido pela Orkes, empresa da plataforma de orquestração de workflows Conductor, para resolver um problema real: manter estado de agentes, filas, documentos e relatórios em sistemas separados é caro e propenso a inconsistência.
O resumo do relatório, para quem não vai ler as dezenas de páginas: "ACID completo" era uma promessa prematura. Foram encontrados aspectos que vão do banal (crashes, deadlocks, perda de dados) ao surreal — linhas parcialmente invisíveis que não podiam ser apagadas, WHERE 4 = 5 retornando linhas, tabelas dropadas ressurgindo distorcidas, colunas confundidas, strings virando inteiros. A maior parte disso apareceu em uma instância saudável, com um cliente, sem injeção de falha. Ou seja: não era necessário um ataque nem uma falha de disco — bastava usar o banco.
O detalhe mais grave não é o volume de bugs, é a natureza de dois deles: no modo de transação default, o banco continuava perdendo escritas já confirmadas em operação normal; e no modo mais forte, ainda permitia anomalia interna e perda de atualização — inclusive quando o processo era morto. O fornecedor já publicou versões com correções e afirma que os problemas foram resolvidos. A auditoria não testou essas versões.
Em paralelo, três episódios da semana pintam o pano de fundo: um incidente de segurança em um provedor de PaaS que forçou clientes a assumir que segredos de ambiente foram decifrados; a disputa sobre custo e uso de modelos de IA em ferramentas de código, com fornecedores bloqueando usos que antes eram permitidos; e a discussão sobre o preço escondido de frameworks JavaScript na era de agentes de código. O fio comum é o mesmo: o que você contrata nem sempre é o que você recebe, e a diferença não aparece no dia da adoção — aparece no incidente.
O bug mais caro é o que não gera erro
Um crash é inconveniente, mas honesto: você perde disponibilidade e ganha um alerta. O bug que realmente destrói confiança em um banco é o silencioso. O relatório traz vários exemplos de uma categoria que merece nome próprio:
- constraints que não bloqueiam —
NOT NULLeUNIQUEinoperantes, chave primária duplicada e nula; - predicados que retornam o conjunto errado sem erro — filtro que casa qualquer coisa, filtro que não casa nada, comparação com tipo diferente que vira resultado aleatório;
- conversões silenciosas — string interpretada como inteiro, float grande virando infinito,
character(n)devolvendo menos caracteres que o declarado.
Nada disso gera exceção. O programa continua rodando, o painel continua verde e o dado errado entra na base. Em um sistema de cadastro é um relatório estranho; em um banco que guarda a memória de um agente de IA ou o estado de um job que dispara pagamento, é o agente repetindo um efeito externo porque o checkpoint que ele achava durável não sobreviveu.
É por isso que "o fornecedor corrigiu 86 dos 96 problemas" é uma métrica enganosa. Bug de banco não é evento isolado, é classe: se WHERE 4 = 5 retorna linhas, o caminho que avalia predicados não está verificando o que deveria — e todo predicado que você escrever passa pelo mesmo caminho. A pergunta certa não é "quantos foram corrigidos", é "que classe de teste passou a existir para impedir a próxima".
Documentação como claim, não como evidência
O relatório também descreve algo que qualquer arquiteto deveria tratar como sinal vermelho: o site do produto anunciava "prova formal em TLA+", mas nenhuma especificação foi disponibilizada durante o trabalho; a página dizia "ACID completo" e, na linha de baixo, "snapshot isolation" — que não é isolamento completo. A documentação dos modos de transação usava expressões como "seguro sob concorrência" sem dizer quais fenômenos o modo proíbe. O guia interno e a CLI se contradiziam sobre qual era o default e sobre a durabilidade de cada modo de fsync.
Há exemplos ainda mais duros de documentação que não correspondia ao software: um cliente oficial cujas coordenadas de dependência não existiam, quickstarts com nomes de usuário errados, e até um e-mail inventado atribuído ao autor do relatório. Nada disso quebra um banco, mas comprova um ponto: a documentação foi gerada com aparência de maturidade, não necessariamente com verificação.
O desfecho também ensina. Depois do relatório, o fornecedor reclassificou as versões avaliadas como "builds de pré-release não suportadas" — versões com numeração de produção, que a página de instalação mandava rodar "para produção". E, ao substituir os modos antigos, a documentação diz que eles foram "removidos", então explica que os antigos eram "nomes anteriores" dos novos. Renomear é mais barato do que remover; e nenhuma das duas frases prova o que aconteceu.
O que isso muda na arquitetura (e o que não muda)
A tentação é transformar a notícia em veredito binário: "banco novo é bom" ou "banco novo é golpe". Os dois são preguiçosos. O que o caso ensina é mais útil e menos confortável:
- Nenhum banco é seguro por inteiro para todo tipo de dado. A decisão não é onde guardar tudo, é onde guardar o que não pode desaparecer. Chame isso de dado de registro: ledger, saldo, pedido, permissão, cadastro. Ele fica onde há prova de durabilidade e reconciliação — não onde há entusiasmo.
- Durabilidade é a propriedade mais fácil de ignorar e a mais cara de descobrir. Um commit confirmado que evapora no crash não tem sintoma no dia seguinte; tem sintoma no fechamento, na auditoria, no cliente que perdeu o pedido. O único teste que decide é o desconfortável: confirmar mil commits, matar o processo no meio e provar que mil linhas existem depois.
- Configuração é parte da garantia. Se o modelo de isolamento depende de um modo de concorrência e de um modo de fsync, então "o banco oferece X" é falso para quem instalou com o default. Um ADR que não fixa o modo não fixa nada.
- "Compatível com Postgres" é promessa de forma, não de fundo. Aceitar o protocolo é a parte fácil; a semântica de predicado, a ordem de validação de constraint e a collation são a parte que muda resultados. Quem migra com a ilusão de compatibilidade descobre a diferença em produção.
- Benchmark de fornecedor não é prova de escala. A ordem de magnitude anunciada é útil como convite a testar; como base de dimensionamento é só marketing.
A pergunta que vale para o seu time
Antes de adotar o próximo banco "mais rápido", a pergunta não é "ele é bom?". É: quanto do nosso dado não pode desaparecer, e o que conseguiria provar hoje se alguém me perguntasse se um commit confirmado sobrevive a um crash? A maioria dos times descobre, nessa pergunta, que nunca testou — e que a resposta "o fornecedor diz que sim" é exatamente a resposta que esse relatório pôs em dúvida.
O que sobra de prático: separar dado de registro de estado reconstruível, replicar o primeiro por fila durável ou outbox, escrever um ADR dizendo onde cada classe de dado mora, e transformar durabilidade e equivalência de semântica em testes executados no CI — não em documento assinado. A notícia de hoje não condena um produto; ela mostra quanto do que chamamos de garantia é, na prática, uma frase bem escrita.
Nota: decisões sobre onde hospedar dado de registro, migração de banco e aceitação de risco de inconsistência devem ser revisadas por quem responde pela integridade dos dados e pela disponibilidade do serviço. Uma saída de IA organiza evidências e aponta lacunas — não substitui o julgamento de quem assina a decisão.