Next.js App Router Best Practices

Chapter 1 · Practice 4 of 5

Import server-only in modules that touch secrets or the database

From Server and Client Components

Why it matters

A Client Component that accidentally imports your database helper would try to bundle it for the browser, along with any environment variables it reads. One import line turns that mistake into a build error.

  • Add import 'server-only' at the top of modules that must never run on the client. The build then fails with a clear error if client code imports them.
  • Only variables prefixed with NEXT_PUBLIC_ are exposed to the browser, and their values are inlined at build time.
  • Keep every secret unprefixed, and read process.env only inside your server-only data layer.

Example

TypeScript
// lib/db.ts
import 'server-only';
import { Pool } from 'pg';

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