PostgreSQL gerenciado — PostGIS, extensões e atualizações
Crie um Postgres, ative PostGIS, pgvector e outras extensões pelo painel ou pela CLI sem reiniciar o banco, e mantenha a imagem atualizada com um clique.
O que é
Cada banco PostgreSQL gerenciado roda num cluster próprio dentro do seu ambiente. A imagem atual da plataforma já traz PostGIS 3.6, pgvector e uma lista curada de extensões: você escolhe o que ativar em cada banco, sem restart. Bancos criados antes da imagem atual recebem uma atualização de manutenção, aplicada por você quando quiser.
Criar um banco
Pelo canvas do projeto (Adicionar Serviço → Database → PostgreSQL) ou pela CLI. A versão é escolhida na criação.
Versões
PostgreSQL 15, 16, 17 ou 18, escolhida ao criar o banco. A troca para uma versão maior depois é in-place (veja Troca de versão maior).
CLI
upuai add --type database --engine postgres --name db — o alias postgres também vale em upuai template deploy (CLI v0.26.0+).
Conexão
As variáveis de conexão (DATABASE_URL e afins) são injetadas nos serviços da aplicação que referenciam o banco. O banco se chama app e o usuário da conexão é postgres, dono do banco.
Migrations
Como o usuário da conexão é dono do banco app, a migration da sua aplicação pode rodar CREATE EXTENSION IF NOT EXISTS postgis; sem passar pelo painel.
Extensões (PostGIS, pgvector e outras)
A lista gerenciada abaixo vem na imagem atual da plataforma. Ative, desative e atualize cada extensão no banco app.
No painel: abra o banco → aba Banco de dados → sub-aba Extensões. Cada extensão tem um switch; ativar é imediato e desativar pede confirmação. Pela CLI: upuai db extensions [enable|disable|update <nome>] (CLI v0.26.0+).
Extensões gerenciadas
Geoespacial
postgis, postgis_topology, postgis_raster, postgis_sfcgal, postgis_tiger_geocoder, address_standardizer, address_standardizer_data_us, pgrouting, earthdistance, cube
Busca e IA
vector (pgvector), pg_trgm, unaccent, fuzzystrmatch
Índices
btree_gin, btree_gist, bloom
Tipos
citext, hstore, ltree, isn, seg, intarray, uuid-ossp
Segurança
pgcrypto
Utilidades
tablefunc, postgres_fdw, dblink
Como funciona
- Ativar roda CREATE EXTENSION ... CASCADE no banco app: as dependências entram junto (ex.: pgrouting traz postgis). É instantâneo e não reinicia o banco.
- Desativar roda DROP EXTENSION ... RESTRICT: se uma tabela, coluna ou outra extensão depende dela, a operação é recusada e o erro lista o que depende. A plataforma nunca apaga nada em cascata.
- Atualizar leva uma extensão instalada para a versão que a imagem atual traz (o painel mostra o botão Atualizar quando há versão nova).
- Uma extensão marcada como indisponível (unavailable) não existe na imagem do seu banco: aplique a atualização de manutenção primeiro.
- Com um deploy ou atualização do banco em andamento, as mudanças de extensão são recusadas até terminar.
# Listar as extensões gerenciadas e o estado de cada uma
$ upuai db extensions -s db
NAME CATEGORY STATUS VERSION DESCRIPTION
postgis geo enabled 3.6.4 PostGIS geometry and geography spatial types and functions
postgis_topology geo available 3.6.4 PostGIS topology spatial types and functions
vector search available 0.8.1 vector data type and ivfflat and hnsw access methods
...
# Ativar (CREATE EXTENSION ... CASCADE no banco app — sem restart)
$ upuai db extensions enable postgis -s db
✓ postgis 3.6.4 enabled
# Desativar (DROP EXTENSION ... RESTRICT — pede confirmação; -y em CI/agentes)
$ upuai db extensions disable postgis -s db -y
✗ cannot disable postgis: other objects still depend on it:
column geo of table lojas depends on type geography
extension postgis_topology depends on extension postgis
drop or change those objects first — the platform never drops dependent objects (no CASCADE)
# Atualizar uma extensão instalada para a versão que a imagem traz
$ upuai db extensions update postgis -s db$ upuai db extensions -s db -o json
{
"extensions": [
{
"name": "postgis",
"category": "geo",
"description": "PostGIS geometry and geography spatial types and functions",
"available": true,
"installed": true,
"installedVersion": "3.6.4",
"defaultVersion": "3.6.4",
"updateAvailable": false
}
]
}Fora da lista gerenciada
- Extensões que exigem shared_preload_libraries — pg_stat_statements e pgaudit — não são gerenciadas pelo painel nem pela CLI.
- pg_cron não faz parte da imagem.
- Outras extensões que existem na imagem continuam disponíveis por SQL com as credenciais do banco.
Exemplo com PostGIS
Uma tabela com coordenadas geográficas, índice espacial GiST e uma consulta por raio — o mesmo roteiro que usamos para validar a funcionalidade.
CREATE EXTENSION IF NOT EXISTS postgis; -- ou: upuai db extensions enable postgis
CREATE TABLE lojas (
id serial PRIMARY KEY,
nome text,
geo geography(Point, 4326)
);
CREATE INDEX lojas_geo_idx ON lojas USING gist (geo);
INSERT INTO lojas (nome, geo) VALUES
('Savassi', ST_GeogFromText('POINT(-43.9378 -19.9381)')),
('Pampulha', ST_GeogFromText('POINT(-43.9706 -19.8512)')),
('Rio de Janeiro', ST_GeogFromText('POINT(-43.1729 -22.9068)'));
-- Lojas num raio de 15 km da Praça Sete (Belo Horizonte), usando o índice GiST
SELECT nome,
round((ST_Distance(geo, ST_GeogFromText('POINT(-43.9386 -19.9191)')) / 1000)::numeric, 1) AS km
FROM lojas
WHERE ST_DWithin(geo, ST_GeogFromText('POINT(-43.9386 -19.9191)'), 15000)
ORDER BY km;
-- nome | km
-- ----------+-----
-- Savassi | 2.1
-- Pampulha | 8.2Atualização de manutenção
Leva o banco para a imagem atual da plataforma, mantendo a mesma versão maior. É assim que bancos criados antes de 2026-10-01 passam a ter PostGIS e as demais extensões gerenciadas.
- Mesma versão maior (ex.: continua 16) — traz correções de segurança, a base atual do sistema e as extensões novas.
- O banco reinicia e fica indisponível por cerca de 1 a 2 minutos. Os dados são preservados.
- Se a atualização não concluir dentro da janela, a imagem anterior é restaurada automaticamente.
- Você decide quando aplicar: o painel e a CLI avisam quando há atualização pendente.
No painel: banco → Configurações → Versão → Aplicar atualização. Pela CLI: upuai db version mostra se há atualização pendente e upuai db update --yes --wait aplica e espera terminar.
$ upuai db version -s db
Engine postgresql
Version 16
Update available — run 'upuai db update'
$ upuai db extensions enable postgis -s db
✗ postgis is not shipped by this database's current image — apply the pending update first: upuai db update
# Mesma versão, imagem atual da plataforma. O banco reinicia (~1–2 min).
$ upuai db update -s db --yes --wait
$ upuai db update -s db --yes
✓ Database already up to date (version 16)Troca de versão maior
Ex.: 16 → 17, pelo painel (Configurações → Versão) ou pela API. A troca pede confirmação.
- Se há atualização de manutenção pendente, aplique-a primeiro — a troca de versão maior é recusada com DB_MAINTENANCE_REQUIRED até lá.
- Um backup é feito antes de aplicar a troca.
- A troca é offline: o banco fica indisponível durante o pg_upgrade (cerca de 2 minutos num banco pequeno no nosso teste).
- Extensões instaladas, incluindo PostGIS, continuam funcionando na versão nova.
- Downgrade não é suportado.
Para agentes de IA
Roteiro para um agente (Claude Code, Cursor, Codex…) que precisa de uma extensão — por exemplo, um app GeoDjango ou Rails com PostGIS.
# 1. Estado das extensões (JSON estável para scripts e agentes)
upuai db extensions -s <db> -o json
# 2a. "available": true → ativar direto (instantâneo, sem restart)
upuai db extensions enable postgis -s <db>
# 2b. "available": false → o banco está numa imagem antiga:
# avise o usuário que o banco reinicia por ~1–2 min, então
upuai db update -s <db> --yes --wait
upuai db extensions enable postgis -s <db>
# Alternativa: a própria migration da aplicação
# CREATE EXTENSION IF NOT EXISTS postgis;Códigos de erro
Os códigos são estáveis e iguais no painel, na API e na CLI (upuai … -o json, campo code/error).
| Código | O que significa / o que fazer |
|---|---|
| DB_EXTENSION_NOT_ALLOWED | A extensão não está na lista gerenciada. Rode upuai db extensions para ver a lista; outras extensões continuam disponíveis por SQL. |
| DB_EXTENSION_UNAVAILABLE | A extensão não existe na imagem atual do banco. Aplique a atualização de manutenção (upuai db update) e ative de novo. |
| DB_EXTENSION_IN_USE | Algo depende da extensão (tabela, coluna ou outra extensão). O erro lista os dependentes: remova-os antes de desativar. |
| DB_OBJECT_LOCKED | Um objeto estava bloqueado por outra sessão. Tente de novo em instantes. |
| DB_READ_ONLY | O banco está em modo somente leitura (limite de armazenamento do plano). Libere espaço ou mude de plano. |
| DB_OPERATION_IN_PROGRESS | Outra operação (deploy, troca de versão ou atualização) está em andamento neste banco. Espere terminar. |
| DB_MAINTENANCE_REQUIRED | Troca de versão maior pedida com atualização de manutenção pendente. Aplique a atualização primeiro. |
| DB_MAINTENANCE_COLLATION_RISK | A atualização trocaria o sistema base e o banco usa collations cuja ordenação pode mudar. Nada foi alterado; fale com o suporte para agendar. |
Perguntas frequentes
Dúvidas comuns sobre extensões e atualizações.
Ter PostGIS na imagem deixa o banco mais lento ou mais caro?
Não. A extensão só é carregada quando você a ativa e usa. Num banco que não ativou nada, ela é só um arquivo no disco.
Ativar uma extensão reinicia o banco?
Não. Ativar, desativar e atualizar extensões rodam SQL no banco app e são imediatos. Só a atualização de manutenção e a troca de versão maior reiniciam.
Posso usar PostGIS num banco criado antes de 2026-10-01?
Sim, depois da atualização de manutenção (Configurações → Versão → Aplicar atualização, ou upuai db update). O banco reinicia por 1 a 2 minutos e os dados são preservados.
Por que desativar uma extensão foi recusado?
Porque algo ainda depende dela — o erro lista o quê (ex.: uma coluna geography). A plataforma usa RESTRICT e nunca apaga dados em cascata: remova os dependentes e tente de novo.
Minha aplicação pode criar a extensão sozinha?
Pode. O usuário do DATABASE_URL é dono do banco app, então CREATE EXTENSION IF NOT EXISTS postgis; numa migration funciona — desde que a extensão exista na imagem do banco.
Dá para usar pg_cron ou pg_stat_statements?
Não pela lista gerenciada: pg_stat_statements e pgaudit exigem configuração de preload do servidor, e pg_cron não faz parte da imagem.
Recursos
Referências relacionadas.