Question presented to candidate: "The same codebase needs a local database URL in development and a completely different one in production. How should that difference be represented in the code, and where should it be decided?"
What a strong answer should cover:
- The standard mechanism is
process.env.NODE_ENV(or an equivalent custom variable) selecting between environment-specific configuration values — the code itself stays identical across environments; only the values it reads differ, sourced from the actual deployment environment. - 📌 A concrete, verifiable pattern: a config-selection script correctly chose the
developmentconfig by default (whenNODE_ENVis unset), correctly switched toproductionwhen set, and threw a clear, immediate error for an unrecognized value rather than silently proceeding withundefinedconfiguration — failing loudly at startup is the correct behavior for a genuinely unrecognized environment name. - Configuration should be validated once, at startup (covered in more depth in the dedicated environment-variables question) — checking every required value is present and correctly typed before the app starts serving any traffic, rather than discovering a missing value deep inside request handling.
- Secrets (database passwords, API keys) should never be hardcoded per-environment in a config file committed to version control — they belong in actual environment variables (injected by the deployment platform, a secrets manager, or a
.envfile that is itself never committed), while non-secret structural configuration (feature flags, timeouts, non-sensitive URLs) can reasonably live in a committed config file. - A precise answer distinguishes configuration (values that differ by environment but are not secret) from secrets (values that must never appear in source control regardless of environment) — treating both identically is a common, real security mistake.
NODE_ENV=productionalso has real, automatic side effects in some frameworks/libraries beyond just an application's own config-switching logic (e.g. Express's own performance-related behavior differences) — worth knowing rather than assumingNODE_ENVis purely an application-level convention with zero built-in framework consequences.
Clarifying questions expected:
- "Is the concern non-secret configuration differences, or actual secrets management?" — these deserve genuinely different handling.
- "Does the deployment platform already inject environment-specific values, or does the app need to load them itself?" — decides how much of a custom loading mechanism is actually needed.
Code / implementation expected: Yes — the config-selection-by-NODE_ENV pattern, including the fail-loudly-on-unrecognized-value behavior, is the concrete, convincing part of the answer.