How to load environment variables
Learn environment variables management in different environments and deployment scenarios.
Local development
Using .env files
The most common way to manage environment variables during development is using .env files:
DATABASE_HOST=localhost
DATABASE_PORT=5432
NODE_ENV=development
API_KEY=your-secret-key
LOG_LEVEL=debugBest practices for .env files
-
Document required variables Create a
.env.examplefile to document required variables:.env.example DATABASE_HOST=localhost DATABASE_PORT=5432 NODE_ENV=development API_KEY=your-secret-key-here LOG_LEVEL=info -
Gitignore configuration Add these patterns to your
.gitignore:.gitignore .env .env.* !.env.example -
Environment-specific files Use different files for different environments:
.env.development- Development settings.env.test- Test environment settings.env.production- Production defaults (if needed)
Loading environment variables
Using dotenv
The simplest way to load environment variables is using the dotenv package:
import 'dotenv/config';
// or
import * as dotenv from 'dotenv';
dotenv.config();Framework-specific solutions
Many frameworks have built-in support for environment variables:
Next.js
- Automatically loads
.env*files - Supports environment-specific files (
.env.development,.env.production) - Next.js Environment Variables Documentation
Vite
- Automatically loads
.envfiles - Supports mode-specific files (
.env.development,.env.production) - Vite Env Variables Documentation
Express
import express from 'express';
import dotenv from 'dotenv';
dotenv.config();
const app = express();Nest.js
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
}),
],
})Runtime arguments
You can also supply variables when running your application:
DATABASE_HOST=localhost DATABASE_PORT=5432 npm startProduction deployment
Cloud platforms
AWS
- Use AWS Systems Manager Parameter Store for non-sensitive values
- Use AWS Secrets Manager for sensitive values
- Set environment variables in ECS Task Definitions or Lambda configurations
Google Cloud Platform
- Use Cloud Secret Manager for sensitive values
- Set environment variables in Cloud Run or App Engine configurations
Azure
- Use Azure Key Vault for sensitive values
- Configure App Settings in Azure App Service
Container environments
Docker
ENV NODE_ENV=productionservices:
app:
environment:
- NODE_ENV=production
- DATABASE_HOST=dbKubernetes
spec:
containers:
- name: app
env:
- name: NODE_ENV
value: "production"
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: database-hostTraditional hosting
- Set environment variables through the hosting platform's dashboard
- Use deployment scripts to configure environment variables
- Consider using configuration management tools
Security best practices
-
Never commit sensitive values
- Keep
.envfiles out of version control - Use secrets management services in production
- Keep
-
Use different values per environment
- Don't share sensitive credentials between environments
- Use environment-specific configurations
-
Access control
- Limit access to production environment variables
- Use role-based access control for secrets management
-
Encryption
- Encrypt sensitive values at rest
- Use secure channels for transmitting secrets
Validation and typesafety
ArkEnv helps ensure your environment variables are valid:
import from 'arkenv';
export const = ({
// Required variables with validation
: "string.host",
: "number.port",
// Boolean values (accepts "true"/"false" strings, converts to boolean)
: "boolean",
// Optional variables with defaults
: "'debug' | 'info' | 'warn' | 'error' = 'info'",
// Optional variables
"FEATURE_FLAGS?": 'string[]'
});Configuration options
ArkEnv supports several configuration options to customize its behavior:
Validator mode
Choose between ArkType (default) or Standard Schema validators:
import from 'arkenv';
import { } from 'zod';
// ArkType mode (default) - requires ArkType to be installed
const = ({
: "number.port",
: "string.host",
});
// Standard mode - works without ArkType
const = (
{
: ..().().(0).(65535),
: .().(),
},
{ : "standard" }
);Coercion
Control automatic type conversion (only available in ArkType mode):
import from 'arkenv';
// Coercion enabled (default)
const = ({
: "number.port", // "3000" becomes 3000
});
// Coercion disabled
const = (
{
: "number.port",
},
{ : false } // Must be a number; strings (like those from process.env) will fail
);Note
Since process.env values are always strings, using coerce: false with numeric or boolean schemas will cause validation to fail unless you provide a custom env source containing the expected literal types.
### Custom environment source
Provide a custom environment object:
```typescript title="src/config/env.ts" twoslash
import arkenv from 'arkenv';
const env = arkenv(
{
PORT: "number.port",
},
{
env: {
PORT: "3000",
// ... other variables
},
}
);Array format
Control how arrays are parsed (only available in ArkType mode):
import from 'arkenv';
// Comma-separated (default)
const = (
{
: "string[]",
},
{
: { : "web, app, api" },
: "comma",
}
);
// JSON format
const = (
{
: "string[]",
},
{
: { : '["web", "app"]' },
: "json",
}
);For more details on configuration options, see the coercion documentation and Standard Schema integration guide.
Common patterns
Configuration factory
Create a configuration factory to handle different environments:
import from 'arkenv';
const = () => {
const = ({
: "'development' | 'test' | 'production'",
: "string.host",
: "number.port",
});
return {
: . === 'production',
: {
: .,
: .,
}
};
};
export const = ();Feature flags
Use environment variables for feature flags:
import from 'arkenv';
export const = ({
"ENABLE_BETA_FEATURES": 'boolean = false',
"MAINTENANCE_MODE": 'boolean = false',
"ALLOWED_ORIGINS": 'string[]'
});Troubleshooting
Common issues
-
Missing variables
- Check if
.envfile exists - Verify variable names match exactly
- Ensure variables are loaded before use
- Check if
-
Type errors
- Verify variable types match schema
- Check for typos in variable names
- Ensure all required variables are provided
-
Loading order
- Load environment variables before importing config
- Consider using a bootstrap file
- Check framework-specific loading behavior