Tips > Building Workflows

Implement Environment Separation for Dev/Staging/Production

Running development experiments on the same n8n instance that serves production workflows is a recipe for accidental data corruption, credential misuse, and ...

TipAdvanced2 min read

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)

Want this running in your stack?

I build production n8n and Cloudflare automation for teams — the same engineering behind HarperFlow. Fixed-price, escrow-protected, US-based.