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
.envfile, but this will not contain any business logic.