Keeping Data Server-Only

Access databases and secrets directly in Server Components, and use the server-only package to prevent leaks.

Syntaximport 'server-only';

Because Server Components never run in the browser, you can talk to a database or use secret API keys right inside them. That code and those secrets are never sent to the client.

Guarding sensitive modules

To be safe, mark modules that must never reach the client by importing the server-only package. If such a module is ever imported into a Client Component, the build fails with a clear error.

Example

Example · typescript
import 'server-only';
import { db } from './db';

// This function can only be used on the server.
export async function getSecretStats() {
  return db.query('SELECT count(*) FROM users');
}

When to use it

  • A developer installs the server-only package in a database utility module to get a build error if it is accidentally imported in a Client Component.
  • A payment processing module accesses a Stripe secret key directly in a Server Component, never exposing it to the browser.
  • An authentication library reads JWT secrets from process.env inside a server-only helper to prevent credential leaks.

More examples

server-only guard in a module

Importing 'server-only' causes a build-time error if the file is included in a client bundle.

Example · ts
// lib/db.ts
import 'server-only'; // build error if imported client-side
import { PrismaClient } from '@prisma/client';

export const db = new PrismaClient();

Direct secret access in Server Component

process.env secrets are available on the server but never sent to the browser in a Server Component.

Example · ts
// app/admin/page.tsx (Server Component)
import Stripe from 'stripe';

export default async function AdminPage() {
  const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
  const balance = await stripe.balance.retrieve();
  return <p>Balance: {balance.available[0].amount}</p>;
}

Environment variable separation

Only variables prefixed with NEXT_PUBLIC_ are embedded in the client bundle; all others stay server-side.

Example · bash
# .env.local
DATABASE_URL=postgres://...     # server-only
STRIPE_SECRET_KEY=sk_live_...   # server-only
NEXT_PUBLIC_STRIPE_KEY=pk_...   # safe for client (NEXT_PUBLIC_ prefix)

Discussion

  • Be the first to comment on this lesson.