Neon HTTP
Serverless PostgreSQL driver for Neon
Installation
pnpm add @neondatabase/serverless
Configuration
import { createClient } from "viborm/neon-http";
const client = createClient({
databaseUrl: process.env.DATABASE_URL,
schema,
});
Options
| Option | Type | Description |
|---|---|---|
databaseUrl |
string |
PostgreSQL connection URL |
namespace |
string |
PostgreSQL schema for VibORM-owned objects (default public) |
options.fetchOptions |
RequestInit |
Custom fetch options |
pgvector |
boolean |
Enable pgvector support |
postgis |
boolean |
Enable PostGIS support |
With pgvector
import { createClient } from "viborm/neon-http";
const client = createClient({
databaseUrl: process.env.DATABASE_URL,
pgvector: true,
schema,
});
Namespace
namespace selects the PostgreSQL schema holding this driver’s tables,
junctions, indexes, ORM-managed enums, and migration tracking table. Omitted, it
is public.
import { createClient } from "viborm/neon-http";
const db = createClient({
databaseUrl: process.env.DATABASE_URL,
namespace: "billing",
schema,
});
Qualification happens before execution, so each HTTP request already carries the schema and no setup statement is sent — direct queries and native batches alike:
SELECT "user"."id" FROM "billing"."user" AS "user"
Raw SQL is never rewritten and keeps ordinary search_path semantics — see
Namespaces.
Serverless Usage
Neon HTTP is optimized for serverless/edge environments:
// Vercel Edge, Cloudflare Workers, etc.
export default async function handler(request: Request) {
const client = createClient({
databaseUrl: process.env.DATABASE_URL,
schema,
});
const users = await client.user.findMany();
return Response.json(users);
}
Transactions & Batching
Neon HTTP does not support traditional dynamic transactions (each HTTP request is a separate connection), but VibORM provides full support for batch mode using Neon’s transaction() function.
Batch Mode (Recommended)
Use the array API for atomic operations - VibORM uses Neon’s transaction() function under the hood:
// Atomic execution using Neon's transaction() function
const [user, post] = await client.$transaction([
client.user.create({ data: { name: "Alice", email: "alice@example.com" } }),
client.post.create({ data: { title: "Hello", authorId: "preset-id" } }),
]);
Dynamic Transactions
Dynamic transactions (callback API) are unsupported and reject:
// Throws TransactionError: Neon HTTP does not support callback transactions
await client.$transaction(async (tx) => {
const user = await tx.user.create({ data: { name: "Alice" } });
await tx.post.create({ data: { title: "Hello", authorId: user.id } });
});
Migrations
Schema push executes atomically through Neon’s transaction() function.
File-based migrate apply requires a callback transaction and rejects on
Neon HTTP.
Capabilities
Dynamic transactions reject; batch mode is fully supported via Neon’s transaction() function. See the feature matrix for the full comparison.
Limitations
- Batch operations cannot read each other’s results — use a single nested write for dependent mutations
- HTTP-based: slightly higher latency than traditional connections
- Best suited for serverless environments with simple queries
- For full transaction support, use
@neondatabase/serverlessPool with WebSockets