Deployment
Environment Variables
Learn how Next.js loads environment variables, how NEXT_PUBLIC_ changes browser behavior, and how to manage runtime configuration safely.
## 1. Learning Objectives
By the end of this lesson, you will be able to load environment variables in Next.js, decide what can be exposed to the browser, avoid build-time freezing mistakes, and manage values across development, preview, and production.
Difficulty: Intermediate.
## 2. Prerequisites
- Next.js server and client components.
- Deployment basics.
- Basic security awareness.
## 3. Overview
Environment variables configure apps without hardcoding values. Next.js loads `.env*` files into `process.env`, keeps server-only variables private by default, and exposes browser variables only when they are prefixed with `NEXT_PUBLIC_`.
## 4. Why This Topic Matters
Most deployment failures involve configuration. A missing secret, a public value accidentally treated as private, or a build-time variable frozen into a promoted image can break production.
## 5. Real-World Analogy
Environment variables are like venue-specific stage notes. The script is the same, but each venue provides its own doors, lights, and security codes.
## 6. Core Concepts
| Concept | Meaning |
|---|---|
| `.env.local` | Local machine overrides, usually ignored by Git. |
| Server-only variable | Available on the server through `process.env`. |
| `NEXT_PUBLIC_` | Prefix that makes a variable available in browser bundles. |
| Build-time value | Value read and inlined during `next build`. |
| Runtime value | Value read when server code executes. |
## 7. Syntax & API Reference
## 8. Visual Diagram
## 9. Live Example - Full Working Code
What just happened? Server secrets are read lazily through functions, which avoids crashing during module evaluation in build contexts where runtime values may not exist yet.
## 10. Interactive Playground
Try this:
- Add a private variable to `.env.local`.
- Read it in a Route Handler.
- Add a `NEXT_PUBLIC_` variable and read it in a Client Component.
- Change the public value after build and observe why it does not change.
## 11. Common Mistakes
| Mistake | Why It Happens | Correct Approach |
|---|---|---|
| Committing `.env.local` | It looks like normal config. | Keep local secrets ignored. |
| Exposing secrets with `NEXT_PUBLIC_` | The prefix sounds like a naming convention only. | Use it only for values safe for the browser. |
| Expecting public vars to change at runtime | The app was built once. | Rebuild or serve runtime config through an API. |
| Initializing SDKs at module scope | Imports run during build. | Lazily initialize clients inside getter functions. |
## 12. Best Practices
- Keep secrets server-only.
- Use `NEXT_PUBLIC_` only for non-sensitive browser values.
- Validate required variables early in server execution.
- Separate development, preview, and production values.
- Avoid module-scope initialization for env-dependent clients.
## 13. Browser Compatibility
| Feature | Browser Impact | Notes |
|---|---|---|
| Server-only env | None | Never shipped to browser. |
| `NEXT_PUBLIC_` env | Visible in JS | Treat as public information. |
| Runtime server env | Depends on rendering | Read in server code at request/runtime. |
## 14. Interview Questions
**Easy:** How do you expose a variable to browser JavaScript in Next.js?
Answer: Prefix it with `NEXT_PUBLIC_`.
**Medium:** Why should `.env.local` not be committed?
Answer: It often contains machine-specific secrets and credentials.
**Hard:** Why can `NEXT_PUBLIC_` variables be problematic for Docker image promotion?
Answer: They are inlined during the build, so one image promoted across environments may keep the value from the build environment.
## 15. Debugging Exercise
Bug report: "Production still uses the staging analytics ID after promotion."
Solution
The analytics ID was probably a `NEXT_PUBLIC_` variable inlined during the staging build. Rebuild for production or move environment-specific client configuration behind a runtime endpoint.
## 16. Practice Exercises
- Easy: Classify variables as public or server-only.
- Medium: Write a helper that validates required server env vars.
- Hard: Design env handling for one Docker image promoted through multiple environments.
## 17. Scenario-Based Challenge
A payment app needs `STRIPE_SECRET_KEY`, `NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY`, and `WEBHOOK_SECRET`. Which values can reach the browser?
Walkthrough
Only `NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY` should be exposed to the browser. The secret key and webhook secret must stay server-only.
## 18. Quick Quiz
1. What prefix exposes env vars to the browser? Answer: `NEXT_PUBLIC_`.
2. Are non-prefixed env vars available in Client Components? Answer: No.
3. Should `.env.local` be committed? Answer: No.
4. What phase inlines public env vars? Answer: Build time.
5. Where should production secrets live? Answer: The deployment platform or secret manager.
## 19. Summary & Key Takeaways
- Next.js loads `.env*` files into server `process.env`.
- Browser env vars require `NEXT_PUBLIC_`.
- Public env vars are build-time values.
- Secrets belong on the server and in platform secret storage.
- Lazy env access avoids build-time crashes.
## 20. Cheat Sheet
| Need | Pattern |
|---|---|
| Local private secret | `.env.local` |
| Browser-safe value | `NEXT_PUBLIC_NAME=value` |
| Server secret | `process.env.SECRET_NAME` in server code |
| Runtime Docker value | Inject when container starts |
| Required validation | Throw from a server-side env helper |
## 21. Further Reading
- Next.js Docs: Environment Variables.
- Vercel Docs: Environment Variables.
- Next.js Docs: Deploying.
## 22. Next Lesson Preview
Chapter 8 is complete. Next, you will build complete projects that combine routing, data fetching, authentication, SEO, performance, and deployment.