Skip to content
dbSDK
Esc
↑↓navigate↵open⌘Jpreview
On this page

Switching providers

How to change adapters between Postgres, Supabase, and Neon, what carries over, and what you must move yourself.

Because every launch adapter is PostgreSQL over a different transport, switching is mostly a configuration change. The query code does not change. But switching adapters is not data migration, and this page is explicit about the difference.

What carries over

If your application uses the documented client surface, these are identical across adapters:

  • db.sql, db.query, db.batch, db.transaction call sites and their SQL text (PostgreSQL dialect throughout).
  • The result envelope: rows, rowCount, command.
  • DbError handling: codes, sqlstate, retryable, indeterminate.
  • Parameterization rules and the sql tag helpers.
  • close() / disposal patterns.

What changes

  • The adapter import and its options (connection string, mode, transport).
  • Capability-sensitive behavior. Check db.capabilities instead of hard-coding assumptions. Example: code that uses db.transaction() works on Supabase but needs a transaction transport on Neon HTTP.
  • Session-state-dependent code. The Supabase transaction pooler and Neon HTTP do not carry session state between top-level queries.
  • Environment variables and secret management.

A switch in code looks like this:

// before: Neon
import { neon } from "dbsdk/neon";
const db = createDatabase({ adapter: neon({ connectionString: NEON_URL }) });

// after: Supabase, same call sites
import { supabase } from "dbsdk/supabase";
const db = createDatabase({
  adapter: supabase({ connectionString: SUPABASE_URL, connectionMode: "session" }),
});

Keep the client construction in one module and the rest of the code transport-blind, and a switch is a one-file diff plus a capabilities re-check.

What does not move automatically

Data does not move. Switching the adapter in your code points the application at a different database. Nothing copies rows, schemas, users, or extensions between services. There is no failover: if one service is down, the other does not silently take over.

If you migrate data between providers, you plan it yourself with the usual tools (logical replication, dumps and restores, a maintenance window, and a cutover you control). A checklist that respects what dbSDK does:

  1. Create the target database and apply your schema (migrations you already have).
  2. Copy data with your chosen tool and verify row counts and constraints.
  3. Point the application at the new provider by changing the adapter configuration.
  4. Re-run your integration tests against the target, because capabilities can differ by transport (transaction support, session state).
  5. Keep the old database read-only until you are confident; dbSDK will not sync the two during the window.

Things that differ between services, not transports

Moving between PostgreSQL services can still surface differences that are about the service, not dbSDK or the driver:

  • Row-level security and roles: policies and grants live in each database.
  • Extensions: installed per database.
  • Connection limits and pooling behavior per plan.
  • Neon branches or Supabase-specific features do not exist on the other side.

None of these are hidden or translated by dbSDK; the SQL you send runs as written on whichever service you point at.

Was this page helpful?