Skip to content

feat: add netlify-db driver#5420

Open
eduardoboucas wants to merge 15 commits intodrizzle-team:betafrom
netlify:netlify-db
Open

feat: add netlify-db driver#5420
eduardoboucas wants to merge 15 commits intodrizzle-team:betafrom
netlify:netlify-db

Conversation

@eduardoboucas
Copy link

@eduardoboucas eduardoboucas commented Mar 2, 2026

Summary

Add a first-party Netlify DB adapter (drizzle-orm/netlify-db) that intelligently selects the optimal underlying Postgres driver based on the runtime environment.

Netlify DB is a managed Postgres database. On Netlify's platform, the same application code runs in two very different contexts:

  • Serverless functions: no persistent connections, best served by HTTP-based queries
  • Server mode: — persistent connections via node-postgres

This adapter abstracts that decision away so consumers can write drizzle() once and get the right driver automatically.

How it works

Intelligent driver selection

The drizzle() entry point accepts multiple configurations:

import { drizzle } from 'drizzle-orm/netlify-db';

// Zero-config: reads NETLIFY_DB_URL and NETLIFY_DB_DRIVER env vars
const db = drizzle();

// Connection string (defaults to serverless)
const db = drizzle('postgres://...');

// Explicit client — consumer controls the driver
const db = drizzle({ client: netlifyDbClient });

When using zero-config or a connection string, the adapter creates a serverless session by default. If NETLIFY_DB_DRIVER=server is set, it delegates to node-postgres instead. When an explicit DrizzleClient is passed, the discriminated union (driver: 'serverless' | 'server') determines which adapter is used.

Dual-transport serverless session

In serverless mode, the adapter uses two transports within a single session:

Operation Transport Why
Regular queries (select, insert, update, delete) Neon HTTP (NeonHttpPreparedQuery) Stateless, one round-trip per query, ideal for one-shot queries
Transactions Neon WebSocket via Pool (NeonPreparedQuery) Transactions require a stateful connection

This is handled by NetlifyDbSession, which delegates to NeonHttpPreparedQuery for regular queries and creates a NetlifyDbWsSession (backed by a PoolClient over WebSocket) when transaction() is called.

Nested transactions are supported via savepoints (NetlifyDbTransaction).

Server mode

When the driver is 'server', drizzle() delegates entirely to the existing node-postgres adapter (drizzleNodePg), returning a NodePgDatabase. This path adds no new code — it reuses the battle-tested node-postgres adapter.

Tests

Integration tests in integration-tests/tests/pg/netlify-db.test.ts follow the existing pattern used by other Postgres adapters (neon-http, neon-serverless, node-postgres):

  • Shared test suite: Runs the full tests() and cacheTests() suites from pg-common.ts (~205 tests), skipping only tests that don't apply to the HTTP transport (migration tests, db.execute format differences, timestamp formatting). Custom versions of skipped tests are provided where applicable.

  • Instantiation paths: Asserts every code path in drizzle():

    • Connection string
    • Config with connection string
    • Config with connection object ({ connectionString })
    • Zero-config via NETLIFY_DB_URL env var
    • Zero-config with NETLIFY_DB_DRIVER=server (verifies node-postgres path)
    • Explicit serverless client ({ driver: 'serverless', httpClient, pool })
    • Explicit server client ({ driver: 'server', pool })
  • Serverless transport selection: Asserts the dual-transport behavior:

    • Regular queries (HTTP) and transactions (WebSocket) work in the same session
    • Transaction rollback works correctly (WebSocket path)
    • Nested transactions use savepoints

Running the tests

I made the integrations test depend on a NETLIFY_DB_URL environment variable containing the database connection string. I assume that would be something that we would need to supply to you and then you'd add it to the CI.

In the meantime, you should be able to test it with any Postgres database, as I've been doing locally:

cd integration-tests
NETLIFY_DB_URL='postgres://...' npx vitest run tests/pg/netlify-db.test.ts
 Test Files  1 passed (1)
      Tests  213 passed | 2 skipped (215)
   Start at  17:25:42
   Duration  656.07s (transform 251ms, setup 0ms, collect 477ms, tests 655.47s, environment 0ms, prepare 32ms)

RomanNabukhotnyi and others added 15 commits November 17, 2025 13:38
…itch job and consolidating secret inheritance
* feat(drizzle-kit): support d1 via binding

* chore: update version to 0.31.9 and add changelog for D1 API improvements

* fix: Fix router workflow

* chore: Clean up secrets in router workflow by commenting out unused variables

---------

Co-authored-by: RomanNabukhotnyi <nabukhotnyiroman@gmail.com>
@eduardoboucas eduardoboucas marked this pull request as ready for review March 2, 2026 18:20
@Sukairo-02 Sukairo-02 changed the base branch from main to beta March 4, 2026 07:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants