Destino Dev

Blog

Migrando um projeto Node + Prisma de SQLite para PostgreSQL: guia passo a passo para iniciantes

Por John Pires · 08 de março de 2026

Migrando um projeto Node + Prisma de SQLite para PostgreSQL: guia passo a passo

O que é e por que importa

SQLite é um banco de dados leve que armazena tudo em um único arquivo no disco. É excelente para protótipos, testes locais e aplicações com baixo volume de dados. PostgreSQL é um sistema gerenciador de banco de dados relacional mais robusto, com suporte a concorrência, índices complexos, tipos avançados e operações em escala.

A migração importa porque, conforme seu projeto cresce, limitações do SQLite aparecem: concorrência limitada, suporte insuficiente a tipos e extensões, e diferenças no comportamento de transações. Mudar para PostgreSQL permite escalar com segurança, melhorar performance e usar recursos avançados como views materializadas, GIN indexes e replicação.

Este guia foca em projetos Node.js que usam Prisma como ORM. A proposta é orientar um iniciante com analogias simples, passos práticos e exemplos comentados para evitar surpresas.

Ao final você terá: um schema Prisma adaptado para Postgres, um processo de migração dos dados (quando aplicável), scripts de seed e um conjunto de dicas para produção.

Conceitos fundamentais com analogias

Banco de dados como uma cozinha

Pense no banco de dados como uma cozinha. SQLite é uma bancada com uma única panela: rápida para preparar uma receita simples, mas limitada se várias pessoas tentarem cozinhar ao mesmo tempo. PostgreSQL é uma cozinha completa com fogões, fornos e prateleiras, onde múltiplas receitas podem ser preparadas em paralelo com ferramentas especializadas.

Prisma como um mapa da despensa

Prisma é como um inventário bem organizado da despensa: ele descreve o que você tem (modelos), gera comandos para acessar esses itens (client) e mantém versões do inventário (migrations). Migrar de SQLite para PostgreSQL significa atualizar esse inventário para refletir que agora você tem ferramentas diferentes e talvez mais itens disponíveis.

Tipos e comportamento: nem tudo casa automaticamente

Nem todos os tipos ou comportamentos mapeiam 1:1. SQLite é permissivo com tipos e aloca espaço diferentemente. PostgreSQL é estrito e possui tipos nativos avançados como timestamptz, jsonb e arrays. Ajustar o schema é parte essencial da migração.

Tip: sempre manter backups do arquivo .sqlite antes de qualquer tentativa de conversão.

Passo a passo com código comentado

Esta seção descreve os passos práticos, com comandos e trechos de código. Cada bloco tem contexto antes e explicação depois.

1. Preparar o ambiente

Instale as dependências necessárias no projeto Node. Você precisará do driver PostgreSQL e do Prisma.

Contexto: aqui instalamos pacotes e inicializamos o Prisma se ainda não tiver.

npm install prisma @prisma/client pg --save-dev
npx prisma init

O comando acima instala o driver pg (necessário para Postgres), Prisma CLI e inicializa a pasta prisma com schema.prisma e um arquivo .env. Após esse passo você terá um arquivo prisma/schema.prisma que começa configurado para SQLite se o projeto foi iniciado assim.

2. Atualizar DATABASE_URL

Contexto: você precisa apontar Prisma para o banco Postgres. No arquivo .env, atualize a variável DATABASE_URL.

# arquivo .env
# exemplo de URL local sem SSL
DATABASE_URL='postgresql://usuario:senha@localhost:5432/nome_db?schema=public'

Depois de alterar, Prisma usará o Postgres para criar as migrations e o client. No ambiente de produção, use variáveis de ambiente seguras e, se necessário, habilite SSL com ?sslmode=require ou configuração equivalente.

3. Adaptar schema.prisma

Contexto: migrar de provider 'sqlite' para 'postgresql' e ajustar tipos. A mudança do provider é simples, mas tipos e constraints precisam de revisão.

// exemplo de prisma/schema.prisma adaptado para postgresql
generator client {
  provider = 'prisma-client-js'
}

datasource db {
  provider = 'postgresql'
  url      = env('DATABASE_URL')
}

model User {
  id        Int      @id @default(autoincrement())
  email     String   @unique
  name      String?
  createdAt DateTime @default(now())
}

Após essa alteração você estará pronto para gerar migrations específicas para Postgres. Observe o uso de autoincrement para IDs numéricos; em Postgres ele mapeia para sequences. Se você usou campos do tipo Integer no SQLite com comportamento permissivo, revise se deve usar String/UUID em Postgres.

4. Gerar e aplicar migrations

Contexto: criar as tabelas no Postgres usando as migrations do Prisma. Em desenvolvimento use migrate dev; em produção use migrate deploy em CI/CD.

npx prisma migrate dev --name init_postgres

Esse comando vai gerar arquivos SQL dentro de prisma/migrations e aplicar ao banco Postgres apontado em DATABASE_URL. Se você já tem dados no SQLite e quer migrá-los, existem duas abordagens: exportar/importar via CSV/SQL ou usar ferramentas externas. Abaixo explico uma forma prática.

5. Migrando dados do arquivo SQLite

Contexto: não existe um comando Prisma que converta o arquivo SQLite diretamente para Postgres. Você exportará dados e reimportará ou usará uma ferramenta de migração. Aqui apresento um método simples: exportar tabelas para CSV e importar para Postgres com psql.

Passos resumidos:

  1. Usar sqlite3 para exportar cada tabela em CSV.
  2. Criar as tabelas em Postgres via prisma migrate.
  3. Usar psql COPY para importar cada CSV nas tabelas correspondentes.
# exportar tabela users do arquivo sqlite
sqlite3 database.sqlite ".mode csv" ".headers on" "select * from User;" > users.csv

# importar no postgres (executar no shell com psql conectado)
psql -d nome_db -c "\copy \"User\"(id,email,name,createdAt) FROM 'users.csv' CSV HEADER"

Depois de importar, verifique constraints e sequences. No Postgres, se você importar IDs manualmente, ajuste o sequence para continuar incrementando corretamente:

-- ajustar sequence do user id
SELECT setval(pg_get_serial_sequence('"User"', 'id'), COALESCE(MAX(id), 1)) FROM "User";

Esse comando sincroniza a sequence do serial com o maior ID presente para evitar conflitos em novas inserções.

Erros comuns e armadilhas

Contexto: lista prática de problemas que iniciantes geralmente enfrentam ao migrar.

  • Tipos incompatíveis: SQLite aceita praticamente qualquer valor em qualquer coluna. Postgres é estrito; strings em campos numéricos falharão na importação.
  • Sequências e autoincrement: depois de importar IDs manualmente, lembre-se de ajustar sequences com setval.
  • Case sensitivity: nomes de tabela com maiúsculas podem precisar de aspas no Postgres (ex: "User"). Prefira nomes em snake_case para evitar isso.
  • Transações longas: não execute migrações em produção sem testes; uma migração mal planejada pode travar tabelas.
  • Conexões e pool: ajustar o pool do Prisma (connection_limit) em produção para não estourar limites do Postgres.
Dica: teste todo o processo em um clone do banco de produção antes de aplicar em produção. Simular o volume ajuda a encontrar problemas de performance e tipos.

Exemplo prático completo

Nesta seção montaremos um mini-projeto Node que usa Prisma para inserir e consultar usuários em PostgreSQL. Foco na praticidade: código real para executar localmente.

Estrutura do projeto

Estrutura recomendada:

  • package.json
  • prisma/schema.prisma
  • src/index.js
  • .env

Instale dependências e inicialize o prisma conforme mostrado antes. Abaixo um exemplo de index.js que cria e consulta usuários usando Prisma Client.

// src/index.js - exemplo funcional com Prisma Client e Postgres
const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();

async function main() {
  // cria um usuário
  const user = await prisma.user.create({
    data: {
      email: 'maria@example.com',
      name: 'Maria'
    }
  });
  console.log('Usuário criado:', user);

  // consulta todos os usuários
  const users = await prisma.user.findMany({
    orderBy: { createdAt: 'desc' }
  });
  console.log('Lista de usuários:', users);
}

main()
  .catch(e => {
    console.error(e);
    process.exit(1);
  })
  .finally(async () => {
    await prisma.$disconnect();
  });

Após configurar .env com DATABASE_URL correto e executar npx prisma migrate dev, rode node src/index.js. O script criará um usuário e listará todos.

Script de seed com dados reais

Contexto: exemplo de seed que popula o banco com alguns registros para desenvolvimento.

// prisma/seed.js - popula dados iniciais
const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();

async function seed() {
  await prisma.user.createMany({
    data: [
      { email: 'ana@example.com', name: 'Ana' },
      { email: 'joao@example.com', name: 'João' }
    ],
    skipDuplicates: true
  });
  console.log('Seed concluído');
}

seed()
  .catch(e => console.error(e))
  .finally(() => prisma.$disconnect());

Rode node prisma/seed.js após aplicar migrations. Em projetos com prisma > 4 é comum usar o comando npx prisma db seed que chama o script configurado no package.json.

Próximos passos para aprofundar

Depois que sua aplicação estiver funcionando com PostgreSQL, explore os pontos abaixo para ganhar maturidade:

  • Indexes: crie índices em colunas usadas em filtros e ordenações e avalie com EXPLAIN.
  • Tipos avançados: use jsonb para dados semi-estruturados e arrays para coleções simples.
  • Monitoramento: configure métricas de conexão, latência e uso de queries lentas.
  • Backups e restore: automatize backups e testes de restore antes de confiar neles.

Otimizando queries e índices

Contexto: as queries que funcionavam no SQLite podem ser lentas no Postgres sem índices. Use EXPLAIN ANALYZE para entender o plano de execução e adicionar índices apropriados.

Exemplo rápido de criação de índice:

-- criar índice para busca por email
CREATE INDEX idx_user_email ON "User" (email);

Índices aceleram leitura, mas afetam escrita. Equilibre conforme seu perfil de carga.

Segurança e produção

Contexto: checklist mínimo para colocar Postgres em produção com Prisma.

  1. Use variáveis de ambiente seguras e segmente credenciais por ambiente.
  2. Habilite SSL e verifique configurações de trust quando aplicável.
  3. Configure pool do Prisma via datasource url ou variável PRISMA_CLIENT_ENGINE_TYPE conforme necessidade.
  4. Implemente backups automáticos e testes de restauração periódicos.

Para aplicações serverless, avalie adaptadores de pool (ex: PgBouncer) para reduzir problemas de excesso de conexões.

Conclusão prática

Concluir a migração de SQLite para PostgreSQL exige três coisas: ajustar o schema, migrar os dados e testar exaustivamente. O Prisma facilita o trabalho gerando migrations e oferecendo um client consistente, mas requer atenção a tipos, sequences e importação de dados.

Sugestão prática imediata: clone seu projeto, aponte .env para uma instância Postgres local, gere a migration e execute os scripts de importação em um ambiente de teste. Valide todas as rotas e queries antes de alterar a produção.

Resumo das etapas essenciais: instalar pg, alterar provider em schema.prisma, ajustar tipos, gerar migrations, exportar/importar dados e ajustar sequences. Cada etapa pode revelar problemas específicos, então faça backups e testes. Boa migração.

Recapitulação rápida em checklist:

  • Backup do arquivo SQLite
  • Instalação do driver pg e inicialização do Prisma
  • Alterar DATABASE_URL para Postgres
  • Atualizar schema.prisma e rodar npx prisma migrate
  • Exportar/importar dados e ajustar sequences
  • Testar a aplicação e ajustar índices / configurações de pool

Se quiser, posso fornecer um script automatizado para exportar todas as tabelas do SQLite e importar para Postgres, ou ajudar a adaptar schema.prisma de um projeto específico. Basta enviar o schema atual e a estrutura das tabelas.

Assuntos: Prisma, PostgreSQL, sqlite, migracao, Node.js, Banco de Dados

Leia também