Back to Blog
Lesson 27 of the Next.js: Build Full-Stack Apps with the App Router course
Next.jsAugust 14, 20264 min read

Using Environment Variables in Next.js: A Security Guide

Learn to secure your database credentials and API keys in Next.js using .env files. Stop hardcoding secrets and master environment variable management today.

Next.jsSecurityEnvironment Variables.envWeb Development
Focused view of a computer screen displaying code and debug information.

Previously in this course, we implemented CRUD operations for comments, allowing users to interact with our database. As we move closer to production, we need to address a critical security concern: hardcoded credentials.

In our database setup with Prisma, you likely placed your database URL directly in your configuration. This is dangerous; if you push that code to a public repository, anyone can access your database. Today, we’ll secure our app by decoupling sensitive data using environment variables.

Why Use Environment Variables?

Environment variables allow your application to behave differently depending on where it’s running (e.g., local development vs. production). More importantly, they provide a place to store "secrets"—data that should never be committed to version control, such as database connection strings, API keys for third-party services, or signing secrets.

In Next.js, we use .env files to store these values. Next.js automatically loads these files into the environment for us, making them accessible via process.env.

Configuring .env Files

Close-up of two red lever arch files on a wooden desk in a modern office setting.

To start, create a file named .env.local in the root of your project. Next.js treats this file as the primary source for local environment variables.

  1. Create the file: touch .env.local
  2. Add your secrets using KEY=VALUE syntax:
Bash
# .env.local
DATABASE_URL="postgresql://user:password@localhost:5432/mydb"
STRIPE_SECRET_KEY="sk_test_51Mz..."

The Golden Rule of Security

Never commit .env files to Git.

Add .env*.local to your .gitignore file immediately. If you have already committed a file containing secrets, you must rotate those keys immediately, as they are considered compromised.

Accessing Secrets in Next.js

Because Next.js runs both on the server and the client, you must be careful where you access these variables.

Server-Side Access (Secure)

You can access any variable defined in your .env.local file inside Server Components or Server Actions. Because this code never leaves your server, your secrets stay hidden from the browser.

JAVASCRIPT
// Example: Using a secret in a Server Action
CE9178">'use server'

export async function processPayment() {
  const apiKey = process.env.STRIPE_SECRET_KEY;
  // Use the key to interact with an API...
}

Client-Side Exposure (The Prefix Rule)

By default, process.env is not available to the browser for security reasons. If you need a variable to be accessible in a Client Component (like a public API key for a map or analytics service), you must prefix it with NEXT_PUBLIC_.

Variable NameAccessible in Browser?
DATABASE_URLNo (Server only)
NEXT_PUBLIC_API_KEYYes (Client & Server)

Comparison: Server vs. Client Variables

FeatureServer VariablePublic Variable (NEXT_PUBLIC_)
Locationprocess.env.KEYprocess.env.NEXT_PUBLIC_KEY
SecurityOpaque to clientVisible in browser source
Use CaseDatabase URLs, API SecretsPublic keys, site URLs

Hands-on Exercise: Protect Your Prisma URL

  1. Open your .env file (where you previously stored the database URL).
  2. Ensure the DATABASE_URL is moved to .env.local.
  3. Update your .gitignore to include .env.local if it isn't already there.
  4. Verify your app still works by restarting the development server.

If you want to ensure your environment variables are valid at runtime, consider using TypeScript Environment Variables: Validating Process.env with Zod to catch missing keys during development rather than production crashes.

Common Pitfalls

  • Caching Issues: If you add a new variable while the server is running, you must stop and restart the development server for Next.js to pick up the change.
  • Leaking Secrets: Accidentally using the NEXT_PUBLIC_ prefix for a secret key. If you can see it in the Network tab of your browser DevTools, it’s not a secret anymore.
  • Deployment Confusion: Remember that .env.local is for your machine. When you deploy to a platform like Vercel, you must set these variables in their Dashboard UI or via their CLI, as files are not uploaded to the production server. For advanced workflows, you might look into Environment-Specific Secrets: Mastering Secure CI/CD Deployments to handle different keys across environments.

FAQ

Q: Can I use multiple .env files? A: Yes. Next.js loads files in a specific order. .env.local always overrides others.

Q: How do I share environment variables with teammates? A: Create a file named .env.example. Populate it with the keys but empty values (e.g., DATABASE_URL=). Commit this to Git so your team knows which variables they need to set up locally.

Q: Is process.env typed? A: By default, it is typed as string | undefined. We will explore how to make this type-safe in future lessons.

Recap

We’ve learned that environment variables are the standard way to handle sensitive configuration. We use .env.local for local development, keep secrets off the client by avoiding the NEXT_PUBLIC_ prefix, and always ensure .env.local is ignored by Git to maintain high security standards.

Up next: We will learn how to optimize our media assets using the next/image component to improve performance.

Similar Posts