Skip to main content

34. Code-Based Configuration over Environment Variables

Status: Accepted Date: 2025-07-06

Context

In the Mercury experimental framework, we need to manage a large number of complex parameters for defining trading tournaments and experiments (e.g., comparison methods, risk limits, indicator settings). Storing this complex business logic in environment variables is brittle, error-prone, and lacks type safety. It leads to "environment drift," where the behavior of the application changes based on difficult-to-track environment settings, making experiments impossible to reproduce reliably.

Decision

We will store all business logic and experimental parameters in version-controlled, type-safe TypeScript configuration files. Environment variables will be used only to specify the high-level operational mode of an instance (e.g., MERCURY_INSTANCE=R for a read-only instance), not to define business behavior. All tournament configurations will be defined as TypeScript objects that implement a strict TournamentConfig interface. This ensures that all configurations are type-checked, version-controlled with Git, and auditable.

Consequences

Positive:

  • Reproducibility & Auditability: Experiments are fully defined in code. Anyone can check out a specific commit and see the exact configuration that was used for a given experiment.
  • Type Safety: The TypeScript compiler prevents entire classes of errors by ensuring that all configuration objects adhere to the defined interfaces.
  • Reduced Complexity: Eliminates the need for complex environment variable parsing and validation logic. The configuration is just TypeScript code.
  • Version Control: All changes to experimental parameters are tracked in Git history, providing a clear audit trail.

Negative:

  • Requires Restart: Unlike environment variables, changes to configuration files require the application to be restarted to take effect. This is an intentional design choice for the experimental framework to ensure user control.
  • Less Dynamic: Configuration is less dynamic than environment variables, which can be changed without a deployment. This is a deliberate trade-off for safety and reproducibility.

Mitigation:

  • Manual Restart Control: As per adr://manual-restart-control, changes are applied only when the user deliberately restarts the application, making this a feature, not a bug, in an experimental context.
  • Clear Structure: Define clear, well-structured, and well-documented configuration interfaces to make them easy to understand and modify.
  • Environment-Specific Files: For the few things that do need to differ between environments (like database credentials), we will continue to use a separate, untracked .env file, but this will not contain any business logic.