DocsDatabases

Supabase

Connect to Supabase Postgres directly or via supabase-js from Deno, covering pooler ports, RLS, Edge Functions, and secret boundaries

There are two ways in: treat Supabase as managed Postgres and connect directly (with Drizzle/postgres.js—see PostgreSQL and 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).

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);
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:

MethodHost:portUse for
Direct connectiondb.<project-ref>.supabase.co:5432persistent servers, migrations, pg_dump; IPv6 (IPv4 requires a paid add-on)
Supavisor session modeaws-<region>.pooler.supabase.com:5432fallback for IPv4-only networks
Supavisor transaction modeaws-<region>.pooler.supabase.com:6543serverless / 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.
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, Row Level Security, Edge Functions, Function dependencies, Deno's official Supabase example.

Type to search all documentation.