Start with a clear configuration security model
An environment variable is not automatically a secret. A public site URL, analytics identifier, or feature label may safely reach the browser. Database credentials, signing keys, webhook secrets, and provider tokens must not. Classify every value by who may read it, where it is needed, and how it is rotated.
NEXT_PUBLIC_ is included in the client-side JavaScript bundle. Treat it as public information even if it originated in a protected deployment setting.Public configuration
Values needed by the browser, such as a public app URL or a publishable payment key. Keep them non-sensitive.
Server configuration
Credentials and internal endpoints used only in API routes, server rendering, background workers, and trusted build steps.
Derived configuration
Values calculated from safe inputs at runtime. Prefer these when exposing a raw credential would create unnecessary risk.
Operational metadata
Deployment environment, release version, and region labels that make logs, metrics, and incident response useful.
Use local files for development, not as a production secret store
Keep developer-specific values in .env.local and exclude it from Git. Commit a small .env.example containing names, safe placeholders, and short notes about where each value comes from. This makes onboarding repeatable without placing credentials in repository history.
# .env.example — safe to commit
NEXT_PUBLIC_APP_URL=http://localhost:3000
DATABASE_URL=replace-with-development-database-url
PAYMENT_PROVIDER_SECRET=replace-with-server-only-secret
SENTRY_DSN=replace-with-observability-dsnUse separate credentials for local development, preview deployments, staging, and production. A preview build should never be able to modify production data merely because it received the same database URL or API token.
Keep secrets behind the Next.js server boundary
Read private values only in server-side code: API routes, server-rendering functions, worker processes, and trusted integrations. Validate inputs at those boundaries, then call external services with a narrowly scoped credential. Do not pass a secret through page props, an API response, a client component, or an error message.
// pages/api/create-checkout.js
export default async function handler(req, res) {
const secret = process.env.PAYMENT_PROVIDER_SECRET;
if (!secret) return res.status(500).json({ error: "Configuration unavailable" });
// Validate and authorize req.body before using the server-only secret.
const checkout = await createCheckout(req.body, secret);
return res.status(200).json({ checkoutId: checkout.id });
}This same separation supports other production concerns. Pair server-only configuration with the Next.js authentication and RBAC practices, and keep asynchronous integrations reliable with a background-job architecture.
Operate configuration as a release dependency
Validate early, fail safely
Validate required variables during application startup or deployment checks. Report the missing key name to secure logs, not to visitors. A clear configuration failure is safer than silently falling back to a development endpoint or an empty secret.
Rotate without a rushed outage
Document each secret's owner, scope, expiry, and rotation procedure. When a provider permits it, add the replacement credential first, deploy code that accepts both during a short migration window, verify traffic, then remove the old credential. Revoke a potentially exposed credential immediately rather than waiting for a routine rotation.
Log context, never credentials
Capture the environment name, release ID, request ID, and upstream response class. Redact authorization headers, connection strings, cookies, and request bodies that may contain tokens. Good observability helps teams troubleshoot without turning logs into a second secret store. For more release hardening, use this Node.js production checklist.
Next.js secret-management checklist
✓ Every variable is classified as public, server-only, or operational metadata
✓ No secret uses the NEXT_PUBLIC_ prefix
✓ .env.local is ignored and .env.example contains only safe placeholders
✓ Local, preview, staging, and production use separate credentials
✓ Required values are validated before serving traffic
✓ API routes authorize requests before using server credentials
✓ Logs and error responses redact sensitive values
✓ Owners, expiry dates, and rotation procedures are documented
Ship a safer Next.js application
Endurance Softwares builds secure, maintainable Next.js and Node.js applications with production-ready configuration, authentication, monitoring, and deployment practices.