PostgreSQL gerenciado no Brasil: seu banco no ar em um comando
Guia prático de PostgreSQL gerenciado no Brasil: banco no ar em um comando, conexão privada com a aplicação, migrations no deploy, backup e restore, com fatura em Real e 15 dias de teste sem cartão.
Subir a aplicação virou a parte fácil. O banco é onde o projeto costuma travar: ou ele vive num Postgres instalado na mão dentro de um VPS, sem backup e com a porta 5432 aberta pra internet, ou num serviço gringo que cobra em dólar e roda a milhares de quilômetros do seu app. PostgreSQL gerenciado no Brasil resolve os dois lados de uma vez: o banco nasce provisionado, com conexão privada e retenção de backup, no mesmo datacenter onde o seu serviço já roda.
Este guia percorre o caminho inteiro na prática: provisionar o banco com um comando, conectar a aplicação sem expor nada na internet, rodar as migrations no deploy, abrir um psql quando precisar investigar, fazer backup e restore, e crescer sem recriar o banco. Todos os comandos, limites e retenções citados aqui são os reais da plataforma hoje, e os 15 dias de teste não pedem cartão.
O que “gerenciado” resolve (e o que continua sendo seu)
Banco gerenciado não é mágica, é divisão de trabalho. Vale saber exatamente onde fica a fronteira antes de escolher.
| A plataforma assume | Continua com você |
|---|---|
| Provisionar a instância, gerar credenciais e injetar a string de conexão | Modelagem, schema e migrations |
| Rodar o Postgres num Kubernetes gerenciado, com memória reservada | Índices, queries e plano de execução |
| Backup automático com retenção por plano e restauração | Decidir o que guardar (e por quanto tempo) |
| Rede interna privada entre serviços do mesmo ambiente | Quem enxerga o banco (o endpoint público é opcional) |
| Atualizar versão, redimensionar CPU, memória e disco sem recriar | Escolher a hora de crescer |
Ou seja: some o trabalho de infraestrutura repetitivo (instalar, configurar, escrever cron de pg_dump, renovar certificado, abrir porta com medo), e continua com você a parte que é do seu produto. Se a sua dor hoje é “não sou DBA e não quero ser”, é exatamente esse pedaço que sai da sua mesa.
Antes de começar
- Uma conta no Upuai. Os 15 dias de teste não pedem cartão. Crie em app.upuai.com.br (GitHub OAuth ou código por e-mail).
- A CLI instalada. No macOS e Linux,
brew tap saiph-ti/upuai-cli && brew install upuai; no Windows, via Scoop. Confira comupuai versioneupuai whoami. - Um projeto criado e linkado. Se você ainda não tem app no ar, o guia de deploy de Next.js cobre esse passo em detalhe. Para um projeto já existente:
upuai link <project-id> --service <nome> --env production.
O banco no ar em um comando
Com o projeto linkado, é uma linha:
upuai add --type database --engine postgres
O que acontece por trás: a plataforma provisiona uma instância gerenciada de PostgreSQL no ambiente atual, cria o banco e o usuário da aplicação e injeta a string de conexão como variável de ambiente (DATABASE_URL). Você não escreve Dockerfile, não sobe docker-compose, não gera senha na mão nem cola credencial em lugar nenhum.
O mesmo comando serve para os outros motores gerenciados, trocando o --engine:
upuai add --type database --engine mysql
upuai add --type database --engine redis # injeta REDIS_URL
upuai add --type database --engine mongo
Duas coisas que costumam gerar dúvida:
- Versão. O catálogo do PostgreSQL cobre as versões 15, 16, 17 e 18, e o padrão de uma instância nova é a 18. Na criação, qualquer versão listada é selecionável (um
initdbnovo é sempre seguro); mudar a versão de uma instância que já roda segue regras diferentes, que estão na seção de crescimento mais abaixo. - Quantos serviços isso consome. No período de teste, o projeto tem 2 serviços, então “app + banco” cabe exatamente. No Starter são 3, no Plus são 4, no Pro são 5. É a conta que a maioria dos side-projects precisa fazer antes de escolher plano.
Conectar a aplicação sem expor o banco
A conexão entre o seu serviço e o banco acontece pela rede interna do ambiente: o endereço tem a forma <id>.internal:5432 e não passa pela internet pública. Não há porta aberta pro mundo por padrão, e isso é o comportamento que você quer.
Na prática, a variável já vem injetada. Para conferir e para distribuir a variável entre os serviços que precisam dela:
upuai vars list -o json # o que o serviço linkado enxerga
upuai vars shared list -s api # variáveis compartilhadas do projeto
upuai vars shared enable DATABASE_URL -s worker # injeta o banco também no worker
As variáveis compartilhadas são opt-in por serviço: o banco não vaza pra todo mundo só por existir no projeto. Você escolhe quem recebe o quê, o que evita o clássico “o serviço de landing page tinha a credencial do banco de produção”.
Dois detalhes que economizam tempo:
- Variável nova vale no próximo deploy. Se você quer efeito imediato,
upuai redeploy --yes. - Segredo não precisa ir para o build. Para variáveis que você mesmo define,
upuai variables set MINHA_SECRET=xxx --scope runtimemantém o valor fora da imagem, disponível só no container em execução. É o caminho certo para segredo, e evita que ele fique assado numa layer.
Migrations no deploy: a release phase
Rodar migration na mão, por SSH, depois do deploy, é a fonte mais comum de “funcionou em staging e quebrou em produção”. O jeito certo é declarar a migration como release phase, no upuai.toml na raiz do repositório:
#:schema https://upuai.com.br/schemas/upuai-toml-v1.json
[build]
builder = "railpack"
[deploy]
startCommand = "node dist/server.js"
releaseCommand = "npx prisma migrate deploy"
releaseTimeoutSeconds = 300
healthCheckPath = "/health"
A releaseCommand roda antes do rollout, com as variáveis do serviço injetadas (inclusive o DATABASE_URL). Se a migration falhar, o deploy falha ali e a versão antiga continua servindo, em vez de subir código novo contra um schema velho. O log da fase é upuai logs --deploy.
Para um comando pontual, sem alterar o upuai.toml, dá pra rodar localmente com as variáveis do serviço injetadas:
upuai run npx prisma migrate deploy
O mesmo raciocínio vale para Django (python manage.py migrate), Rails (bin/rails db:migrate) e qualquer ferramenta de migration que você já use.
Abrir um psql quando precisar investigar
Nem tudo se resolve pelo painel. Para acesso direto ao banco, a CLI embrulha o psql e busca as credenciais por você:
upuai db connect --print # imprime a string de conexão (script-friendly)
upuai db connect --output json # mesma coisa, em JSON
upuai db connect --enable # liga o endpoint público, se estiver desligado
upuai db connect # abre a sessão psql interativa
O endpoint público é opt-in por serviço: quando ligado, o banco ganha um hostname próprio no formato <slug>.db.upuai.cloud, na porta 5432, com TLS e sslmode=require. Ele existe para o seu cliente gráfico favorito, para uma carga pontual ou para um script de manutenção, não para ser o caminho da aplicação (esse é a rede privada).
Se preferir não abrir nada pra fora, dá para entrar por dentro do container e mandar a query pelo pipe:
echo "SELECT count(*) FROM users;" | upuai ssh -s db -- psql
Backup, restore e a retenção do seu plano
Aqui vale a honestidade que a gente gosta de praticar: backup automático não existe no período de teste. A retenção acompanha o plano, e é assim:
| Plano | Preço/mês | Retenção de backup | Armazenamento padrão do banco |
|---|---|---|---|
| Teste (15 dias) | grátis, sem cartão | sem backup automático | 1 GB |
| Starter | R$ 19 | 1 dia | 3 GB |
| Plus | R$ 49 | 2 dias | 6 GB |
| Pro | R$ 99 | 3 dias | 10 GB |
| Business | R$ 199 | 7 dias | 10 GB |
Se você trocar de plano, a retenção se ajusta na hora, sem precisar recriar o banco. Os planos anuais saem por 10 vezes o mensal, o que dá dois meses grátis.
Independente do plano, o backup manual está a um comando de distância, e é ele que também resolve a migração do seu banco atual para cá:
upuai db backup --out backup-2026-07-25.dump # pg_dump gerenciado
upuai db restore -f backup-2026-07-25.dump --yes # pg_restore gerenciado
Recomendação prática: use os 15 dias de teste para desenvolver e validar, e assuma um plano pago no momento em que existir dado de usuário real, que costuma chegar antes de o teste acabar. Um banco de produção sem retenção automática é risco que não compensa economizar.
Crescer sem recriar o banco
O que mais dói em banco auto-hospedado é a hora de crescer: parar tudo, redimensionar disco, torcer. Aqui o caminho é ao vivo:
- CPU e memória de um Postgres mudam sem recriar a instância. A mudança aplica com um restart breve, sem perda de dados.
- Armazenamento e versão também são configuráveis com o banco no ar, e desde julho isso vale igual para MySQL, Redis e MongoDB.
- Bancos rodam com memória reservada (classe Guaranteed no Kubernetes), o que os protege de despejo quando o nó fica sob pressão.
- Pico de escrita não derruba o banco. O arquivamento interno roda em paralelo e os limites físicos têm folga sobre o plano, justamente para picos temporários não travarem a instância.
- Estouro de armazenamento é escalonado, não fatal: primeiro aviso, depois um período de carência e, no limite, o banco entra em modo somente leitura em vez de simplesmente cair. Você tem tempo de agir.
Vale um detalhe sobre alta disponibilidade, porque prometer o contrário seria desonesto: o Redis roda como instância única em todos os planos, com persistência em disco (AOF) e backup diário do volume — é o mesmo padrão de Railway, Render e Fly. Não há failover automático; se você precisa dele, fale com a gente antes de colocar uma fila crítica em produção.
O que muda quando o banco também está no Brasil
Esse é o ponto que não aparece em tutorial gringo. Três efeitos concretos:
1. Aplicação e banco no mesmo lugar. O tráfego entre o seu app e o Postgres não atravessa o Atlântico. Numa requisição que faz cinco queries, cada ida e volta conta, e uma aplicação hospedada no Brasil com banco nos Estados Unidos paga esse pedágio em toda requisição. O raciocínio completo está no post sobre latência e percepção do produto.
2. Os dados ficam no país. Para vender B2B no Brasil, “onde mora o banco” é pergunta de contrato e de due diligence, não preferência técnica. Detalhamos o que muda em LGPD na sua PaaS.
3. A fatura é em Real. Sem cartão internacional, sem variação cambial e sem os 3,5% de IOF que hoje incidem sobre compra internacional no cartão de crédito (Agência Brasil).
E como fica a comparação com as plataformas gringas de sempre? Sendo justo com elas: o Render, por exemplo, é uma plataforma madura, com anos de estrada e presença em três continentes. Se o seu público está nos Estados Unidos, na Europa ou na Ásia, elas resolvem bem. Só que, conferindo a documentação oficial deles nesta semana, duas coisas importam para quem atende o Brasil: as regiões disponíveis são Oregon, Ohio, Virgínia, Frankfurt e Singapura, nenhuma na América do Sul, e o Postgres do plano gratuito expira 30 dias depois de criado, com 14 dias de carência para virar plano pago antes de ser apagado com os dados (docs do Render). Aqui a regra é parecida, e a gente prefere dizer com clareza: o teste dura 15 dias, e sem um plano pago os serviços são pausados, os dados ficam guardados por mais 15 dias e depois são apagados. A diferença que fica é a região e a moeda: o banco no Brasil, a partir do Starter a R$ 19/mês, em Real. Se você está comparando alternativas em Real, também escrevemos sobre alternativa ao Railway no Brasil.
FAQ
Posso usar um banco externo em vez do gerenciado?
Pode. Basta apontar a DATABASE_URL para onde você quiser (Neon, Supabase, RDS, seu VPS). Você perde a rede privada e ganha a latência do caminho até lá, então avalie: para banco fora do país, cada query paga a viagem de ida e volta.
O banco do período de teste serve para produção?
Para produção com dado de usuário, não: são 1 GB, sem backup automático, e ao fim dos 15 dias o serviço pausa sem plano pago. Ele serve muito bem para desenvolver e testar. A partir do Starter (R$ 19) você já tem retenção diária e o banco fica no ar.
Como migro meu banco atual para cá?
pg_dump na origem (ou upuai db backup se ela também estiver aqui) e upuai db restore -f <arquivo> --yes no destino. Como é PostgreSQL padrão, sem fork nem formato proprietário, o dump é o mesmo de sempre.
Preciso escrever Dockerfile ou YAML para o banco?
Não. O banco é um serviço gerenciado da plataforma, criado pelo comando upuai add --type database. Para a aplicação, o railpack detecta a stack e builda o container sozinho, o mesmo caminho descrito no guia de hospedar bot 24/7.
E se um dia eu quiser sair?
É PostgreSQL padrão. Você tira um dump com um comando e leva o banco para onde quiser. Lock-in de dado é justamente o que a gente não quer construir.
Do zero ao banco em produção
O resumo do caminho: upuai add --type database --engine postgres provisiona o banco e injeta a conexão, a rede privada liga o app ao Postgres sem expor nada, a release phase roda a migration antes do rollout, upuai db connect --print te dá o acesso quando precisar investigar, e o backup segue a retenção do seu plano. Tudo no Brasil, com a fatura em Real.
Comece seus 15 dias grátis, sem cartão →
Referências úteis: a documentação da CLI traz a lista completa de comandos de banco, e a referência do upuai.toml o esquema de build, release e deploy.
Faça deploy no Brasil em 5 minutos
PaaS brasileira, preços em Real, infraestrutura LGPD-native.
Ver planosArtigos relacionados

Migrar do Railway para a Upuai: do railway.json ao upuai.toml
Guia para levar um app do Railway para a Upuai: o que cada chave do railway.json vira no upuai.toml, variáveis, banco Postgres, domínio e a conta em reais.
Deploy de API Node no Brasil: o POST que some em produção
A API Node responde no notebook. Em produção o GET passa e o primeiro POST some. Guia de deploy de API Node no Brasil: env, bind, CORS, proxy, healthcheck e body parser.
Bot de WhatsApp na Cloud API: quando sair da biblioteca não oficial
A conta da API oficial do WhatsApp muda em 1º de outubro de 2026: mensagem de serviço e utilidade dentro da janela de 24h passam a ser cobradas. Quando migrar e o que muda no deploy.