UpuaiUpuai

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.

Equipe Upuai· Upuai CloudAtualizado em 12 min de leitura

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 assumeContinua com você
Provisionar a instância, gerar credenciais e injetar a string de conexãoModelagem, 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çãoDecidir o que guardar (e por quanto tempo)
Rede interna privada entre serviços do mesmo ambienteQuem enxerga o banco (o endpoint público é opcional)
Atualizar versão, redimensionar CPU, memória e disco sem recriarEscolher 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

  1. 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).
  2. A CLI instalada. No macOS e Linux, brew tap saiph-ti/upuai-cli && brew install upuai; no Windows, via Scoop. Confira com upuai version e upuai whoami.
  3. 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 initdb novo é 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 runtime manté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:

PlanoPreço/mêsRetenção de backupArmazenamento padrão do banco
Teste (15 dias)grátis, sem cartãosem backup automático1 GB
StarterR$ 191 dia3 GB
PlusR$ 492 dias6 GB
ProR$ 993 dias10 GB
BusinessR$ 1997 dias10 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 planos

Artigos relacionados