# Postgres extensions

> Which Postgres extensions you can use on SupaHost, how to list, enable and remove them per project, and the special cases: pg_cron is built in, pg_net and dblink are preinstalled.

Source: https://supahost.app/docs/database/extensions · Updated 2026-11-11

Extensions add features to Postgres: vector search, geographic types, fuzzy text matching, scheduling and more. On SupaHost, the extensions you can use are the ones that ship in the Supabase Postgres image your instance runs, `supabase/postgres` 17 (release `2026.11.02` uses `17.6.1.136`). There's no separate list to request from; if the image has it, you can enable it.

Each project is its own database, so extensions are enabled per project. Turning on `vector` in one project doesn't affect the others.

## See what's available

In Studio's SQL editor (or any SQL session):

```sql
select name, default_version, installed_version, comment
from pg_available_extensions
order by name;
```

`installed_version` is filled in for extensions already enabled in this project.

Other ways to see the same list:

- **Studio**: *Database → Extensions*, with a toggle per extension.
- **MCP**: the `list_extensions` tool returns each extension with its installed and default versions and schema. Handy when an AI agent needs to know whether `vector` or `postgis` is enabled before writing a migration.

## Enable an extension

Create extensions in the `extensions` schema:

```sql
create extension if not exists vector with schema extensions;
create extension if not exists pg_trgm with schema extensions;
```

Why `extensions` rather than `public`:

- It keeps `public` (which the Data API exposes) free of dozens of helper functions and types.
- The Data API already adds `extensions` to its search path, so types like `vector` and functions like `similarity()` still resolve in API requests and in your own functions.

When you write functions with `set search_path = ''`, refer to extension objects with the schema, for example `extensions.vector(1536)` or `extensions.similarity(a, b)`.

Put the `create extension` line in a migration so a branch or a new project gets the same setup. See [SQL migrations](/docs/database/migrations).

## Example: fuzzy search on recipe titles

```sql
create extension if not exists pg_trgm with schema extensions;

create index recipes_title_trgm
  on public.recipes using gin (title extensions.gin_trgm_ops);

select title, extensions.similarity(title, 'chiken curry') as score
from public.recipes
where title operator(extensions.%) 'chiken curry'
order by score desc
limit 5;
```

## Remove an extension

```sql
drop extension if exists pg_trgm;
```

If tables, columns or indexes depend on the extension, Postgres refuses and lists them. `drop extension ... cascade` removes those objects too, including columns that use the extension's types, so read the list before you add `cascade`.

## Special cases on SupaHost

### pg_cron is built in: don't create it

Scheduling works in every project without enabling anything. Call `cron.schedule()` directly:

```sql
select cron.schedule('nightly-cleanup', '0 3 * * *', $$
  delete from public.sessions_log where created_at < now() - interval '30 days'
$$);
```

Do **not** run `create extension pg_cron`. pg_cron can only be installed in one database per Postgres server, and on SupaHost that's the instance's own `postgres` database. Each project gets a `cron` schema that forwards to it, so `cron.schedule`, `cron.unschedule`, `cron.job` and `cron.job_run_details` work as usual. Running `create extension pg_cron` in a project fails. The MCP server's `execute_sql` and `apply_migration` skip that statement and explain why, and `list_extensions` shows pg_cron with a note that it's built in. See [Scheduled jobs with pg_cron](/docs/cron-queues/cron) and [ERROR: can only create extension in database postgres](/kb/create-extension-pg-cron).

### pg_net is already installed

`pg_net` (asynchronous HTTP from SQL) and the `supabase_functions` schema used by database webhooks are set up when the project is created. See [Database webhooks and HTTP requests with pg_net](/docs/database/webhooks).

### Leave dblink in place

`dblink` is installed in the `extensions` schema of every project because the cron shim uses it to reach pg_cron. Dropping it breaks `cron.schedule()` in that project.

### Queues: use the dashboard

To use pgmq, click **Enable Queues** on the project's **Queues** tab instead of creating the extension yourself. That also creates the `pgmq_public` functions the Data API exposes. See [Queues with pgmq](/docs/cron-queues/queues).

### pg_graphql has no HTTP endpoint

The `graphql_public` schema exists, but there's no `/graphql/v1` route on SupaHost, so GraphQL over HTTP isn't available. Use the REST Data API.

## Extensions people often look for

Check the list in your project for exact names and versions. These are typical of the Supabase image:

| Need | Extension | Docs |
|---|---|---|
| Vector similarity search | `vector` | [Vector columns with pgvector](/docs/ai/pgvector) |
| Geographic data | `postgis` | [Geo data with PostGIS](/docs/database/postgis) |
| Fuzzy matching, `ilike` speed-ups | `pg_trgm` | [Full-text search](/docs/database/full-text-search) |
| Query statistics | `pg_stat_statements` | [Query performance and EXPLAIN](/docs/database/query-performance) |
| Secrets | `supabase_vault` | [Storing secrets with Vault](/docs/database/vault) |
| Case-insensitive text | `citext` | |
| Message queues | `pgmq` | [Queues with pgmq](/docs/cron-queues/queues) |

Supabase deprecated a few extensions for Postgres 17, including `plv8`, `timescaledb` and `pgjwt`. If an app you're moving relies on one of them, check `pg_available_extensions` first. When you import a project from Supabase Cloud, extensions that aren't available here are skipped with a warning.

Some extensions need to be preloaded when the server starts. Those only work if the image already preloads them; server-level settings aren't something you change on SupaHost.

## Updating an extension

A newer Postgres image can ship newer extension versions. In Postgres, an enabled extension stays at its installed version until someone runs `alter extension ... update`, so compare the two:

```sql
select name, installed_version, default_version
from pg_available_extensions
where installed_version is not null and installed_version <> default_version;

alter extension vector update;
```

## Related

- [Postgres on SupaHost](/docs/database/overview)
- [Supabase features on SupaHost](/docs/getting-started/feature-support)
