Supabase publishes `supabase/postgres` — plain Postgres with a bundled extension set
(`pgvector`, `pg_graphql`, `pg_cron`, `wrappers`, and more). `oke docker` matches that
image ahead of the generic Postgres recipe.

<Callout title="Not the full Supabase platform">
  This recipe does **not** start GoTrue, PostgREST, Kong, Realtime, Storage, or Studio. Auth, files,
  and realtime delivery are already covered by [Vault](/docs/elements/vault), [Store ·
  files](/docs/elements/store#files), and [Signal](/docs/elements/signal).
</Callout>

## Quick start

<Steps>

<Step>
### Pin the image

```typescript title="oke.config.ts"
images: {
  "store.sql": "supabase/postgres:15.8.1.049", // pin a real tag from Supabase's registry
},
```

</Step>

<Step>
### Same env shape as Postgres

`oke docker` injects the same `POSTGRES_USER` / `POSTGRES_PASSWORD` / `POSTGRES_DB`
refs from `OKE_STORE_SQL_*`. Driver id stays `postgres`.

</Step>

<Step>
### Use pgvector when you need it

```typescript
drivers: {
  store: {
    index: { test: "memory", prod: "pgvector" },
  },
},
```

`CREATE EXTENSION IF NOT EXISTS vector` runs when the `pgvector` index driver opens —
the extension ships in this image.

</Step>

</Steps>

## Required env

| Variable                 | Meaning                                   |
| ------------------------ | ----------------------------------------- |
| `OKE_STORE_SQL_USER`     | → `POSTGRES_USER`                         |
| `OKE_STORE_SQL_PASSWORD` | → `POSTGRES_PASSWORD`                     |
| `OKE_STORE_SQL_DB`       | → `POSTGRES_DB`                           |
| `DATABASE_URL`           | App connection (`postgres://…:5432/…`)    |
| `PGDATA`                 | Default `/var/lib/postgresql/data/pgdata` |

Identical credential contract to [Postgres](/docs/recipes/postgres) — only the image
(and its extension bundle) differs.

## Data and backup

| Path                                      | What lives there                           |
| ----------------------------------------- | ------------------------------------------ |
| `$PGDATA`                                 | Cluster data, including extension catalogs |
| Image `VOLUME` `/var/lib/postgresql/data` | Persistence mount                          |

Same backup story as plain Postgres: `pg_dump` or volume backup of
`/var/lib/postgresql/data`. Losing that volume loses tables **and** which extensions
were created.

## Production note

Want managed Supabase (Auth / Storage / Realtime included)? Use the
[Supabase provider](/docs/providers/supabase) and set `DATABASE_URL` — do not run this
image and the cloud project as if they were the same deployment.

For self-hosted production, prefer a pinned tag (not `latest`) and the same
shared-store guidance as [Postgres](/docs/recipes/postgres#production-note). Free-tier
cloud pausing does not apply to this Docker image — you own uptime.

## What the recipe configures

| Field          | Value                                                |
| -------------- | ---------------------------------------------------- |
| Match          | `supabase/postgres` before generic `postgres`        |
| Container port | `5432`                                               |
| Healthcheck    | `pg_isready -U $POSTGRES_USER`, every 5s, 10 retries |
| Connection URL | `postgres://user:pass@host:5432/db`                  |
| Preload        | Image config — recipe does **not** set `command`     |

## Query performance

<Callout title="Do not overwrite command">
  `supabase/postgres` already preloads `pg_stat_statements`. This recipe leaves `command` unset so
  vendor startup stays intact.
</Callout>

| Step    | What you do                                                        |
| ------- | ------------------------------------------------------------------ |
| Preload | Image `postgresql.conf` (not an oke `command`)                     |
| Create  | `CREATE EXTENSION IF NOT EXISTS pg_stat_statements`                |
| Advisor | `CREATE EXTENSION IF NOT EXISTS index_advisor CASCADE` when listed |

Console **Performance** then reads engine stats. Enable Index Advisor from the
same view when `pg_available_extensions` lists it.

## Troubleshooting

<Accordions>
<Accordion title="PgStatStatementsNotPreloaded after a custom command">

Do not replace the image entrypoint with a generic `postgres -c
shared_preload_libraries=pg_stat_statements`. Restore the vendor command, create
the extension, then open Store → **Performance**.

</Accordion>
<Accordion title='Extension "vector" is not available'>

You pinned a plain `postgres:` image, not `supabase/postgres`, or the tag predates the
bundle. Confirm the image reference contains `supabase/postgres`, then re-derive.
With the right image, `CREATE EXTENSION vector` succeeds without a separate install.

</Accordion>
<Accordion title="Looking for Studio / the REST API">

Those services are not part of this recipe. Use the
[managed Supabase provider](/docs/providers/supabase) for the full platform, or oke's
own Vault / Store · files / Signal for those concerns.

</Accordion>
</Accordions>

## Learn more

- [Supabase (provider)](/docs/providers/supabase) — managed cloud alternative
- [Postgres](/docs/recipes/postgres) — generic recipe this one takes precedence over
- [Store · Index](/docs/elements/store#index) — `pgvector`-backed vector search

## Next

<Cards>
  <Card
    title="Supabase"
    description="Managed cloud, same wire protocol."
    href="/docs/providers/supabase"
  />
  <Card
    title="PgDog"
    description="Add pooling in front of this recipe too."
    href="/docs/recipes/pgdog"
  />
  <Card
    title="Postgres"
    description="The plain image this specializes."
    href="/docs/recipes/postgres"
  />
</Cards>
