How to Manage .env Files in a Monorepo
Monorepos introduce unique challenges for environment variable management. Learn strategies that scale with your codebase while keeping configuration secure.
The Monorepo Challenge
In a monorepo, you might have multiple applications (web app, API server, admin dashboard) and shared packages (UI components, utilities, database clients). Each may need different environment variables, but some variables should be shared across all packages.
Strategy 1: Root-Level .env with Package Overrides
The simplest approach is a root .env file for shared variables, with package-specific .env files that add or override values:
Root .env
App-Specific .env
How to load: Tools like Turborepo can pass root env vars to tasks, or you can use a script that loads both files.
Strategy 2: Centralized Configuration Package
Create a shared configuration package that validates and exports environment variables with TypeScript types:
Each app imports only the env object it needs:
Benefits: Type safety, validation at startup, single source of truth for env var shapes.
Strategy 3: Turborepo Global Env
Turborepo has built-in support for global and package-specific environment variables:
globalEnv: Variables available to all tasks (affects caching)
env:Package-specific variables that affect that task's cache
Dotenv-CLI Integration
Use dotenv-cli to load .env files before running commands:
Strategy 4: Environment Layers
For complex setups, use layered configuration with clear precedence:
Create a loader utility that handles this layering:
Deployment Considerations
Vercel Monorepo Deployment
When deploying to Vercel, each app is deployed separately with its own environment variables:
- Set shared variables at the project level in Vercel
- Use different Vercel projects for different apps, or use the "Root Directory" setting
- Environment variables set in Vercel override those in .env files
CI/CD Pipelines
In CI/CD, inject environment variables at the pipeline level:
Best Practices Summary
1. Use .env.example files
Create .env.example in both root and each app to document all required variables.
2. Centralize validation
Use a shared config package with Zod or similar to validate env vars with types.
3. Keep secrets out of Git
Never commit .env.local or any file containing real credentials.
4. Document the loading order
Make it clear which files override which, and document this in your README.
5. Use platform env vars for production
Don't deploy .env files to production - use your hosting platform's secrets management.
Key Takeaways
- Use root-level .env for shared configuration across packages
- Package-specific .env files add or override shared values
- A centralized config package provides type safety and validation
- Turborepo's globalEnv and env options help manage caching correctly
- Always document your env loading order for team clarity