Environments, config & secrets
In one line
Anything that varies between environments is config and comes from the environment at runtime; anything that would be damaging if leaked is a secret and never touches the repository.
What it is
The twelve-factor rule is a good test: could you open-source the repository right now without leaking anything? If not, credentials are in the code. Config — database URLs, feature endpoints, API keys, log levels — is injected as environment variables or fetched from a config service at boot. Not config/production.ts checked into git, which doesn't scale past a handful of environments and inevitably ends up holding a secret.
Environments typically run local → preview (per-PR ephemeral) → staging → production, though plenty of good teams collapse the middle. What matters is parity: the closer staging is to production in dependencies, data shape and topology, the more a green staging run means. Perfect parity is unaffordable, so name the deltas explicitly — smaller data, mocked third parties, one instance instead of twelve — because those deltas are exactly where staging-passes-production-fails bugs live. Per-PR preview environments have largely displaced a shared staging box for frontend work, since they remove the queue for the one environment everyone needs.
Secrets live in a manager — cloud KMS/Secrets Manager, Vault, or the platform's own store — with access scoped per service and per environment, and rotation possible without a code change. Practical rules: separate credentials per environment so a staging leak can't touch production data; short-lived credentials over static ones (OIDC federation from CI to your cloud beats a long-lived access key in a repo secret); scan for committed secrets in pre-commit and in CI; and treat any leaked secret as compromised and rotate it, because git history is forever and rewriting it doesn't help once it's been cloned.
The frontend-specific trap deserves its own sentence: anything bundled into client JavaScript is public, NEXT_PUBLIC_-prefixed or not. A key that must stay secret has to sit behind a server route or an edge function. This is one of the most common real-world leaks and a very common interview probe.
Why it matters
Config and secret handling shows up in practical rounds ("how would you deploy this?") and in security-flavoured questions. It also produces some of the most expensive real incidents — a production key committed to a public repo is a rotation scramble at best and a breach at worst.
Key points
- Config comes from the environment at runtime; the artifact is identical across environments.
- The test for secrets in code: could this repository be made public right now?
- Name the deltas between staging and production explicitly — they predict the bugs staging will miss.
- Per-PR preview environments remove contention for a single shared staging box.
- Use distinct credentials per environment so a staging compromise can't reach production.
- Prefer short-lived federated credentials (OIDC from CI) over long-lived static keys.
- Anything shipped in client JavaScript is public regardless of naming — secrets must live server-side.
- A leaked secret is compromised the moment it's pushed; rotate rather than rewriting history.