Extensão Database

PostgreSQL gerenciado para o seu app, com backups automáticos e zero configuração para rodar em Rails.

O que a Extensão entrega

Todo app não-estático nasce com um PostgreSQL gerenciado: banco, usuário e credencial dedicados ao app, com backups automáticos. Não é preciso subir um banco à parte nem configurar réplica — a Extensão Database já entrega isso pronto no primeiro deploy.

O primeiro banco (plano base) é cortesia — um por time, não por app. Times com mais de um app pagam o plano de catálogo a partir do segundo banco.

Variáveis de ambiente injetadas

O Jataí injeta duas variáveis automaticamente no app — nenhuma configuração manual é necessária.

DATABASE_URL=postgresql://usuario:senha@host:6432/banco?prepared_statements=false&pgbouncer=true DIRECT_DATABASE_URL=postgresql://usuario:senha@host:5432/banco

DATABASE_URL é a conexão do app e passa por um pooler de conexões (por isso a porta 6432). No modo transaction do pooler, prepared statements não funcionam, e a URL carrega o parâmetro que desliga esse recurso em cada ORM: prepared_statements=false é lido pelo Active Record e pgbouncer=true pelo Prisma. Cada um ignora o parâmetro do outro. Em Rails e em Prisma, portanto, é zero-config. Outros drivers (node-postgres, Drizzle, psql) só precisam consumir DATABASE_URL diretamente.

DIRECT_DATABASE_URL vai direto ao PostgreSQL, sem pooler. Use-a só para migrações: ela consome o limite de conexões do plano e não escala para servir requisições. O caso típico é o Prisma, que se recusa a rodar prisma migrate por um pooler:

datasource db {
  provider  = "postgresql"
  url       = env("DATABASE_URL")
  directUrl = env("DIRECT_DATABASE_URL")
}

Rode jatai env list a qualquer momento para conferir o valor atual.

Migrations e comandos avulsos

Migrations (fase de release do deploy) e comandos avulsos via jatai run não passam pelo pooler: a plataforma troca, só nesses processos, a DATABASE_URL por uma conexão direta ao banco. Isso é transparente ao cliente — não é preciso configurar nada — e evita erros de lock em migrations concorrentes que o modo transaction do pooler causaria. Apps que rodam migrações na subida do próprio container (fora da fase de release) devem apontá-las para DIRECT_DATABASE_URL.

Planos

O plano define o limite de armazenamento e o número máximo de conexões simultâneas do banco.

Plano Armazenamento Conexões Preço
base 512 MB 20 R$ 19/mês (cortesia no 1º banco do time)
escala_1 1 GB 50 R$ 29/mês
escala_2 5 GB 100 R$ 119/mês

Comportamento de quota

Ao ultrapassar o armazenamento do plano contratado (com uma pequena margem de tolerância), a plataforma revoga apenas escrita: o usuário do app perde a permissão de INSERT e UPDATE. Leitura e DELETE continuam funcionando normalmente, então dá para liberar espaço apagando dados sem precisar de suporte.

Assim que o uso volta a ficar abaixo do limite do plano, a escrita é restaurada automaticamente — sem intervenção manual.