Neon’s serverless Postgres is a game-changer for Next.js apps, but the connection details can trip you up.

Let’s see it in action. Imagine a simple Next.js API route that fetches data from Neon.

// pages/api/users.js
import { Pool } from 'pg';

const pool = new Pool({
  user: process.env.NEON_USER,
  host: process.env.NEON_HOST,
  database: process.env.NEON_DATABASE,
  password: process.env.NEON_PASSWORD,
  port: 5432,
  ssl: {
    rejectUnauthorized: false // For local development, but use proper certs in production
  }
});

export default async function handler(req, res) {
  try {
    const result = await pool.query('SELECT * FROM users');
    res.status(200).json(result.rows);
  } catch (error) {
    console.error('Database query failed:', error);
    res.status(500).json({ error: 'Failed to fetch users' });
  }
}

This pages/api/users.js file, when deployed to Vercel, will try to connect to your Neon database using environment variables. The Pool object from the pg library manages a pool of connections, which is crucial for performance in a serverless environment where new instances spin up and down frequently.

The problem Neon solves is providing a scalable, cost-effective Postgres database that can handle the bursty traffic common in serverless applications. Traditional databases often struggle with connection limits and provisioning overhead. Neon’s architecture, with its separation of compute and storage and its branching capabilities, addresses these issues.

The key components you control are:

  • Connection String/Environment Variables: These are your credentials and endpoint for Neon. You’ll get these from your Neon project dashboard.
  • pg Library Configuration: How you instantiate the Pool object in your Next.js app. This includes setting ssl options, which are important for secure connections.
  • Database Schema and Queries: The actual SQL commands you run against your Neon database.
  • Vercel Environment Variables: How you securely inject your Neon credentials into your Vercel deployment.

Here’s how you’d set up the Vercel environment variables:

  1. Go to your Vercel project settings.
  2. Navigate to "Environment Variables."
  3. Add the following variables, using the values from your Neon project:
    • NEON_USER: Your Neon database user (e.g., neon or a custom user).
    • NEON_HOST: Your Neon connection string host (e.g., ep-example-12345.us-east-1.aws.neon.tech).
    • NEON_DATABASE: The name of your Neon database (e.g., mydb).
    • NEON_PASSWORD: Your Neon database password.

For local development, you’d typically use a .env.local file in your Next.js project root:

NEON_USER=your_local_neon_user
NEON_HOST=your_local_neon_host
NEON_DATABASE=your_local_neon_db
NEON_PASSWORD=your_local_neon_password

Neon’s serverless nature means it auto-scales. You don’t provision specific instance sizes. Instead, you pay for what you use. This is a significant departure from traditional managed Postgres offerings. The connection pooling in your Next.js app is still vital because even with auto-scaling, establishing a new database connection incurs latency. A pool keeps connections warm and ready.

The ssl: { rejectUnauthorized: false } part is a common shortcut for local testing. In production, you must configure SSL properly. Neon’s connection strings often include sslmode=require. The pg library handles this by default when a ssl option is present, but you might need to explicitly pass certificates if you’re not using the standard Neon connection string format or if your environment requires it. For most Vercel deployments using the standard Neon connection string, the pg library will correctly infer the SSL requirements.

When you query Neon, it’s not just a simple TCP connection. Neon’s architecture involves a proxy that routes your query to the appropriate compute instance. The pg library’s connection pooling helps manage these interactions efficiently, minimizing the overhead of establishing and tearing down connections to this distributed system. The serverless Postgres aspect means the compute layer scales independently of the storage. When your Next.js app gets a sudden traffic spike, Neon can spin up more compute to handle the database load without you needing to manually scale a database server.

The most counterintuitive aspect of Neon’s serverless architecture for many developers is how it handles connections and scaling. You might think that since it’s serverless, you don’t need connection pooling in your application. However, Neon’s serverless compute still involves connection establishment overhead. The pg library’s connection pool, when configured correctly with environment variables, ensures that your Next.js API routes can quickly acquire an available connection from Neon’s scaled compute, rather than waiting for a new one to be provisioned each time a request hits your API. This is why you still use new Pool() and not new Client().

The next hurdle you’ll likely face is optimizing your database queries for performance within the serverless context, especially as your application grows.

Want structured learning?

Take the full Neon course →