Orange Book
External databases

Connect Supabase from Workers: supabase-js or Hyperdrive

Use @supabase/supabase-js over PostgREST, or Hyperdrive pooled direct Postgres; choose by query frequency and cold-start requirements.

Edited and verified by Orange Book Editorial Team ·

INTEGRATIONSINTERMEDIATE30 minutesVerified 2026-08-27

Bottom line first

When you use Supabase table APIs, Auth, or Storage, pick @supabase/supabase-js (HTTP/PostgREST, naturally suited to Workers). When you need raw SQL, connection pooling, and lower latency, use Hyperdrive plus postgres.js for a direct Postgres connection.

Choosing between the two paths

PathBest forKey limits
@supabase/supabase-jsTable queries, row-level security (RLS), Auth, Storage — the full Supabase feature setGoes through PostgREST; expressiveness is limited by the API; no pooling benefit
Hyperdrive + postgres.jsRaw SQL, complex transactions, frequent short queriesRequires a Hyperdrive configuration; no LISTEN/NOTIFY or advisory locks

Supabase free-plan projects pause automatically after roughly 7 days of inactivity (they can be restored). While paused, both paths fail, so check project status in the Supabase dashboard first when troubleshooting.

Path one: supabase-js

npm i @supabase/supabase-js
npx wrangler secret put SUPABASE_URL
npx wrangler secret put SUPABASE_SERVICE_ROLE_KEY

SUPABASE_URL looks like https://<project-ref>.supabase.co; the service role key lives in the API settings of the Supabase dashboard. The service key bypasses RLS — keep it in a server-side secret only, never in a frontend bundle.

src/index.ts
import { createClient } from '@supabase/supabase-js';

interface Env {
  SUPABASE_URL: string;
  SUPABASE_SERVICE_ROLE_KEY: string;
}

export default {
  async fetch(request, env: Env): Promise<Response> {
    const supabase = createClient(env.SUPABASE_URL, env.SUPABASE_SERVICE_ROLE_KEY);
    const { data, error } = await supabase.from('notes').select('id,title').limit(10);
    if (error) {
      return Response.json({ error: error.message }, { status: 502 });
    }
    return Response.json({ notes: data });
  },
};

This path needs no Wrangler binding at all; beyond the secrets there is no extra configuration.

Path two: Hyperdrive direct Postgres

Get the direct connection string from the Supabase dashboard, shaped like postgres://USER:PASSWORD@HOST:PORT/postgres, then create the Hyperdrive configuration:

npx wrangler hyperdrive create supabase-pg --connection-string="postgres://USER:PASSWORD@HOST:PORT/postgres"
wrangler.jsonc
{
  "name": "notes-api",
  "compatibility_date": "2026-08-25",
  "compatibility_flags": ["nodejs_compat"],
  "hyperdrive": [
    { "binding": "HYPERDRIVE", "id": "<id returned by the create command>" }
  ]
}
src/index.ts
import { Client } from 'pg';

interface Env {
  HYPERDRIVE: Hyperdrive;
}

export default {
  async fetch(request, env: Env): Promise<Response> {
    const client = new Client({ connectionString: env.HYPERDRIVE.connectionString });
    try {
      await client.connect();
      const result = await client.query('SELECT id, title FROM notes LIMIT 10');
      return Response.json({ notes: result.rows });
    } catch (error) {
      return Response.json({ error: String(error) }, { status: 502 });
    } finally {
      await client.end().catch(() => {});
    }
  },
};

With postgres.js the idea is identical — swap in env.HYPERDRIVE.connectionString. Hyperdrive enforces TLS, which Supabase satisfies by default.

Verification and troubleshooting

After deploying, walk the endpoint with curl:

curl -s https://<worker>.workers.dev/notes
SymptomCheck firstRecovery
502 with a fetch failureWhether the Supabase project was auto-pausedRestore the project in the dashboard and retry
401/403Whether the service role key was mistyped or rotatedRewrite it with wrangler secret put and redeploy
Hyperdrive path cannot connectWhether HOST/PORT point to the direct endpoint instead of the pooled oneRebuild Hyperdrive with the direct connection string from the dashboard
SQL errors mentioning LISTENWhether the code uses a feature Hyperdrive does not supportSwitch to polling or supabase-js Realtime

Remote boundary and rollback

Creating a Hyperdrive configuration, writing Supabase secrets, and deploying the Worker all change Cloudflare- or Supabase-side state; this tutorial does not run those actions. Rollback: remove the hyperdrive binding from wrangler.jsonc and redeploy, then delete the configuration with wrangler hyperdrive delete <id>. If you rotated the service role key, regenerate it in the Supabase dashboard and invalidate the old value. Business data is unaffected by a code rollback and needs no restore.

Next: connect Neon from Workers. General binding and secret rules live in Bindings, environments, and secrets.

Primary sources

Did this page help you complete your goal?

Beta feedback is generated in this browser and is never uploaded automatically.

On this page