Skip to content

009. Sensitive Data via Environment Variables

  • Status: Accepted
  • Date: 2025-09-15

Context

In software development, sensitive information such as API keys, database connection strings, client secrets, and other credentials must be handled with extreme care. Exposing such data directly within the codebase (e.g., hardcoding them) poses significant security risks, especially when the code is version-controlled (e.g., on GitHub). Furthermore, configurations often vary between different environments (development, testing, staging, production), necessitating a flexible and secure mechanism for managing these differences without modifying the application code itself.

Decision

All sensitive data and environment-specific configurations must be injected into the application at runtime via environment variables. This decision aligns with the 12-Factor App methodology and ensures that:

  1. Sensitive credentials are never committed to the source code repository.
  2. Configuration is strictly separated from code, allowing for easy changes across environments without requiring code modifications or redeployments.
  3. The application remains portable and can be deployed consistently across various environments.

Consequences

Positive

  • Enhanced Security: Prevents accidental exposure of sensitive data in source control or build artifacts.
  • Improved Environment Management: Simplifies the process of deploying the same codebase to different environments with distinct configurations.
  • Adherence to Best Practices: Follows industry-standard security and deployment practices (e.g., 12-Factor App).
  • Increased Portability: Applications become more self-contained and easier to run in diverse environments.

Negative

  • Requires Careful Environment Setup: Deployment pipelines and local development environments must be meticulously configured to provide the necessary environment variables.
  • Potential for Misconfiguration: Incorrectly set or missing environment variables can lead to runtime errors or unexpected application behavior if not properly validated.
  • Local Development Overhead: Developers need to manage local .env files (which must be git-ignored) or set environment variables in their shell.

Specific Guidelines

To ensure consistent adherence to this decision, especially in the context of the migration to a new backend stack (as detailed in ADR-008), the following guidelines apply:

  • Never Hardcode Sensitive Values: Absolutely no sensitive information (e.g., API keys, database passwords, client secrets) should be directly written into the source code.
  • Use Environment Variables for All Configuration: All configuration that varies by environment or is sensitive should be sourced from environment variables.
  • NestJS Applications (api_gateway-ts, auth-ts):
    • Utilize the @nestjs/config package for structured and validated access to environment variables. This package automatically loads variables from .env files in development and from the system environment in production.
    • Define configuration schemas (e.g., using Joi) to validate the presence and type of required environment variables at application startup.
    • Access configuration values through the ConfigService (e.g., this.configService.get<string>('DATABASE_URL')).
  • Local Development: For local development, use .env files to define environment variables. These files must be added to .gitignore to prevent them from being committed to the repository.
  • Deployment Pipelines: Ensure CI/CD pipelines are configured to securely inject environment variables into the build and runtime environments of the deployed applications (e.g., using secrets management systems in GitHub Actions, Kubernetes Secrets, or cloud provider-specific mechanisms).