CapyDB Docs
Reference

Extensions

The Postgres extensions available on CapyDB clusters, how to enable them per database, and why the list is an allowlist.

The allowlist

CapyDB clusters (Postgres 17) provide these extensions:

ExtensionTrustedWhat it is for
pg_stat_statementsnoQuery statistics; also powers the slow-query view in Observability
pgcryptoyesCryptographic functions (gen_random_uuid(), digests, PGP)
uuid-osspyesLegacy UUID generators (uuid_generate_v4() etc.)
citextyesCase-insensitive text type
hstoreyesKey/value pairs in a column
pg_trgmyesTrigram matching — fuzzy search and LIKE acceleration
vector (pgvector)yesVector similarity search for embeddings
postgisnoGeographic objects, spatial types, and spatial indexing
unaccentyesText-search dictionary that strips accents
ltreeyesHierarchical label paths with rich search operators
fuzzystrmatchyesString similarity and distance (soundex, levenshtein)
btree_ginyesGIN operator classes for common scalar types
btree_gistyesGiST operator classes for common scalar types

plpgsql ships inside every Postgres server and is always available. New projects start with vector, pgcrypto, uuid-ossp, and pg_trgm already enabled.

Trusted vs superuser-managed

The Trusted column is the practical split:

  • Trusted extensions can be enabled by your own database role, on a direct connection, the normal way:

    CREATE EXTENSION IF NOT EXISTS pg_trgm;
  • Superuser-managed extensions (postgis, pg_stat_statements) need privileges your role deliberately does not have. Enable them through CapyDB instead — the managed path works for every allowlisted extension, trusted or not, so you can use it uniformly.

Managing extensions per database

Three equivalent surfaces, all backed by the same async job:

Dashboard — the project's Extensions page lists the allowlist with enablement toggles.

CLI:

capydb extensions list --project my-app
capydb extensions enable postgis --project my-app --wait
capydb extensions disable hstore --project my-app --wait

API:

GET    /v1/projects/{projectID}/extensions          # allowlist + enabled/trusted/version per extension
POST   /v1/projects/{projectID}/extensions          # {"name": "postgis"} → 202 + job
DELETE /v1/projects/{projectID}/extensions/{name}   # → 202 + job

Enable and disable are asynchronous jobs — poll the returned job (or pass --wait in the CLI) until it reaches completed. The extension is recorded as enabled only after CREATE EXTENSION actually succeeded on the host, so the listing never claims something the database does not have.

Disable is RESTRICT, on purpose

Disabling runs DROP EXTENSION without CASCADE. If anything in your schema depends on the extension — a column of its type, an index using its operator class — the job fails with the dependency error instead of silently dropping your objects. Remove the dependents first if you really mean it.

Why an allowlist

Extensions run inside the database process. A short, audited list keeps upgrades predictable and means a restore or import never lands on a host missing a library it needs. The list covers the unexciting majority of real workloads: UUIDs, crypto, fuzzy search, embeddings, and — since PostGIS joined — geospatial.

Imports and extensions

The import preflight fails when the source database uses an extension that is not on this list, naming the offenders. Options at that point:

  • drop the extension on (a copy of) the source if it was installed but unused — common with provider-default extensions
  • replace its usage (uuid-ossppgcrypto's gen_random_uuid() is the classic)
  • if your workload genuinely needs something missing, contact support — the allowlist grows on demand, not on speculation

After a successful import, the per-project extension list is reconciled with what the restored dump actually created, so the Extensions page reflects reality rather than the pre-import defaults.