Environment Variables
How environment variables work on mctx. Server-level and version-level variables, encryption, runtime injection, and security best practices.
Environment variables let you securely store secrets like API keys, database credentials, and configuration values. They're encrypted at rest and injected into your server at runtime.
Variable Scope
mctx supports two levels of environment variables:
| Level | Scope | Precedence | Use Case |
|---|---|---|---|
| Server | All versions | Lower | Shared secrets (API keys, credentials) |
| Version | Specific version | Higher | Version-specific overrides |
Precedence Rule: Version variables override server variables when keys match.
Setting Server Variables
Server-level variables apply to all deployed versions:
- Navigate to server detail page (
/dev/servers/[id]) - Scroll to Server Environment Variables
- Enter variable key (e.g.,
API_KEY) - Enter variable value
- Click Add
- Click Save Environment Variables
Effect: Saving triggers automatic redeployment of all active versions with new values.
Setting Version Variables
Version-specific variables override server variables:
- Navigate to server detail page
- Select version from Version History
- Scroll to Version Environment Variables
- Add variable (same process as server variables)
- Click Save Version Variables
Effect: Changes take effect on next deployment of that specific version.
Naming Rules
Variable keys must follow these constraints:
- Start with: Letter (A-Z)
- Contain only: Uppercase letters, digits, underscores
- Maximum length: 64 characters
- Case-sensitive:
API_KEYandapi_keyare different keys
Valid Examples:
API_KEYDATABASE_URLOPENAI_API_KEYMAX_RETRY_ATTEMPTSWEBHOOK_SECRET_2024
Invalid Examples:
| Invalid | Reason |
|---|---|
api_key | Lowercase not allowed |
123_KEY | Starts with number |
API-KEY | Hyphen not allowed |
my.api.key | Dot not allowed |
API_KEY_WITH_A_VERY_LONG_NAME_THAT_EXCEEDS_64_CHARACTERS | Exceeds 64 chars |
Accessing Variables in Code
Variables are available via the env parameter in your handler:
interface Env {
API_KEY: string;
DATABASE_URL: string;
MAX_RETRIES?: string; // Optional variable
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
// Access required variables
const apiKey = env.API_KEY;
const dbUrl = env.DATABASE_URL;
// Access optional variables with fallback
const maxRetries = env.MAX_RETRIES ? parseInt(env.MAX_RETRIES, 10) : 3;
// Use in external API calls
const response = await fetch("https://api.example.com/data", {
headers: {
Authorization: `Bearer ${apiKey}`,
},
});
// ...
},
};Type Safety: Define an Env interface matching your dashboard variables for TypeScript type checking.
Editing Variables
To update an existing variable:
- Find variable in the list
- Click Edit
- Enter new value
- Click Set
- Click Save Environment Variables
Effect: Saving triggers redeployment with updated values.
Note: You cannot edit the key name. To rename, delete and recreate the variable.
Deleting Variables
To remove a variable:
- Find variable in the list
- Click Delete
- Click Save Environment Variables
Effect: Variable is removed and redeployment is triggered.
Warning: Deleting a variable your code depends on will cause runtime errors. Ensure your code handles missing variables gracefully.
Security Architecture
Encryption at Rest
All environment variables are encrypted using AES-256-GCM encryption before storage:
- Algorithm: AES-256-GCM (Galois/Counter Mode)
- Implementation: WebCrypto API
- Key derivation: Platform-managed encryption key (
ENV_ENCRYPTION_KEY) - Storage: Encrypted values stored in D1 database
Decryption
Variables are decrypted only during deployment:
- Deploy worker fetches encrypted values from database
- Decrypts using platform encryption key
- Injects plaintext values into tenant worker at deploy time
- Original encrypted values remain in database
Important: After creation, variable values are never exposed in:
- Dashboard UI (shows masked values)
- API responses
- Server logs
- Error messages
Runtime Access
At runtime, your server receives plaintext variables via the env parameter. The Cloudflare Workers runtime isolates these values per-tenant.
Best Practices
Never Log Secrets
// ❌ Bad - Exposes secret in logs
console.log(`API Key: ${env.API_KEY}`);
// ✅ Good - Safe reference
console.log(`Using API key: ${env.API_KEY.slice(0, 4)}...`);Use Specific Keys
Create separate API keys per service for easier rotation and access control:
// ❌ Bad - Single key for everything
env.API_KEY;
// ✅ Good - Service-specific keys
env.OPENAI_API_KEY;
env.ANTHROPIC_API_KEY;
env.WEATHER_API_KEY;Rotate Regularly
Update secrets periodically to minimize exposure risk:
- Generate new secret in external service
- Update variable in mctx dashboard
- Wait for redeployment to complete
- Revoke old secret in external service
Minimize Scope
Only add variables you actually need. Avoid "just in case" variables.
Handle Missing Variables
Provide graceful fallbacks for optional variables:
const timeout = env.REQUEST_TIMEOUT ? parseInt(env.REQUEST_TIMEOUT, 10) : 5000; // Default 5s
if (!env.REQUIRED_API_KEY) {
return new Response("Server misconfigured", { status: 500 });
}Common Variable Examples
| Variable Name | Purpose | Example Value |
|---|---|---|
API_KEY | Generic API authentication | sk_live_xyz123... |
DATABASE_URL | Database connection string | postgres://user:pass@host/db |
OPENAI_API_KEY | OpenAI API access | sk-proj-xyz... |
ANTHROPIC_API_KEY | Anthropic API access | sk-ant-api03-xyz... |
WEBHOOK_SECRET | Webhook signature verification | whsec_xyz123... |
MAX_RETRIES | Configuration value | 3 |
TIMEOUT_MS | Configuration value | 5000 |
FEATURE_FLAG | Feature toggle | true |
Redeployment Behavior
Server Variable Changes
When you save server-level environment variable changes:
- Server status changes to Deploying
- All active versions are redeployed with new values
- Each version deployment happens sequentially
- Server status returns to Active when complete
Duration: Typically 30-60 seconds for all versions.
Version Variable Changes
Version-specific variable changes take effect on the next deployment of that version. If the version is already deployed, it triggers immediate redeployment.
Troubleshooting
Variable Not Available in Code
Symptoms: env.MY_VAR is undefined
Causes:
- Key name mismatch (case-sensitive)
- Changes not saved
- Redeployment not complete
Solutions:
- Verify key name matches exactly
- Ensure you clicked "Save Environment Variables"
- Wait for redeployment to finish (check server status)
Redeployment Failed
Symptoms: Server status stuck in Deploying or shows Error
Causes:
- Invalid variable value format
- Code doesn't handle new variable
- External service rejecting new credentials
Solutions:
- Check server logs for errors
- Verify variable value is valid for your code
- Test variable value with external service first
Version Override Not Working
Symptoms: Version still uses server-level variable
Causes:
- Version variable not saved
- Redeployment not triggered
- Wrong version selected
Solutions:
- Verify version variable was saved
- Check version history shows correct version
- Trigger manual redeployment if needed
Limits
| Limit | Value | Notes |
|---|---|---|
| Maximum variables per server | 50 | Server-level |
| Maximum variables per version | 20 | Version-level |
| Maximum key length | 64 | Characters |
| Maximum value length | 10,000 | Characters |
| Maximum total size | 100 KB | All variables combined |
Note: These limits apply per server or per version, not globally.
See Also
- mctx.json Reference - Server configuration
- Server Requirements - Using variables in code
- Server Logs - Debugging with logs
See something wrong? Report it or suggest an improvement — your feedback helps make these docs better.