With Vercel Postgres transitioning to Neon's native integration in the Vercel Marketplace, now is the perfect time to migrate from the Vercel Postgres SDK (@vercel/postgres) to the Neon serverless driver.

Why migrate?

Switching to the Neon serverless driver provides several advantages. It offers greater flexibility by allowing the choice between HTTP for single queries or WebSockets for transactions and full node-postgres compatibility. Additionally, it enhances maintainability by relying on Neon's actively maintained, native database driver.

Prerequisites

To begin, you’ll need:

  • An existing application using the Vercel Postgres SDK
  • A Neon account (your Vercel Postgres database will automatically migrate to Neon)

Migration Steps

1. Install the Neon serverless driver

Start by installing the Neon serverless driver in your project:

npm install @neondatabase/serverless

important

To ensure proper configuration, set your environment variable to DATABASE_URL when referencing the database URL in your code, especially if you're following this guide.

2. Update your database connection

Replace your Vercel Postgres SDK imports and connection setup with the Neon serverless driver. You have two options:

import { sql } from '@vercel/postgres';

import { neon } from '@neondatabase/serverless';
const sql = neon(process.env.DATABASE_URL!);
import { db } from '@vercel/postgres';

import ws from 'ws';
import { Pool, neonConfig } from '@neondatabase/serverless';

const pool = new Pool({ connectionString: process.env.DATABASE_URL });
neonConfig.webSocketConstructor = ws;

3. Update your queries

Here are common query patterns and how to migrate them:

Simple Queries

# Vercel Postgres SDK
const { rows } = await sql`SELECT * FROM users WHERE id = ${userId}`;

# Neon HTTP
const rows = await sql`SELECT * FROM users WHERE id = ${userId}`;

# Neon WebSockets
const { rows } = await pool.query('SELECT * FROM users WHERE id = $1', [userId]);

Transactions

import { db } from '@vercel/postgres';

async function transferFunds(fromId: number, toId: number, amount: number) {
  const client = await db.connect();
  try {
    await client.query('BEGIN');
    await client.query('UPDATE accounts SET balance = balance - $1 WHERE id = $2', [
      amount,
      fromId,
    ]);
    await client.query('UPDATE accounts SET balance = balance + $1 WHERE id = $2', [amount, toId]);
    await client.query('COMMIT');
  } catch (e) {
    await client.query('ROLLBACK');
    throw e;
  } finally {
    client.release();
  }
}

import { Pool } from '@neondatabase/serverless';

async function transferFunds(fromId: number, toId: number, amount: number) {
  const pool = new Pool({ connectionString: process.env.DATABASE_URL });
  try {
    await pool.query('BEGIN');
    await pool.query('UPDATE accounts SET balance = balance - $1 WHERE id = $2', [amount, fromId]);
    await pool.query('UPDATE accounts SET balance = balance + $1 WHERE id = $2', [amount, toId]);
    await pool.query('COMMIT');
  } catch (e) {
    await pool.query('ROLLBACK');
    throw e;
  } finally {
    await pool.end();
  }
}

Best practices

  1. Choose the right connection method:

    • Use HTTP (neon()) for single queries and simple transactions.
    • Use WebSockets (Pool) for complex transactions and session-based operations.
  2. Connection management:

    • For HTTP queries, reuse the sql query function.
    • For WebSocket connections in serverless environments, always close connections:
    const pool = new Pool({ connectionString: process.env.DATABASE_URL });
    try {
      // Your queries here
    } finally {
      await pool.end();
    }
  3. Error Handling:

    try {
      const result = await sql`SELECT * FROM users`;
      return result;
    } catch (error) {
      console.error('Database error:', error);
      throw new Error('Failed to fetch users');
    }

Working with ORMs

Neon's serverless driver is compatible with popular ORMs like Prisma and Drizzle ORM. Check out the following guides to learn more:

Advanced Configuration

For most cases, using neon serverless driver is straightforward without needing advanced configuration. However, for custom setups or troubleshooting, here are the key options:

  • poolQueryViaFetch: Setting poolQueryViaFetch to true sends Pool.query() calls as low-latency HTTP fetch requests (currently defaults to false).

  • wsProxy: This option is for connecting via a WebSocket proxy deployed in front of your your own Postgres instance, which allows you to use the Neon serverless driver with a local development environment.

For more information about these options, see Advanced configuration.

Need help?

Join our Discord Server to ask questions or see what others are doing with Neon. Users on paid plans can open a support ticket from the console. For more details, see Getting Support.