Heuristic:Confident ai Deepeval Dotenv Loading Order
| Knowledge Sources | |
|---|---|
| Domains | Infrastructure, LLM_Evaluation |
| Last Updated | 2026-02-14 10:00 GMT |
Overview
Understanding deepeval's three-layer dotenv file loading order and precedence rules to avoid unexpected configuration behavior.
Description
Deepeval automatically loads environment variables from dotenv files on import, following a specific order: `.env` first, then `.env.<APP_ENV>` (if `APP_ENV` is set), then `.env.local`. Critically, later files do NOT override earlier values; the first value wins. This is the opposite of what many developers expect. Process environment variables have the highest precedence (they are never overwritten by dotenv loading). The legacy `.deepeval/.deepeval` JSON keystore has the lowest precedence.
Usage
Apply this heuristic when debugging configuration issues where environment variables are not picking up expected values, when setting up multi-environment configurations (dev/staging/production), or when overriding defaults for testing.
The Insight (Rule of Thumb)
- Action: Place base configuration in `.env`, environment-specific overrides in `.env.<APP_ENV>`, and local developer overrides in `.env.local`. Remember: first value wins among dotenv files.
- Value: Loading order is `.env` -> `.env.<APP_ENV>` -> `.env.local` -> legacy keyfile. Process env vars always take highest precedence.
- Trade-off: The "first value wins" behavior means `.env` values cannot be overridden by `.env.local`. To override, remove the key from `.env` or set it as a process environment variable.
- Configuration flags:
- `DEEPEVAL_DISABLE_DOTENV=1`: Skip all dotenv loading (useful in CI/CD)
- `ENV_DIR_PATH=/path/to/dir`: Custom directory for dotenv files
- `APP_ENV=production`: Select environment-specific dotenv file
Reasoning
The "first value wins" approach matches the `python-dotenv` library's default behavior with `override=False`. It ensures that process environment variables (set by CI/CD, Docker, or shell) always take precedence. The `.env` file serves as the base config, and more specific files layer on top only for keys not yet defined.
Dotenv loading implementation from `deepeval/config/settings.py` docstring:
Autoloads dotenv files into os.environ without overwriting existing vars
(order: .env -> .env.{APP_ENV} -> .env.local).
IMPORTANT comment from `deepeval/__init__.py:8`:
# IMPORTANT: load environment variables before other imports
from deepeval.config.settings import autoload_dotenv, get_settings
autoload_dotenv()
Disable dotenv flag from `deepeval/config/settings.py:203`:
if parse_bool(os.getenv("DEEPEVAL_DISABLE_DOTENV"), default=False):
return
Custom env dir from `deepeval/config/settings.py:206`:
raw_dir = os.getenv("ENV_DIR_PATH")
APP_ENV discovery from `deepeval/config/settings.py:218`:
os.getenv("APP_ENV") or _discover_app_env_from_files(env_dir) or None
Precedence chain:
Process env (highest) > .env > .env.<APP_ENV> > .env.local > .deepeval/.deepeval JSON (lowest)