Seeds: Como Fazer o Banco de Dados Nascer Vivo
Índice do Manual
Você acabou de rodar supabase db reset. O banco local renasce limpo, todas as tabelas criadas pelas suas Migrations estão lá — mas vazias. Para testar qualquer tela do sistema, você precisa abrir o painel, cadastrar categorias, criar um plano, inventar um usuário admin... tudo na mão. Toda vez.
O Seed resolve esse problema de uma vez por todas. Ele é um arquivo SQL que o Supabase CLI executa automaticamente após todas as Migrations, populando o banco com dados iniciais prontos para uso.
Como o Seed Funciona na Prática
O arquivo vive em um caminho fixo dentro do seu projeto:
supabase/seed.sql
A cadeia de execução é automática e previsível:
supabase db reset
Quando você roda esse comando, o Supabase CLI executa três passos em sequência:
- Destrói o banco local atual.
- Recria todas as tabelas rodando suas Migrations na ordem cronológica.
- Popula o banco executando o
seed.sqlno final.
Ou seja: toda vez que o banco é recriado, ele já nasce com vida. Zero trabalho manual.
O Que Colocar no Seed (e o Que NÃO Colocar)
O Seed é uma ferramenta de produtividade do desenvolvedor, não um dump de produção. Trate-o como o "kit de sobrevivência" do seu ambiente local.
Colocar:
- Dados estruturais obrigatórios: categorias, tipos de plano, roles de acesso, listas fixas (estados, países).
- Um usuário admin de teste com credenciais conhecidas (ex:
admin@teste.com/123456). - Dados falsos suficientes para testar as telas principais — de 3 a 5 registros por tabela bastam.
NÃO colocar:
- Dados de produção reais (CPFs, e-mails de clientes verdadeiros, tokens de API).
- Milhares de linhas. O seed deve ser rápido, não um dump de 500MB.
- Lógica condicional complexa. Mantenha SQL puro e simples.
[!TIP] E os geradores automáticos (Faker.js / Snaplet)? Para sistemas iniciais, um
seed.sqlescrito na mão (focado no essencial) dá menos trabalho de manutenção. Mas quando a empresa cresce e o time precisa de um banco local abarrotado com milhões de registros aleatórios realistas (CPFs, nomes) para testar performance de paginação, a geração procedural através de bibliotecas como Faker.js ou ferramentas como o Snaplet (parceiro oficial do Supabase) torna-se obrigatória para construir seus seeds.
Exemplo Prático
-- =============================================
-- SEED: Dados iniciais para desenvolvimento
-- =============================================
-- Camada 1: Tabelas Raiz (sem dependências)
-- -------------------------------------------
INSERT INTO public.plans (id, name, price, features)
VALUES
('free', 'Free', 0, '{"limits": "basic"}'),
('pro', 'Pro', 4990, '{"limits": "advanced"}'),
('enterprise', 'Enterprise', 19990, '{"limits": "unlimited"}')
ON CONFLICT (id) DO NOTHING;
INSERT INTO public.categories (slug, label)
VALUES
('tecnologia', 'Tecnologia'),
('financeiro', 'Financeiro'),
('saude', 'Saúde'),
('educacao', 'Educação')
ON CONFLICT (slug) DO NOTHING;
-- Camada 2: Tabelas que dependem da Camada 1
-- -------------------------------------------
INSERT INTO public.organizations (id, name, plan_id)
VALUES
('org-teste', 'Empresa de Teste', 'pro')
ON CONFLICT (id) DO NOTHING;
-- Camada 3: Dados de teste para o dia a dia
-- -------------------------------------------
INSERT INTO public.projects (
id, title, category_slug, organization_id
)
VALUES
('proj-1', 'Projeto Alpha', 'tecnologia', 'org-teste'),
('proj-2', 'Projeto Beta', 'financeiro', 'org-teste'),
('proj-3', 'Projeto Gamma', 'saude', 'org-teste')
ON CONFLICT (id) DO NOTHING;
O segredo desse arquivo está na cláusula ON CONFLICT DO NOTHING. Ela torna o seed idempotente: você pode executá-lo uma, duas ou cem vezes sem nunca gerar erro de duplicação. Se o registro já existe, o Postgres simplesmente ignora a linha.
O Cuidado com Foreign Keys: Ordem de Inserção
Seeds devem respeitar a hierarquia de dependências do seu banco. Se a tabela organizations possui uma Foreign Key apontando para plans, você precisa inserir os planos antes das organizações.
A boa prática é organizar o seu seed.sql em camadas numeradas:
- Camada 1: Tabelas raiz (sem FK para nenhuma outra tabela).
- Camada 2: Tabelas que dependem da Camada 1.
- Camada 3: Tabelas que dependem da Camada 2.
Se você inverter a ordem, o Postgres vai rejeitar o INSERT com um erro de violação de Foreign Key e o db reset vai falhar.
A Trava de Segurança: Nunca Rodar Seed em Produção
O comando supabase db reset é uma operação destrutiva que apaga todo o banco antes de recriá-lo. Por isso, o Supabase CLI já bloqueia esse comando quando o projeto está linkado a um banco remoto de produção.
Mesmo assim, reforce essa regra na sua equipe: o Seed é uma ferramenta exclusivamente local e de staging.
Se você precisa de dados que devem existir obrigatoriamente em produção (como uma lista fixa de estados brasileiros ou os planos iniciais do SaaS), o caminho correto é criar uma Migration dedicada com esses INSERTs — não o seed.
Seed vs Migration de Dados: Quando Usar Cada Um
| Cenário | Ferramenta | Por quê? |
|---|---|---|
| Dados de teste para o dev local | Seed | Dados descartáveis, morrem no db reset |
| Dados obrigatórios em produção (ex: lista de estados) | Migration | Precisam existir em todos os ambientes |
| Popular uma tabela logo após criá-la | Migration | Rode o INSERT na mesma Migration do CREATE |
| Dados falsos para demonstrar ao cliente em staging | Seed | Ambiente de homologação é descartável |
| Usuário admin padrão para login local | Seed | Credenciais de teste não vão para produção |
A partir de agora, toda vez que o seu banco local for destruído e recriado, ele já nasce equipado com planos, categorias, organizações e projetos de teste. Seu time de desenvolvimento nunca mais vai perder tempo cadastrando dados na mão para poder trabalhar.
Com o banco estruturado (Migrations) e populado (Seeds), está na hora de dar inteligência e lógica serverless a ele. Siga para o próximo manual: Supabase Edge Functions: Criação, Testes e Deploy.