Neon serverless PostgreSQL adapter implementation for the Drizzle Adapter ecosystem.
The @drizzle-adapter/neon-http
package provides the Neon implementation for the Drizzle Adapter interface. While you don't interact with this package directly (you use @drizzle-adapter/core
instead), it enables support for Neon's serverless PostgreSQL in the Drizzle Adapter ecosystem.
Neon offers unique advantages for modern applications:
- HTTP-based PostgreSQL: Direct database access over HTTP, perfect for serverless and edge environments
- Serverless PostgreSQL: True serverless with instant scaling to zero
- Database Branching: Create instant database branches for development and testing
- Auto-scaling: Scales compute and storage independently
- Bottomless Storage: Separates storage from compute for unlimited capacity
- Edge Computing: Low-latency access through compute placement
- Cost Efficiency: Pay only for actual compute and storage usage
- PostgreSQL Compatibility: 100% PostgreSQL compatible with latest features
- Point-in-Time Recovery: Built-in backup and restore capabilities
- Serverless Applications: Zero cold starts with instant scaling
- Development Workflows: Instant database branching for testing and staging
- Edge Applications: Low-latency data access worldwide
- Cost-Optimized Workloads: Pay only for what you use
- Modern Development: Perfect for JAMstack and serverless architectures
# Install both the core package and the Neon adapter
pnpm install @drizzle-adapter/core @drizzle-adapter/neon-http
For the adapter to work correctly with the DrizzleAdapterFactory, you must import it for its self-registration side effects:
// Import for side effects - adapter will self-register
import '@drizzle-adapter/neon-http';
// Now you can use the factory
import { DrizzleAdapterFactory } from '@drizzle-adapter/core';
import { DrizzleAdapterFactory, TypeDrizzleDatabaseConfig } from '@drizzle-adapter/core';
const config: TypeDrizzleDatabaseConfig = {
DATABASE_DRIVER: 'neon-http',
DATABASE_URL: 'postgres://user:pass@your-branch.your-project.neon.tech/neondb'
};
const factory = new DrizzleAdapterFactory();
const adapter = factory.create(config);
While Neon operates over HTTP and doesn't require traditional database connections, this adapter implements the standard connection interface for compatibility. This means your code remains portable across different database adapters:
// These connection operations are no-ops for Neon HTTP but ensure
// your code remains portable if you switch to another database
const connection = await adapter.getConnection();
const client = connection.getClient();
try {
// Your database operations
} finally {
await connection.disconnect(); // No-op for Neon HTTP
}
This design allows you to switch between Neon and other databases without changing your application code.
const dataTypes = adapter.getDataTypes();
const users = dataTypes.dbTable('users', {
id: dataTypes.dbUuid('id').primaryKey().defaultRandom(),
name: dataTypes.dbText('name').notNull(),
email: dataTypes.dbText('email').notNull().unique(),
profile: dataTypes.dbJsonb('profile'),
searchVector: dataTypes.dbTsVector('search_vector'),
createdAt: dataTypes.dbTimestampTz('created_at').defaultNow()
});
const posts = dataTypes.dbTable('posts', {
id: dataTypes.dbUuid('id').primaryKey().defaultRandom(),
userId: dataTypes.dbUuid('user_id')
.references(() => users.id),
title: dataTypes.dbText('title').notNull(),
content: dataTypes.dbText('content').notNull(),
tags: dataTypes.dbArray('tags', { type: 'text' }),
metadata: dataTypes.dbJsonb('metadata'),
published: dataTypes.dbBoolean('published').default(false),
createdAt: dataTypes.dbTimestampTz('created_at').defaultNow()
});
import { eq, and, or, desc, sql } from 'drizzle-orm';
const client = await adapter.getConnection().getClient();
// INSERT
// Single insert with returning
const [newUser] = await client
.insert(users)
.values({
name: 'John Doe',
email: 'john@example.com',
profile: { bio: 'Hello!' }
})
.returning();
// Bulk insert
await client
.insert(posts)
.values([
{
userId: newUser.id,
title: 'First Post',
content: 'Hello, world!',
tags: ['hello', 'first']
},
{
userId: newUser.id,
title: 'Second Post',
content: 'Another post',
tags: ['second']
}
]);
// SELECT
// Select all
const allUsers = await client
.select()
.from(users);
// Select with conditions
const user = await client
.select()
.from(users)
.where(eq(users.email, 'john@example.com'));
// Select with join and array operations
const postsWithTags = await client
.select({
userName: users.name,
postTitle: posts.title,
tags: posts.tags
})
.from(posts)
.leftJoin(users, eq(posts.userId, users.id))
.where(sql`${posts.tags} && ARRAY['hello']::text[]`)
.orderBy(desc(posts.createdAt));
// UPDATE
// Update with JSONB operations
await client
.update(users)
.set({
profile: sql`${users.profile} || '{"title": "New Title"}'::jsonb`
})
.where(eq(users.id, newUser.id));
// DELETE
await client
.delete(posts)
.where(
and(
eq(posts.userId, newUser.id),
eq(posts.published, false)
)
);
Perfect for development and testing workflows:
// Development branch
const devAdapter = factory.create({
DATABASE_DRIVER: 'neon-http',
DATABASE_URL: 'postgres://user:pass@dev-branch.project.neon.tech/neondb'
});
// Staging branch
const stagingAdapter = factory.create({
DATABASE_DRIVER: 'neon-http',
DATABASE_URL: 'postgres://user:pass@staging-branch.project.neon.tech/neondb'
});
// Production branch
const prodAdapter = factory.create({
DATABASE_DRIVER: 'neon-http',
DATABASE_URL: 'postgres://user:pass@main-branch.project.neon.tech/neondb'
});
const client = await adapter.getConnection().getClient();
// Queries are automatically optimized for HTTP
const result = await client
.select()
.from(users)
.where(eq(users.id, userId));
- Query Optimization: Minimize the number of queries to reduce HTTP requests
- Database Branching: Use branches for development, testing, and staging environments
- Edge Computing: Deploy close to your users for lower latency
- Error Handling: Implement proper retry logic for network issues
- Portability: Use the connection interface for database portability
We welcome contributions! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
- @drizzle-adapter/core - Core interfaces and types
- @drizzle-adapter/pg-core - Shared PostgreSQL functionality