# Supabase

There are two ways in: treat Supabase as managed Postgres and connect directly (with Drizzle/postgres.js—see [PostgreSQL and Drizzle](/en/docs/database/postgres-drizzle)), or use the official SDK `@supabase/supabase-js` against the PostgREST/Auth/Storage APIs. The SDK is published on both npm and JSR (`jsr:@supabase/supabase-js`).

```ts title="src/supabase.ts"
import { createClient } from "jsr:@supabase/supabase-js@2";

const url = Deno.env.get("SUPABASE_URL");
const key = Deno.env.get("SUPABASE_PUBLISHABLE_KEY");
if (!url || !key) throw new Error("SUPABASE_URL / SUPABASE_PUBLISHABLE_KEY required");

export const supabase = createClient(url, key);
```

```bash
deno run \
  --allow-env=SUPABASE_URL,SUPABASE_PUBLISHABLE_KEY \
  --allow-net=<project-ref>.supabase.co \
  src/main.ts
```

## Direct Postgres connections and pooling

Supabase offers several connection methods; ports and use cases per the official docs:

| Method | Host:port | Use for |
| --- | --- | --- |
| Direct connection | `db.<project-ref>.supabase.co:5432` | persistent servers, migrations, `pg_dump`; IPv6 (IPv4 requires a paid add-on) |
| Supavisor session mode | `aws-<region>.pooler.supabase.com:5432` | fallback for IPv4-only networks |
| Supavisor transaction mode | `aws-<region>.pooler.supabase.com:6543` | serverless / edge functions with many short-lived connections |

- For environments without persistent processes (such as Deno Deploy), use transaction mode (6543). The docs state transaction mode does not support prepared statements—disable them in your client (`postgres.js`: `postgres(url, { prepare: false })`).
- Under serverless concurrency, budget total connections against the maximum instance count, not a single instance.
- Run migrations over a direct or session-mode connection as a separate release step; never grant schema mutation to the production HTTP process.

```bash
deno run \
  --allow-env=DATABASE_URL \
  --allow-net=aws-<region>.pooler.supabase.com:6543 \
  src/main.ts
```

## Auth and RLS boundaries

- The SDK acts as the caller: with the new publishable key (the counterpart of the legacy anon JWT key — the two are distinct key types that can coexist, not a simple rename) plus a user JWT, PostgREST operates under that user's role and RLS policies apply.
- The official RLS docs require RLS on every table in an exposed schema (`public` by default); once enabled, the API serves nothing to publishable-key requests until policies exist. Tables created in the Table Editor get RLS automatically; tables created via raw SQL need an explicit `enable row level security`.
- The new secret key (the counterpart of the legacy service_role JWT key) bypasses RLS, and the docs forbid shipping it to browsers or customers. Keep it server-side only, injected from the environment, out of logs.
- If your Deno backend only makes trusted service-to-service calls, a direct Postgres connection is usually simpler than service key + PostgREST. Reach for the SDK + RLS when you need per-end-user authorization.

## Edge Functions vs. local Deno

Supabase Edge Functions run on the Supabase Edge Runtime, which the docs describe as a Deno-compatible, TypeScript-first runtime (open source at github.com/supabase/edge-runtime). Practical differences from local Deno:

- Imports support `npm:`, `jsr:`, and Node built-ins; the docs recommend a dedicated `deno.json` per function and warn against sharing one global config across `/supabase/functions` for deployment.
- Use `supabase functions serve` locally for a runtime close to production, and `supabase functions deploy` to ship.
- Functions are designed for short-lived, idempotent work and can cold-start; move long-running jobs to background workers instead.
- It is a Deno-compatible runtime, not Deno itself—do not assume feature parity with your local `deno` version; check the Edge Runtime repo before relying on newer APIs.

## Secret management

- Do not introduce the secret key where publishable-key access suffices; keep the two under distinct environment variable names to prevent mix-ups.
- Load secrets only from the environment or a secret store—never source, logs, or error responses—and rotate using Supabase's key-rolling flow in the dashboard.
- Scope `--allow-env` to exact variable names and `--allow-net` to the project host; add `--no-prompt` in CI.

Official references: [Connecting to your database](https://supabase.com/docs/guides/database/connecting-to-postgres), [Row Level Security](https://supabase.com/docs/guides/database/postgres/row-level-security), [Edge Functions](https://supabase.com/docs/guides/functions), [Function dependencies](https://supabase.com/docs/guides/functions/dependencies), [Deno's official Supabase example](https://docs.deno.com/examples/supabase/).
