Running development experiments on the same n8n instance that serves production workflows is a recipe for accidental data corruption, credential misuse, and ...
Running development experiments on the same n8n instance that serves production workflows is a recipe for accidental data corruption, credential misuse, and outages. Separate your environments so that development changes can be tested safely before reaching production.
Real-world example: A three-environment setup using n8n's environment variable support and separate credentials.
Environment configuration using n8n environment variables:
# .env file for production instance
N8N_ENVIRONMENT=production
WEBHOOK_BASE_URL=https://n8n.yourcompany.com
DB_HOST=prod-db.internal
DB_NAME=app_production
SLACK_CHANNEL=#alerts-production
# .env file for staging instance
N8N_ENVIRONMENT=staging
WEBHOOK_BASE_URL=https://n8n-staging.yourcompany.com
DB_HOST=staging-db.internal
DB_NAME=app_staging
SLACK_CHANNEL=#alerts-staging
# .env file for development instance
N8N_ENVIRONMENT=development
WEBHOOK_BASE_URL=http://localhost:5678
DB_HOST=localhost
DB_NAME=app_dev
SLACK_CHANNEL=#alerts-dev
```text
Reference environment variables in workflow nodes:
```text
// In a Postgres node connection:
Host: {{ $env.DB_HOST }}
Database: {{ $env.DB_NAME }}
// In a Webhook node URL display:
// Automatically uses WEBHOOK_BASE_URL from environment
// In a Slack node:
Channel: {{ $env.SLACK_CHANNEL }}
```text
Use a Code node to add environment context to log entries:
```javascript
return [{
json: {
...($input.first().json),
_environment: process.env.N8N_ENVIRONMENT || 'unknown',
_processed_at: new Date().toISOString()
}
}];
```text
> **Warning: Credential Isolation**
>
> Never share API credentials across environments. Create separate credentials named with environment prefixes: `Prod - Stripe API`, `Staging - Stripe API`, `Dev - Stripe API (Test Mode)`. This prevents a development workflow from accidentally charging real customers.
> **Warning: Env Access May Be Blocked**
>
> The `$env` and `process.env` references in this tip require that `N8N_BLOCK_ENV_ACCESS_IN_NODE` is not set to `true`. Many production deployments block env access for security (see [Security Tip 2](../security/index.md)). If env access is blocked, use n8n's credentials system to store configuration values, or pass them via workflow-level static data.
Promotion workflow for moving changes between environments:
```text
Development → (manual test & review) → Export workflow JSON
→ Import to Staging → (automated test suite) → Approve
→ Import to Production → (activate, monitor)
```text
Environment separation is the foundation of reliable workflow operations.
**Related:** [Always Set an Error Workflow on Every Production Workflow](../error-handling-and-reliability/01-always-set-an-error-workflow-on-every-production-workflow.md) | [Use "Pin Data" to Freeze Node Output](../testing-and-debugging/01-use-pin-data-to-freeze-node-output.md)
I build production n8n and Cloudflare automation for teams — the same engineering behind HarperFlow. Fixed-price, escrow-protected, US-based.