Database

PostgreSQL extensions

Kuunda Cloud follows the model teams expect from managed Postgres: rich image, minimal preload, on-demand activation. The tenant is a proj_* schema — not an isolated database. That changes where an extension can be installed.

PostgreSQL 16extensions schemaCORE includedDedicated: on demand

1. Three layers (do not mix them up)

1 · Image

Package present

The extension appears in pg_available_extensions. It is not yet created in the database.

2 · Preload

Postgres startup

Only pg_stat_statements is preloaded. No pg_cron by default.

3 · CREATE

Activation

CORE and optional extensions at provisioning. The rest: console button on a dedicated instance, never via the SQL editor.

2. Shared pool vs dedicated instance

A PostgreSQL extension is database-level, not schema-level. On the shared pool, several proj_* projects share the same database: a CREATE EXTENSION would affect all of them.

PlanCatalogInstallation
Shared poolRead: CORE + optional extensions already createdDenied (contact support for a dedicated instance)
Dedicated / clusterAllowlist ∩ packages on the instanceDatabase → Extensions, one extension at a time

Why the button is greyed out

On a shared project, the UI shows the catalog but installs nothing. That is not an omission: it is the isolation boundary between tenants.

3. In the console

  1. Project → Database → Extensions
  2. Review already installed extensions ( extensions schema except the exceptions below)
  3. Dedicated instance: pick a packaged extension, then install. Dependencies (e.g. PostGIS before raster) are applied without CASCADE

SQL editor

CREATE EXTENSION and DROP EXTENSION are rejected in the editor. Use the Extensions screen. Do not create tables in the extensionsschema.

4. SQL, search_path and API

After creation, types and functions usually live in extensions. The project search_path is:

proj_<id_sans_tirets>, public, extensions

The REST API adds the same extra-search-path (public, extensions). You can therefore write citext or vector without a prefix, as on a Supabase project.

-- Exemple une fois citext activée (instance dédiée)
CREATE TABLE contacts (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  email citext NOT NULL UNIQUE
);

Schemas outside the REST API

The REST API only exposes public and proj_*. Never extensions, graphql, topology, tiger, cron and net in pgrst.db_schemas. GraphQL and PostGIS remain usable in SQL; they do not become REST collections.

plpgsql is PostgreSQL’s native language: it does not appear as a UI catalog row.

5. Catalog

The console only offers names packaged on the instance and allowed. An extension missing from pg_available_extensions is not listed.

Always there (CORE)

Created at provisioning (the project is not delivered without them). Present on the shared pool and on dedicated. No “install” button: they are already there.

ExtensionRole
uuid-osspUUID generation (uuid_generate_v4, etc.).
pgcryptoHashing, encryption, gen_random_uuid().
pg_trgmTrigram similarity, GIN/GiST indexes for fuzzy search.

Optional (provisioner)

Installed if the package is available. pg_stat_statements requires the preload (already in place). pg_graphql lives in its own schema.

ExtensionRole
vectorEmbeddings and similarity search (pgvector).
pg_stat_statementsSQL execution statistics (preloaded at startup).
pg_graphqlGraphQL API (graphql schema, outside the REST API).

On demand — contrib (dedicated instance)

Standard PostgreSQL 16 extensions, activable from the console on dedicated / cluster.

ExtensionRole
amcheckB-tree index integrity checks.
autoincAuto-increment trigger (legacy contrib).
bloomBloom index for multi-column equality filters.
btree_ginB-tree operator classes for GIN indexes.
btree_gistB-tree operator classes for GiST indexes.
citextCase-insensitive text (emails, identifiers).
cubeMultidimensional cube type (required by earthdistance).
dict_intFull-text search dictionary for integers.
dict_xsynSynonym dictionary for full-text search.
earthdistanceDistance between points on a sphere (depends on cube).
fuzzystrmatchSoundex, Levenshtein, metaphone (required by tiger).
hstoreKey/value pairs in a column.
insert_usernameTrigger that records the current user.
intaggInteger aggregates (legacy).
intarrayOperations and indexes on integer arrays.
isnISBN / ISSN / EAN types and related checks.
ltreeHierarchical paths (categories, trees).
moddatetimeAutomatic updated_at trigger.
old_snapshotInspection of old MVCC snapshots.
pageinspectLow-level page inspection (admin).
pg_buffercachePostgreSQL buffer cache contents.
pg_freespacemapFree space map.
pg_prewarmPreload relations into cache.
pg_visibilityTuple visibility map.
pg_walinspectWAL inspection.
pgrowlocksCurrent row locks.
pgstattupleTable fragmentation statistics.
refintReferential integrity triggers (legacy).
segNumber interval / segment type.
sslinfoSSL session information.
tablefunccrosstab and crosstab functions.
tcnTriggered change notification.
tsm_system_rowsTABLESAMPLE SYSTEM_ROWS.
tsm_system_timeTABLESAMPLE SYSTEM_TIME.
unaccentAccent stripping for search.

On demand — Kuunda image (PostGIS, etc.)

Tenant image packages. PostGIS can take 1–2 minutes and RAM. Do not install it on the shared pool (the UI refuses).

ExtensionRole
postgisGeographic types and functions (extensions schema).
postgis_rasterPostGIS rasters (depends on postgis).
postgis_sfcgalSFCGAL 3D geometry if the package is present on the instance.
postgis_topologyPostGIS topology (topology schema, outside the REST API).
postgis_tiger_geocoderTIGER geocoder (USA). tiger / tiger_data schemas.
address_standardizerPostal address normalization.
address_standardizer_data_usUS ruleset (depends on address_standardizer).
hypopgHypothetical indexes for EXPLAIN.
pg_repackTable reorganization without a long exclusive lock.

Packaged, no UI (dormant)

ExtensionRole
pg_cronScheduled SQL jobs. No UI. Preload only on ops request.
pgauditSQL audit. Packaged, no console activation.

Never offered

Isolation, attack surface or boot. Absent from the allowlist, including in the SQL editor.

ExtensionRole
dblinkQueries to another database (isolation leak).
postgres_fdwPostgreSQL Foreign Data Wrapper.
file_fdwRead server files.
httpHTTP calls from SQL.
pg_netAsync HTTP (Supabase).
wrappersSupabase FDW wrappers.
pgsodiumLegacy Supabase crypto / vault.
supabase_vaultSupabase secrets vault.
plv8JavaScript in the server.
pljavaJava in the server.
pllsLiveScript in the server.
plcoffeeCoffeeScript in the server.
adminpackpgAdmin admin tools.
loServer-side large objects.
xml2Legacy XML (risks).
pg_surgeryDestructive page repair.
pg_plan_filterPlan filtering (unsupported).
safeupdateGuard UPDATE/DELETE without WHERE (not packaged).
supautilsThird-party image internal utilities.

Intentionally absent from the image

Not a “full Supabase” clone. Among the missing: pgroongarumpgroutingpgjwtpgmqindex_advisorpg_partmanpg_jsonschemapg_hashidspg_tle*_wrapper.

6. Dependencies and imposed schemas

Kuunda installs the listed dependencies, without CASCADE.

ExtensionBefore
postgis_topologypostgis
postgis_rasterpostgis
postgis_sfcgalpostgis
postgis_tiger_geocoderpostgis, fuzzystrmatch
address_standardizer_data_usaddress_standardizer
earthdistancecube

Some extensions cannot be relocated into extensions (the .controlfile):

ExtensionSchema(s)
pg_graphqlgraphql, graphql_public
postgis_topologytopology
postgis_tiger_geocodertiger, tiger_data
pg_croncron (if enabled by ops)

postgis_tiger_geocoder

The install script reads the database default search_path to find the geometry type (PostGIS in extensions). The console handles this order. US geocoding only.

7. Import from Supabase / pg_dump

Import rewrites extensions.* references to match the Kuunda search_path . The dump’s CREATE EXTENSION statements are not replayed as-is: first install the needed pieces via Database → Extensions (dedicated) the needed pieces (pgcrypto is already CORE).

Guide: Supabase migration · Data import.

8. FAQ

Can I paste CREATE EXTENSION vector like on Supabase?

On dedicated: use the UI (safe equivalent). On the shared pool: vector is already installed at provisioning; a second CREATE from the editor is blocked.

Where are uuid-ossp / pgcrypto if I come from public?

New creations go into extensions. Kuunda does not move an extension already created in public. The search_path covers both.

How long does PostGIS take?

Up to about two minutes. One CREATE at a time; a platform lock avoids races.

How do I get citext / PostGIS on an existing project?

Shared-pool projects stay catalog-read-only. You need a dedicated instance (support / plan change), then the Extensions screen.

Open the console