Banco de dados em projetos de Vibe Coding: guia completo
O erro número 1 dos projetos de Vibe Coding
Peça para uma IA gerar uma tela de cadastro de pedidos e ela vai fazer isso bem: campo de nome, campo de valor, botão de salvar, tudo funcionando em minutos. Peça para ela pensar no schema de banco de dados que vai sustentar esse pedido daqui a um ano, com histórico, cancelamento, reembolso parcial e relatório mensal, e a resposta tende a ser bem mais frágil. Esse é o erro número um em projetos de Vibe Coding: o banco de dados nasce improvisado, desenhado tela por tela, em vez de desenhado como modelo de dados coerente antes de qualquer tela existir.
O sintoma aparece tarde, e é isso que o torna perigoso. O produto funciona bem nos primeiros meses, com poucos dados e poucos usuários testando o caminho feliz. O problema estoura quando o volume cresce, quando aparece um caso de uso que o schema original não previu, ou quando dois times mexem na mesma tabela sem saber o que o outro mudou. Neste guia, o assunto é como pensar em banco de dados de projetos de Vibe Coding do jeito que evita boa parte desse retrabalho: modelagem, convenções, migrações, segurança e o backup que ninguém lembra até precisar dele.
Modelagem: pense em entidades, não em telas
O hábito mais comum, e mais fácil de corrigir, é desenhar tabelas espelhando exatamente os campos de um formulário. Isso parece prático no início, mas confunde o que é dado permanente com o que é só apresentação. A alternativa é pensar em entidades: quais “coisas” o negócio realmente tem (cliente, pedido, produto, pagamento) e como elas se relacionam entre si, independentemente de como uma tela específica vai exibir esses dados.
Um exercício simples ajuda bastante antes de escrever a primeira linha de SQL: liste os substantivos do seu produto (o que ele guarda) e depois os verbos (o que acontece com eles). Cliente faz pedido, pedido tem itens, item referencia produto, pagamento se relaciona a pedido. Esse mapeamento vira o esqueleto das tabelas e das relações entre elas, e resolve de cara perguntas que aparecem tarde demais quando ignoradas, como “um pedido pode ter mais de um pagamento?” ou “um produto pertence a mais de uma categoria?”.
Vale também decidir cedo o nível de normalização que faz sentido para o seu caso. Dado repetido em várias tabelas parece inofensivo no início e vira fonte de inconsistência conforme o sistema cresce, porque uma atualização esquece de propagar em algum lugar. Nem tudo precisa de normalização extrema, mas dado que muda com frequência (como o nome de um cliente) geralmente deveria viver em um único lugar de origem, referenciado, não copiado. Esse é um dos pontos que separam um MVP que só demonstra a ideia de um produto pronto para produção, tema que tratamos com mais profundidade no artigo sobre criar um SaaS com IA.
Um exemplo concreto ajuda a fixar a diferença. Imagine um produto de agendamento de serviços. Desenhar “pela tela” produz uma tabela agendamentos com nome do cliente, telefone e serviço escritos direto ali, repetidos em cada linha. Desenhar por entidade produz clientes, servicos e agendamentos referenciando os dois primeiros por identificador. A segunda abordagem parece mais trabalho no dia um, mas evita que uma troca de telefone do cliente exija atualizar dezenas de linhas espalhadas, e permite relatórios (quantos agendamentos por cliente, por serviço) que a primeira estrutura simplesmente não suporta sem gambiarra.
Postgres/Supabase: convenções que salvam
Postgres, especialmente via Supabase, é hoje a escolha mais comum em projetos de Vibe Coding, e por bons motivos: maduro, com RLS embutido, extensível e bem documentado, o que ajuda tanto a IA quanto quem revisa o código depois. Algumas convenções simples, adotadas desde o início, evitam boa parte da dor de cabeça mais adiante:
- Nomeie tabelas no plural e em minúsculas (
pedidos, nãoPedido), de forma consistente em todo o projeto. - Use
uuidcomo chave primária em vez de inteiro sequencial sempre que o identificador puder aparecer em uma URL pública, para evitar que alguém descubra quantos registros existem só somando 1 ao número da URL. - Defina
NOT NULLem toda coluna que o negócio realmente exige, em vez de permitir nulo “porque é mais rápido não pensar nisso agora”. - Use tipos de dado específicos (data, numérico com precisão definida, enum) em vez de texto genérico para tudo, o que evita boa parte dos bugs de validação que aparecem só em produção.
- Padronize nomes de coluna de data e hora (
created_at,updated_at) em todas as tabelas, para que qualquer consulta de auditoria funcione de forma previsível.
Nenhuma dessas convenções é sofisticada. O valor delas está em serem aplicadas sempre, sem exceção “só dessa vez”, porque é exatamente a exceção que vira inconsistência difícil de rastrear meses depois.
Migrações: por que “editar direto no banco” cobra caro
A interface visual do Supabase Studio, ou de qualquer painel administrativo de banco de dados, torna tentador alterar uma tabela direto ali: adicionar uma coluna, mudar um tipo, apagar algo que parece não estar em uso. É rápido, funciona na hora, e é exatamente esse tipo de mudança sem rastro que gera os incidentes mais difíceis de depurar depois.
Migração versionada resolve isso: cada alteração de schema vira um arquivo, com data e descrição, versionado junto do código no mesmo repositório Git. Isso traz três benefícios concretos. Primeiro, qualquer pessoa do time consegue ver o histórico completo de como o banco chegou ao estado atual, sem depender de perguntar “quem mudou essa coluna e por quê”. Segundo, o ambiente de produção e o de desenvolvimento ficam sincronizados de forma confiável, porque a mesma sequência de migrações roda nos dois lugares. Terceiro, e mais importante na prática: uma migração mal feita pode ser revertida, porque existe um registro exato do que foi alterado, o que uma edição manual no painel visual normalmente não deixa.
O custo de não fazer isso aparece tarde, geralmente no dia em que uma coluna precisa mudar de tipo com dados de produção já dentro dela, e ninguém no time sabe ao certo qual era a estrutura anterior nem o que outra alteração manual, feita meses atrás, pode ter deixado inconsistente.
RLS e segurança de dados
Row Level Security (RLS) é o mecanismo que define, dentro do próprio banco, quem pode ler ou escrever cada linha de cada tabela, independentemente do que a interface do produto mostra ou esconde. Em bancos usados por Supabase, essa camada é especialmente importante porque o banco costuma ficar acessível diretamente pela API, não só através do backend da aplicação.
O padrão de falha mais comum é RLS desativado “por enquanto, para não travar durante o desenvolvimento”, e nunca reativado antes do lançamento. Isso significa que qualquer pessoa com a chave pública do projeto, visível no código do navegador, consegue ler e às vezes até alterar dado de outros usuários direto pela API, sem passar pela sua aplicação. O tratamento correto é ativar RLS em toda tabela com dado de usuário desde o início do projeto, escrever policies explícitas por operação (quem pode ler, inserir, atualizar, apagar cada linha) e testar essas policies logado como um usuário comum tentando acessar dado que não é seu. Esse é só um dos riscos que merecem checklist próprio antes de lançar um produto de Vibe Coding, e tratamos o tema de forma mais ampla no artigo sobre se Vibe Coding é seguro.
Índices e performance básica
Um índice funciona como o sumário de um livro: sem ele, o banco precisa ler linha por linha até achar o que procura, o que é rápido com cem registros e lento com um milhão. A regra prática mais simples é indexar toda coluna usada com frequência em filtros (WHERE), ordenação (ORDER BY) ou junção entre tabelas (JOIN), especialmente chaves estrangeiras, que raramente vêm indexadas por padrão.
Índice em excesso também tem custo: cada índice a mais deixa operações de escrita um pouco mais lentas, porque o banco precisa atualizar tanto a tabela quanto todos os índices dela a cada inserção. O equilíbrio certo, para a maioria dos projetos, é indexar o que realmente aparece em consultas frequentes e revisar periodicamente quais consultas estão lentas, usando as ferramentas de análise que o próprio Postgres oferece, em vez de indexar tudo de forma preventiva sem medir o efeito real.
Na prática, o comando EXPLAIN ANALYZE do Postgres, rodado na frente de uma consulta lenta, mostra exatamente por onde o tempo está sendo gasto: se está varrendo a tabela inteira linha por linha (sinal de índice faltando) ou usando um índice de forma eficiente. Não precisa virar rotina de especialista em banco de dados para usar esse comando algumas vezes por mês nas consultas que o time já sabe, por instinto, que estão pesadas. É um hábito pequeno que evita boa parte da surpresa de performance mais adiante.
Backup e o dia em que você vai precisar dele
Backup é o tipo de item que todo mundo concorda ser importante e quase ninguém testa de verdade até o dia em que precisa. E o detalhe que separa um backup útil de um backup decorativo é justamente esse: não basta o backup existir, é preciso já ter testado o processo de restauração pelo menos uma vez, num ambiente separado, para confirmar que ele realmente devolve os dados num estado utilizável.
Configure backup automático diário como padrão não negociável, com retenção de pelo menos alguns dias ou semanas, dependendo da criticidade do produto. Depois, agende um teste de restauração periódico, trimestral é um bom ponto de partida, para um ambiente isolado, e confirme que os dados voltam íntegros e que o processo inteiro (não só o download do arquivo de backup) funciona sem surpresa. Times que pulam esse teste costumam descobrir, exatamente no incidente que mais precisavam do backup, que ele estava corrompido, incompleto ou apontando para a configuração errada.
Conclusão
Banco de dados bem cuidado em projetos de Vibe Coding não é sobre usar a tecnologia mais sofisticada disponível, é sobre disciplina básica aplicada de forma consistente: modelar pensando em entidades, seguir convenções simples no Postgres ou Supabase, versionar cada migração, ativar RLS com policies testadas, indexar o que a consulta realmente usa e testar o backup antes de precisar dele de verdade. Nenhum desses pontos é caro de fazer cedo. Todos eles ficam caros quando adiados até depois que o produto já tem dados reais de clientes reais.
Se o seu projeto já tem schema de banco em produção e você quer uma auditoria séria antes de escalar, converse com a MVP Plus sobre o Vibe Squad.
Foto: Panumas Nikhomkhai