Neon’s serverless Postgres, when paired with Next.js’s App Router, offers a powerful, scalable database solution for modern web applications.
Let’s see it in action. Imagine a simple Next.js app that displays a list of users fetched from a Neon database.
// app/page.js
import { sql } from '@vercel/postgres';
export default async function Page() {
const { rows } = await sql`SELECT * FROM users;`;
return (
<div>
<h1>Users</h1>
<ul>
{rows.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
}
This page.js file leverages Next.js’s Server Components. When a user requests this page, the sql function from @vercel/postgres (which is designed to work seamlessly with Neon) executes a query directly on the server. The results are then passed as props to the React component, which renders the HTML. Notice there’s no client-side JavaScript needed for this data fetching.
The magic here is how Neon and Next.js (specifically the App Router’s server-side capabilities) eliminate the need for a persistent database connection. Traditional setups often involve a connection pool running on a server that your Next.js app connects to. With serverless Postgres, the database itself scales connections on demand. When your Next.js server component needs to query the database, it establishes a connection. Once the query is complete, that connection is released back to Neon’s pool, and the database scales down. This drastically reduces idle connection costs and improves resource utilization.
To set this up:
- Create a Neon Project: Go to neon.tech and create a new Postgres database. Note down your connection string. It will look something like
postgresql://[user]:[password]@[host]/[database]?sslmode=require. - Configure Environment Variables: In your Next.js project, create a
.env.localfile and add your Neon connection string:POSTGRES_URL="postgresql://[user]:[password]@[host]/[database]?sslmode=require" - Install
@vercel/postgres:npm install @vercel/postgres # or yarn add @vercel/postgres # or pnpm add @vercel/postgres - Create a
userstable: Connect to your Neon database (e.g., using the Neon UI orpsql) and run:CREATE TABLE users ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL ); INSERT INTO users (name) VALUES ('Alice'), ('Bob');
The POSTGRES_URL environment variable is crucial. @vercel/postgres reads this and automatically configures itself to connect to your Neon database. When Next.js Server Components execute, they trigger sql queries. @vercel/postgres then establishes a connection to Neon using the provided URL, executes the query, and closes the connection. Neon’s serverless architecture handles the scaling of these connections efficiently.
The primary benefit is cost and performance. You only pay for the compute you use when your database is actively being queried. This is a stark contrast to traditional database hosting where you pay for provisioned capacity, often with many idle connections. For applications with spiky traffic patterns, this can lead to significant savings. Furthermore, because the database scales connections automatically, you avoid the operational overhead of managing connection pools on your application servers.
One aspect that trips people up is understanding how @vercel/postgres interacts with Neon’s serverless nature. It’s not a traditional connection pooler managed by your Next.js app. Instead, @vercel/postgres acts as a lightweight client that delegates connection management to Neon. When sql is called, it requests a connection from Neon’s infrastructure. Neon then spins up a compute branch (if necessary) and provides a connection for that specific query. This ephemeral connection model is key to the cost-effectiveness of serverless databases.
The next step is often integrating mutations (INSERT, UPDATE, DELETE) and handling potential errors gracefully within your App Router components.