dotenv Advanced Techniques in Node.js Variables Expansion, Validation, and Type Casting
Learn advanced dotenv techniques for Node.js variable expansion, schema validation, type casting, and using dotenv-flow for multiple environments.
dotenv Advanced Techniques in Node.js
Beyond basic dotenv usage, there are advanced features for better environment variable management.
1. Variable Expansion
npm install dotenv
# .env BASE_URL=https://api.yourdomain.com API_URL=${BASE_URL}/api/v1 SOCKET_URL=${BASE_URL}/socket
require("dotenv").config(); console.log(process.env.API_URL); // https://api.yourdomain.com/api/v1 console.log(process.env.SOCKET_URL); // https://api.yourdomain.com/socket
Variable expansion lets you reference other variables with ${VAR_NAME}.
2. Type Casting
Environment variables are always strings. Cast them to the right type:
const config = { port: parseInt(process.env.PORT, 10) || 3000, isProduction: process.env.NODE_ENV === "production", maxConnections: parseInt(process.env.MAX_CONNECTIONS, 10) || 100, enableCache: process.env.ENABLE_CACHE === "true", allowedOrigins: process.env.ALLOWED_ORIGINS?.split(",") || [], timeout: Number(process.env.TIMEOUT) || 5000 };
3. Schema Validation with envalid
npm install envalid
const { cleanEnv, str, num, bool, email, url } = require("envalid"); const env = cleanEnv(process.env, { NODE_ENV: str({ choices: ["development", "staging", "production"] }), PORT: num({ default: 3000 }), MONGODB_URI: str({ format: "url" }), JWT_SECRET: str({ minLength: 32 }), CLIENT_URL: url(), ENABLE_CACHE: bool({ default: false }), LOG_LEVEL: str({ choices: ["error", "warn", "info", "debug"], default: "info" }) }); // envalid validates, type-casts, and provides defaults // It throws an error at startup if validation fails console.log(env.PORT); // 3000 (number, not string) console.log(env.NODE_ENV); // "development" (validated)
4. dotenv-flow for Multiple Environments
npm install dotenv-flow
require("dotenv-flow").config();
dotenv-flow automatically loads:
.env(base config).env.local(local overrides, not committed).env.${NODE_ENV}(environment-specific).env.${NODE_ENV}.local(environment-specific local)
Priority: Later files override earlier ones.
5. Environment-Specific Configuration
// src/config/index.js const env = require("dotenv-flow").config(); const { cleanEnv, str, num, bool } = require("envalid"); const config = cleanEnv(process.env, { NODE_ENV: str({ choices: ["development", "staging", "production"] }), PORT: num({ default: 3000 }), MONGODB_URI: str(), JWT_SECRET: str({ minLength: 32 }), CLIENT_URL: str(), // SES SES_HOST: str(), SES_PORT: num({ default: 587 }), SES_USER: str(), SES_PASS: str(), SES_FROM: str(), // Feature flags ENABLE_EMAILS: bool({ default: false }), ENABLE_CHAT: bool({ default: true }), // Limits RATE_LIMIT_MAX: num({ default: 100 }), RATE_LIMIT_WINDOW: num({ default: 15 * 60 * 1000 }) }); module.exports = config;
6. Feature Flags
Use environment variables as feature flags:
# .env ENABLE_EMAILS=true ENABLE_CHAT=true ENABLE_RATE_LIMITING=true ENABLE_SWAGGER=false
// Conditional middleware if (config.ENABLE_RATE_LIMITING) { const rateLimit = require("express-rate-limit"); app.use(rateLimit({ max: config.RATE_LIMIT_MAX, windowMs: config.RATE_LIMIT_WINDOW })); } // Conditional routes if (config.ENABLE_SWAGGER) { const swaggerUi = require("swagger-ui-express"); app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(specs)); } // Conditional email sending if (config.ENABLE_EMAILS) { await sendEmail(user.email, "welcome", { firstName: user.firstName }); }
7. Secrets in Docker
For Docker deployments, pass environment variables at runtime:
# docker run docker run -e MONGODB_URI=$MONGODB_URI -e JWT_SECRET=$JWT_SECRET my-app # docker-compose.yml services: api: image: devtinder-api environment: - MONGODB_URI - JWT_SECRET env_file: - .env.production
8. CI/CD Secrets
In GitHub Actions, use secrets:
# .github/workflows/deploy.yml jobs: deploy: runs-on: ubuntu-latest steps: - name: Deploy uses: appleboy/[email protected] with: host: ${{ secrets.EC2_HOST }} key: ${{ secrets.EC2_SSH_KEY }} script: | echo "MONGODB_URI=${{ secrets.MONGODB_URI }}" > /home/ubuntu/devtinder-backend/.env echo "JWT_SECRET=${{ secrets.JWT_SECRET }}" >> .env
The Takeaway
Advanced dotenv techniques include: variable expansion (${VAR}), type casting (parseInt, Boolean, split), schema validation with envalid (validates, type-casts, provides defaults), dotenv-flow for multiple environments (automatic file loading by NODE_ENV), feature flags (enable/disable features via env vars), Docker env vars, and CI/CD secrets. Use envalid for production-grade validation.
Use ${VAR_NAME} syntax. For example, BASE_URL=https://api.yourdomain.com and API_URL=${BASE_URL}/api/v1. When dotenv loads, API_URL becomes https://api.yourdomain.com/api/v1. This avoids duplication.
Use the envalid package. Define a schema with types (str, num, bool, url, email), choices, defaults, and minLength. cleanEnv validates all variables, type-casts them, provides defaults, and throws an error at startup if validation fails.
dotenv-flow automatically loads multiple .env files based on NODE_ENV: .env (base), .env.local (local overrides), .env.${NODE_ENV} (environment-specific), and .env.${NODE_ENV}.local. Later files override earlier ones, providing flexible environment management.
Set boolean env vars like ENABLE_EMAILS=true, ENABLE_CHAT=true. In code, check if (config.ENABLE_EMAILS) before sending emails. This lets you enable/disable features without code changes useful for staging testing and gradual rollouts.
Pass at runtime with docker run -e VAR=value, or use env_file in docker-compose.yml to load from a .env file. Never bake secrets into the Docker image. Use Docker secrets or AWS Secrets Manager for production.
Ready to master Node.js completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.
Master Node.js
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course.

