Serverless Driver
Use @neondatabase/serverless to connect from edge runtimes and serverless functions through PgBeam with HTTP or WebSocket transports.
Connect from edge runtimes and serverless functions using the
@neondatabase/serverless driver. PgBeam supports both the HTTP query endpoint
and the WebSocket wire protocol. Your neon() / Pool call sites and every
query stay exactly as they are.
One required step: point the driver at PgBeam
Changing the connection-string host is not enough on its own. By default
@neondatabase/serverless derives its endpoint by rewriting the host: it
replaces the first label with api., so abc.proxy.pgbeam.app would resolve
to https://api.proxy.pgbeam.app/sql, dropping the abc subdomain PgBeam
needs to route your project. Point the driver at PgBeam once, globally, with
neonConfig before any query runs:
import { neonConfig } from "@neondatabase/serverless";
// HTTP /sql endpoint: keep the project subdomain, append /sql
neonConfig.fetchEndpoint = (host) => `https://${host}/sql`;
// WebSocket /v2 endpoint (Pool / Client)
neonConfig.wsProxy = (host) => `${host}/v2`;These two lines are the only addition. Your query call sites do not change.
(On Neon's own *.neon.tech hosts the defaults work; PgBeam needs the override
because its hostnames are not *.neon.tech.)
Setup
Install the package
npm install @neondatabase/serverlesspnpm add @neondatabase/serverlessyarn add @neondatabase/serverlessbun add @neondatabase/serverlessFor Node.js environments using WebSocket transport, also install ws:
npm install wsPoint the driver at PgBeam
Set neonConfig once, before any query runs (see the warning above for why
this is required). In Node.js, also set the WebSocket constructor.
import { neonConfig } from "@neondatabase/serverless";
neonConfig.fetchEndpoint = (host) => `https://${host}/sql`;
neonConfig.wsProxy = (host) => `${host}/v2`;
// Node.js only: provide a WebSocket implementation for the Pool/Client paths
// import ws from "ws";
// neonConfig.webSocketConstructor = ws;HTTP transport: neon() tagged template
Best for one-shot queries from edge/serverless functions. Each call is a single HTTP request. No persistent connection required.
import "./neon-config"; // applies neonConfig.fetchEndpoint
import { neon } from "@neondatabase/serverless";
const sql = neon("postgresql://user:pass@abc.proxy.pgbeam.app/mydb");
const rows = await sql`SELECT * FROM users WHERE active = true`;WebSocket transport: Pool / Client
Best for interactive transactions or session-level features. Uses the PostgreSQL wire protocol over WebSocket.
import "./neon-config"; // applies neonConfig.wsProxy
import { Pool } from "@neondatabase/serverless";
const pool = new Pool({
connectionString: "postgresql://user:pass@abc.proxy.pgbeam.app/mydb",
});
const { rows } = await pool.query("SELECT * FROM users");import { Pool, neonConfig } from "@neondatabase/serverless";
import ws from "ws";
neonConfig.fetchEndpoint = (host) => `https://${host}/sql`;
neonConfig.wsProxy = (host) => `${host}/v2`;
neonConfig.webSocketConstructor = ws;
const pool = new Pool({
connectionString: "postgresql://user:pass@abc.proxy.pgbeam.app/mydb",
});
const { rows } = await pool.query("SELECT * FROM users");Run a test query
const result = await sql`SELECT 1 AS ok`;
console.log(result); // [{ ok: 1 }]If this returns results, the serverless driver is connected through PgBeam.
HTTP vs WebSocket
HTTP (neon()) | WebSocket (Pool / Client) | |
|---|---|---|
| Best for | One-shot queries, edge functions | Transactions, session features |
| Connection | Stateless HTTP request | Persistent WebSocket |
| Cold start | None | WebSocket handshake + TLS |
| Transactions | sql.transaction([...]) | BEGIN / COMMIT via client |
| Pipelining | Automatic (batched in one request) | PostgreSQL wire protocol |
| Max payload | ~10 MB response | Unlimited streaming |
Edge runtime compatibility
The serverless driver works in any runtime with fetch (for HTTP) or
WebSocket (for WS):
| Runtime | HTTP | WebSocket | Notes |
|---|---|---|---|
| Vercel Edge Functions | Yes | Yes | Built-in WebSocket support |
| Cloudflare Workers | Yes | Yes | Built-in WebSocket support |
| Deno Deploy | Yes | Yes | Built-in WebSocket support |
| Bun | Yes | Yes | Built-in WebSocket support |
| Node.js | Yes | Yes | Requires ws package |
Drizzle ORM integration
Use the serverless driver adapters with Drizzle for type-safe queries:
The same neonConfig setup applies. Drizzle wraps the Neon driver, so once the
endpoint is pointed at PgBeam, your Drizzle schema and queries are unchanged.
import "./neon-config"; // applies neonConfig.fetchEndpoint
import { neon } from "@neondatabase/serverless";
import { drizzle } from "drizzle-orm/neon-http";
const sql = neon("postgresql://user:pass@abc.proxy.pgbeam.app/mydb");
const db = drizzle(sql);
const users = await db.select().from(usersTable);import "./neon-config"; // applies neonConfig.wsProxy (+ webSocketConstructor on Node)
import { Pool } from "@neondatabase/serverless";
import { drizzle } from "drizzle-orm/neon-serverless";
const pool = new Pool({
connectionString: "postgresql://user:pass@abc.proxy.pgbeam.app/mydb",
});
const db = drizzle(pool);
const users = await db.select().from(usersTable);Transactions
Use sql.transaction() to run multiple statements in a single HTTP request:
import { neon } from "@neondatabase/serverless";
const sql = neon("postgresql://user:pass@abc.proxy.pgbeam.app/mydb");
const results = await sql.transaction([
sql`UPDATE accounts SET balance = balance - 100 WHERE id = 1`,
sql`UPDATE accounts SET balance = balance + 100 WHERE id = 2`,
]);Use standard BEGIN / COMMIT with a dedicated client:
import { Pool } from "@neondatabase/serverless";
const pool = new Pool({
connectionString: "postgresql://user:pass@abc.proxy.pgbeam.app/mydb",
});
const client = await pool.connect();
try {
await client.query("BEGIN");
await client.query("UPDATE accounts SET balance = balance - 100 WHERE id = 1");
await client.query("UPDATE accounts SET balance = balance + 100 WHERE id = 2");
await client.query("COMMIT");
} catch (e) {
await client.query("ROLLBACK");
throw e;
} finally {
client.release();
}Data type notes
PgBeam matches the @neondatabase/serverless type contract over the HTTP
endpoint. In particular, bigint (int8), numeric, and money are returned
as strings, not numbers: a JavaScript Number cannot represent integers
above 2^53 or arbitrary-precision decimals without silent loss. Wrap them with
BigInt(...) or a decimal library as needed.
const [row] = await sql`SELECT 9223372036854775807::bigint AS big`;
row.big; // "9223372036854775807" (string)
BigInt(row.big); // 9223372036854775807njson / jsonb are parsed into objects, and arrays into JS arrays, exactly as
the Neon driver does.
Caching and replicas
SQL annotations work the same with the serverless driver:
import { neon } from "@neondatabase/serverless";
const sql = neon("postgresql://user:pass@abc.proxy.pgbeam.app/mydb");
// Cache for 5 minutes
const categories =
await sql`/* @pgbeam:cache maxAge=300 */ SELECT * FROM categories`;
// Route to read replica
const stats = await sql`/* @pgbeam:replica */ SELECT count(*) FROM orders`;
// Combine both
const products =
await sql`/* @pgbeam:replica */ /* @pgbeam:cache maxAge=60 */ SELECT * FROM products`;See Caching and Read Replicas for details.
Common issues
| Issue | Cause | Fix |
|---|---|---|
Requests hit api.proxy.pgbeam.app / 404 / wrong project | neonConfig.fetchEndpoint not set; driver rewrote the host to api. | Set neonConfig.fetchEndpoint so requests target the /sql path (see Setup step 2) |
WebSocket is not defined | Node.js missing WS constructor | Install ws and set neonConfig.webSocketConstructor = ws |
fetch failed on HTTP endpoint | Network/firewall blocking HTTPS, or fetchEndpoint not pointed at /sql | Verify the proxy hostname resolves, port 443 is open, and fetchEndpoint is set |
| Slow cold starts with WebSocket | TLS + WS handshake on each invocation | Use HTTP transport for stateless queries |
connection terminated | Idle timeout exceeded | Use connection pooling or reconnect on error |
Further reading
- Connection Pooling: Pool modes and sizing guidance
- Caching: TTL, SWR, cache rules, and SQL annotations
- Read Replicas: Replica setup and routing
- @neondatabase/serverless on npm: Driver documentation