TL;DR
Supabase CLI executa uma pilha Supabase completa na sua máquina usando Docker: PostgreSQL, Auth, Storage e Edge Functions. Instale com brew install supabase/tap/supabase, execute supabase init e supabase start para iniciar o ambiente local, depois use supabase db push e supabase functions deploy para enviar para produção. É a rota mais rápida para construir e testar backends Supabase localmente sem depender da nuvem.
Introdução
73% dos bugs de backend são encontrados em produção porque os devs pulam testes locais. Com Supabase CLI, isso não é mais desculpa. Você roda um ambiente espelhando a produção na sua máquina em menos de 5 minutos.
Aqui está o problema real: muitos devs testam direto em produção (arriscado) ou gastam horas montando ambientes locais que nunca batem 100% com a nuvem (frustrante). O Supabase CLI resolve ambos: oferece uma stack local via Docker idêntica à produção. O que funcionar local, vai funcionar na produção.
💡 Se você constrói APIs sobre Supabase, precisa de uma ferramenta para projetar, testar e documentar seus endpoints enquanto desenvolve. O Apidog conecta direto nas APIs REST e GraphQL do Supabase, permitindo testar o backend enquanto constrói localmente.
Teste suas APIs Supabase com Apidog - grátis
Ao final deste guia, você será capaz de:
- Subir um ambiente Supabase local completo em minutos
- Gerenciar alterações de schema com migrações versionadas
- Construir e testar Edge Functions localmente antes do deploy
- Fazer deploy para produção com um comando
Por que desenvolvimento Supabase local falha sem o CLI
Se já tentou criar um app Supabase sem o CLI, conhece a dor. Três cenários típicos:
Teste direto em produção: Você altera schema no painel do Supabase, funciona, envia o frontend. Dias depois, um colega puxa o repo e o app quebra — o banco local dele não tem a nova coluna.
Ambiente incompatível: Você sobe um PostgreSQL local, replica o schema na mão, perde horas debugando por que as políticas de RLS parecem diferentes. Não são — você só esqueceu uma política.
"Funciona na minha máquina": Sua Edge Function roda no editor da dashboard, mas falha em produção porque você testou com valores hardcoded, não variáveis reais.
Esses casos são comuns. O "schema drift" (bancos locais e remotos fora de sincronia) é o problema nº 1 em times Supabase. O CLI resolve:
- Migrações deixam mudanças em schema versionadas e reproduzíveis
- Stack Docker local idêntica à produção (mesma versão do Postgres, mesmo RLS)
- Serviço de funções local testa Edge Functions com variáveis reais de ambiente
Como o Supabase CLI funciona
A pilha local
Rodando supabase start, o CLI inicializa um Docker Compose com estes serviços:
| Serviço | Porta | Finalidade |
|---|---|---|
| PostgreSQL | 54322 | Seu banco de dados |
| PostgREST | 54321 | API REST gerada automaticamente |
| GoTrue | 54321/auth | Autenticação |
| Realtime | 54321/realtime | WebSocket subscriptions |
| Storage | 54321/storage | Armazenamento de arquivos |
| Studio | 54323 | Painel visual |
| Inbucket | 54324 | Teste de e-mail (captura todos localmente) |
| Edge Runtime | 54321/functions | Executor de funções (Deno) |
É a mesma stack da Supabase Cloud, rodando local.
Instalação
macOS:
brew install supabase/tap/supabase
Windows (Scoop):
scoop bucket add supabase https://github.com/supabase/scoop-bucket.git
scoop install supabase
Linux / npm:
npm install -g supabase
Verifique a instalação:
supabase --version
# supabase 1.x.x
supabase start
Configuração do projeto
mkdir my-project && cd my-project
supabase init
Isso cria:
supabase/
├── config.toml # Portas, configs de auth/storage
├── seed.sql # Dados de desenvolvimento para resets
└── migrations/ # Histórico de schema versionado
Iniciando a stack local
supabase start
Na primeira vez, baixa ~1GB de imagens Docker. Depois, inicializa em ~10 segundos.
API URL: http://localhost:54321
DB URL: postgresql://postgres:postgres@localhost:54322/postgres
Studio: http://localhost:54323
anon key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Copie a anon key para seu .env.local — será usada no frontend.
Gerenciamento de banco de dados com migrações
Migrações são o core do fluxo do CLI. Cada mudança de schema vira um arquivo SQL versionado e rastreado no Git. Chega de "quem mudou o banco?".
Criando sua primeira migração
supabase migration new create_posts_table
# Cria: supabase/migrations/20260324120000_create_posts_table.sql
Edite o arquivo:
-- Criar tabela de posts com RLS desde o início
CREATE TABLE posts (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE NOT NULL,
title TEXT NOT NULL,
content TEXT,
published BOOLEAN DEFAULT false,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- Habilitar Row Level Security
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;
-- Qualquer pessoa pode ler posts publicados
CREATE POLICY "Anyone can read published posts"
ON posts FOR SELECT
USING (published = true);
-- Usuários gerenciam seus próprios posts
CREATE POLICY "Users manage own posts"
ON posts FOR ALL
USING (auth.uid() = user_id);
-- Atualizar automaticamente 'updated_at' a cada mudança
CREATE OR REPLACE FUNCTION update_updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER posts_updated_at
BEFORE UPDATE ON posts
FOR EACH ROW EXECUTE FUNCTION update_updated_at();
Aplique a migração:
supabase migration up
Gerando tipos TypeScript
Após cada alteração no schema, gere os tipos:
supabase gen types typescript --local > src/types/database.ts
No frontend, tipagem total:
import { Database } from '@/types/database'
type Post = Database['public']['Tables']['posts']['Row']
type NewPost = Database['public']['Tables']['posts']['Insert']
const createPost = async (post: NewPost) => {
const { data, error } = await supabase
.from('posts')
.insert(post)
.select()
.single()
return data
}
Semeando dados de desenvolvimento
Edite supabase/seed.sql:
-- Usuários de teste
INSERT INTO auth.users (id, email) VALUES
('00000000-0000-0000-0000-000000000001', 'alice@example.com'),
('00000000-0000-0000-0000-000000000002', 'bob@example.com');
-- Posts de teste
INSERT INTO posts (user_id, title, content, published) VALUES
('00000000-0000-0000-0000-000000000001', 'Começando com Supabase', 'Aqui está o que eu aprendi...', true),
('00000000-0000-0000-0000-000000000002', 'Rascunho: padrões de design de API', 'Trabalho em andamento...', false);
Para resetar e re-seedar:
supabase db reset
Remove tudo, aplica migrações e carrega seed. Ideal para começar do zero.
Testando APIs Supabase com Apidog
Com Supabase local rodando, você já tem uma API REST em http://localhost:54321. O Supabase gera endpoints para cada tabela via PostgREST. Testar manualmente com curl fica inviável rápido, especialmente para cenários de RLS.
O Apidog conecta direto à instância local. Você pode:
- Salvar requisições como coleções reutilizáveis
- Testar endpoints como diferentes usuários (trocando ambientes)
- Adicionar asserções ("resposta contém pelo menos 1 post") e rodar como pacote de testes
- Compartilhar documentação automática da API com a equipe
Configuração do Apidog com Supabase local:
- Crie um projeto no Apidog
- Defina a URL base:
http://localhost:54321 - Adicione a variável de ambiente:
anon_key = sua-anon-key-local - Configure o header Authorization:
Bearer {{anon_key}}
Testando o endpoint de posts:
GET http://localhost:54321/rest/v1/posts?published=eq.true
Authorization: Bearer {{anon_key}}
apikey: {{anon_key}}
Salve como requisição, adicione asserção (ex: resposta com pelo menos um post), e rode a cada alteração de política de RLS. Pegue erros antes de chegar na produção.
Comece a testar suas APIs Supabase com Apidog
Edge Functions: construa e teste localmente
Edge Functions rodam com Deno na borda, perto dos usuários. Ideais para webhooks, jobs background, endpoints com lógica server-side.
Crie uma função
supabase functions new send-welcome-email
Cria supabase/functions/send-welcome-email/index.ts:
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
serve(async (req) => {
const { user_id } = await req.json()
// Service role ignora RLS - use com cuidado
const supabase = createClient(
Deno.env.get('SUPABASE_URL')!,
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
)
const { data: profile } = await supabase
.from('profiles')
.select('email, full_name')
.eq('id', user_id)
.single()
// Lógica de envio de e-mail
console.log(`Enviando e-mail de boas-vindas para ${profile?.email}`)
return new Response(
JSON.stringify({ success: true }),
{ headers: { 'Content-Type': 'application/json' } }
)
})
Teste local com hot reload
supabase functions serve
O serviço observa alterações e recarrega automaticamente.
Teste via curl:
curl -X POST http://localhost:54321/functions/v1/send-welcome-email \
-H "Authorization: Bearer YOUR_ANON_KEY" \
-H "Content-Type: application/json" \
-d '{"user_id": "00000000-0000-0000-0000-000000000001"}'
Deploy para produção
# Deploy de uma função
supabase functions deploy send-welcome-email
# Deploy de todas as funções
supabase functions deploy
Técnicas avançadas e abordagens comprovadas
Gerenciamento de segredos
Nunca deixe chaves de API no código. Use segredos:
# Setar segredos de produção
supabase secrets set RESEND_API_KEY=re_xxx STRIPE_KEY=sk_live_xxx
# Listar segredos
supabase secrets list
# Remover segredo
supabase secrets unset STRIPE_KEY
Acesse no código:
const resendKey = Deno.env.get('RESEND_API_KEY')
// Nunca: const resendKey = 're_xxx'
Branching de banco de dados
Para grandes mudanças de schema, crie uma branch isolada:
supabase branches create feature-payments
supabase branches switch feature-payments
# Faça mudanças, teste, depois mescle
supabase branches merge feature-payments
Mantém seu banco de dev principal limpo.
Erros comuns a evitar
- Editar banco direto no Studio: sempre use migrações. Edições diretas não são rastreadas.
-
Commitar
.env: usesupabase secrets setpara produção. Adicione.env*ao.gitignore. -
Pular
supabase db resetapós pull: após puxar alterações do time, rode o reset para aplicar novas migrações. - Não gerar tipos após mudancas: gere tipos TypeScript sempre após mexer no schema.
-
Deploy de funções sem testar local: sempre rode
supabase functions serveantes de deploy. - Usar service role key no frontend: service role ignora RLS, use só em funções server-side.
Dicas de desempenho
# Pule serviços não usados para economizar memória
supabase start --exclude-studio --exclude-inbucket
# Veja uso de recursos
docker stats
Alternativas e comparações
| Recurso | Supabase CLI | Firebase CLI | PlanetScale CLI |
|---|---|---|---|
| Banco local | PostgreSQL completo | Apenas emulador | Só na nuvem |
| Migrações | SQL versionado no Git | Sem suporte nativo | Branching |
| Edge Functions | Runtime Deno | Cloud Functions | Não incluído |
| Auth local | GoTrue completo | Emulador | Não incluído |
| Código aberto | Totalmente aberto | Proprietário | Proprietário |
| Geração de tipos | Embutida | Manual | Manual |
O emulador do Firebase é bom para protótipos, mas não fornece Postgres real. O branching do PlanetScale é ótimo para schema changes, mas sempre na nuvem. Supabase CLI brilha para times querendo experiência local 100% open source e PostgreSQL de verdade.
Casos de uso no mundo real
SaaS multi-tenant: Startup de fintech gerencia 47 migrações em dev/staging/prod. Políticas RLS testadas localmente com funções diferentes de usuário antes do deploy. Resultado: zero incidentes de schema em produção em 6 meses.
Processamento de pedidos e-commerce: Time usa Edge Functions para webhooks Stripe. Testam payloads localmente com supabase functions serve e eventos reais do Stripe. Deploy caiu de 2h para 15min.
Backend mobile: Equipe React Native gera tipos TypeScript após cada migração e publica como pacote npm interno. Frontend e backend sempre sincronizados. Dúvidas de "quais campos esse endpoint retorna?" acabaram.
Conclusão
O que fazer agora:
- Subir ambiente Supabase local completo em minutos
- Usar migrações para versionar cada alteração de schema
- Testar Edge Functions com hot reload
- Gerar tipos TypeScript automaticamente do seu schema
- Deploy rápido com
supabase db pushesupabase functions deploy - Testar APIs com Apidog antes de subir para produção
Esse fluxo traz ganhos imediatos. Sua equipe entrega mais rápido, encontra bugs cedo e nunca mais sofre com "schema drift".
Próximos passos:
- Instale:
brew install supabase/tap/supabase - Execute
supabase initno projeto - Crie sua primeira migração
- Configure o Apidog para testar endpoints locais
- Faça deploy para produção com confiança
Teste suas APIs Supabase com Apidog - grátis
FAQ
Preciso do Docker para usar o Supabase CLI? Sim. O Docker Desktop precisa estar rodando antes do supabase start. O CLI usa Docker Compose para rodar toda a stack local. Se o Docker não estiver ativo, você verá erro "Cannot connect to Docker daemon".
Como sincronizo meu banco local com a produção? Use supabase db pull para gerar migração do schema remoto, depois supabase db push para aplicar migrações locais na produção. Rode supabase db reset local após o pull para garantir ambiente idêntico.
Posso usar Supabase CLI sem conta Supabase Cloud? Sim. Use o CLI totalmente local para desenvolvimento. Só precisa de supabase login e supabase link quando for fazer deploy.
Como lidar com conflitos de migração em equipe? Puxe sempre as últimas mudanças do Git e rode supabase db reset antes de criar novas migrações. Nomeie migrações de forma descritiva e comunique mudanças que quebram compatibilidade.
Qual a diferença entre supabase db push e supabase migration up? supabase migration up aplica migrações pendentes no banco local. supabase db push aplica para o projeto remoto (produção). Sempre teste local antes.
Posso usar o Supabase CLI em projeto existente? Sim. Execute supabase link --project-ref SEU_ID_DO_PROJETO para linkar, depois supabase db pull para gerar migrações do schema remoto.
Como testar políticas de RLS localmente? Use o Supabase Studio em http://localhost:54323 para alternar funções de usuário, ou teste via API com JWTs diferentes. O Apidog facilita: crie ambientes com tokens de usuários diferentes e teste as mesmas requisições.
O Supabase CLI é gratuito? Sim. CLI é open source e grátis. Desenvolvimento local não custa nada. Você só paga pela Supabase Cloud na produção.
Top comments (0)