n8n Environment Variables: Complete Configuration Reference
n8n Environment Variables: Complete Configuration Reference
• Logic Workflow Team

n8n Environment Variables: Complete Configuration Reference

#n8n #environment variables #configuration #self-hosting #DevOps #tutorial

One missing environment variable can destroy your entire n8n deployment. Credentials become unreadable. Webhooks stop receiving data. Workflows silently fail. And you won’t know something is wrong until a client asks why their automation hasn’t run in three days.

The n8n community forums are filled with these stories. Someone migrates their instance, forgets to set the encryption key, and suddenly every credential shows “could not be decrypted.” Another user deploys behind a reverse proxy, skips the webhook URL configuration, and spends hours debugging why external services can’t reach their workflows.

Configuration mistakes are the silent killer of self-hosted n8n deployments.

The Silent Killer of n8n Deployments

Most n8n guides focus on getting the application running. They show you the basic Docker command, maybe a simple docker-compose file, and call it a day. You see the n8n interface, create a workflow, and assume everything works.

But production readiness requires much more. Environment variables control everything from how n8n encrypts your credentials to how many workflows can run simultaneously. Miss a critical setting, and your “working” deployment becomes a liability.

The worst part? Many configuration problems don’t surface immediately. Your encryption key might auto-generate on first launch, work perfectly for months, then disappear after a container restart. Your webhooks might function in testing but fail in production because the URL doesn’t match your domain.

What Most Guides Get Wrong

Documentation tends to list environment variables alphabetically without context. You see N8N_BASIC_AUTH_ACTIVE next to N8N_ENCRYPTION_KEY with no indication that one is deprecated and the other is absolutely critical.

This guide organizes variables by what they actually do, explains when you need them, and shows you real configurations that work in production. We’ll cover the mistakes we’ve seen across dozens of n8n deployments and how to avoid them.

What You’ll Learn

  • How n8n’s configuration system works, including the _FILE suffix for secrets
  • Essential variables every deployment needs from day one
  • Security settings that protect your credentials and data
  • Database configuration for production-grade persistence
  • Performance tuning to handle high workflow volumes
  • Queue mode setup for scaling across multiple workers
  • Logging and monitoring for operational visibility
  • Complete production configurations you can copy and adapt
  • Troubleshooting the most common configuration problems

How n8n Configuration Works

Before diving into specific variables, understand how n8n reads configuration. This knowledge helps you debug issues and organize your settings properly.

Configuration Methods

n8n accepts configuration through three methods, listed in order of precedence:

  1. Environment variables (highest priority)
  2. Configuration file (config file in n8n directory)
  3. Default values (lowest priority)

Environment variables override everything else. This makes them ideal for Docker deployments where you define settings in docker-compose files or container orchestration platforms.

Setting variables in Bash:

export N8N_HOST=n8n.example.com
export N8N_PORT=5678

Setting variables in Docker Compose:

services:
  n8n:
    environment:
      - N8N_HOST=n8n.example.com
      - N8N_PORT=5678

Setting variables in Docker run:

docker run -it --rm \
  -e N8N_HOST=n8n.example.com \
  -e N8N_PORT=5678 \
  docker.n8n.io/n8nio/n8n

The _FILE Suffix for Secrets

For sensitive values like database passwords and encryption keys, n8n supports loading values from files instead of environment variables directly. Append _FILE to the variable name and provide a file path.

# Instead of this (exposes password in environment)
DB_POSTGRESDB_PASSWORD=my_secret_password

# Use this (reads password from file)
DB_POSTGRESDB_PASSWORD_FILE=/run/secrets/db_password

This pattern integrates with Docker secrets and Kubernetes secrets, keeping sensitive data out of your environment variable listings and container inspection output.

Proxy Variable Handling

n8n uses the proxy-from-env package for proxy configuration. This creates a specific precedence rule: lowercase proxy variables take priority over uppercase versions.

If you set both http_proxy and HTTP_PROXY, the lowercase version wins. Keep this in mind when debugging connectivity issues in corporate environments.

Essential Variables for Every Deployment

These variables define how n8n identifies itself and communicates with the outside world. Configure them correctly from the start.

Core Identity Settings

VariableDescriptionExample
N8N_HOSTThe hostname where n8n is accessiblen8n.example.com
N8N_PORTPort n8n listens on internally5678
N8N_PROTOCOLProtocol for generated URLshttps
GENERIC_TIMEZONEDefault timezone for schedulesAmerica/New_York

N8N_HOST determines the hostname in generated URLs. Set this to your actual domain, not localhost, when deploying to a server.

N8N_PROTOCOL affects URL generation throughout the application. If you’re running behind a reverse proxy with SSL termination, set this to https even though n8n itself might listen on HTTP internally.

Webhook Configuration

Webhooks are how external services trigger your workflows. Misconfigure these, and your integrations break silently.

VariableDescriptionExample
WEBHOOK_URLPublic URL for webhook endpointshttps://n8n.example.com/
N8N_PROXY_HOPSNumber of reverse proxies in front of n8n1

WEBHOOK_URL is critical. This URL appears in webhook configuration screens and gets sent to external services. If it doesn’t match your actual public URL, webhooks won’t reach your instance.

# Behind a reverse proxy with SSL
export WEBHOOK_URL=https://n8n.example.com/
export N8N_PROXY_HOPS=1

N8N_PROXY_HOPS tells n8n how many reverse proxies sit between it and the internet. This ensures n8n reads the correct client IP from forwarded headers. Set to 1 for a single proxy (like Nginx or Traefik), 2 if you have a CDN in front of your proxy, and so on.

For detailed webhook security practices, see our webhook security guide.

Security Configuration

Security variables protect your credentials, control access, and prevent unauthorized code execution. Get these wrong, and you risk exposing sensitive data.

N8N_ENCRYPTION_KEY: The Most Critical Variable

This single variable causes more support requests than any other.

n8n encrypts credentials (API keys, passwords, OAuth tokens) before storing them in the database. The encryption key controls this process.

What happens if you don’t set it:

  1. n8n auto-generates a random key on first launch
  2. This key gets stored in the .n8n folder
  3. If the container restarts and that folder isn’t persisted, the key changes
  4. All existing credentials become unreadable
  5. You see: “Credentials could not be decrypted”

The fix:

Always set N8N_ENCRYPTION_KEY explicitly:

# Generate a secure 32-character key
openssl rand -hex 32

# Set it in your environment
export N8N_ENCRYPTION_KEY=your-generated-64-character-hex-string

Queue mode requirement: When running n8n in queue mode with separate workers, every instance (main and workers) must use the exact same encryption key. Workers need to decrypt credentials to execute workflows.

# docker-compose.yml for queue mode
services:
  n8n-main:
    environment:
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}

  n8n-worker:
    environment:
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}  # Must match!

Store your encryption key securely. Use a secrets manager, keep it in a password vault, back it up somewhere safe. Losing this key means re-creating every credential in your instance.

Code Execution Security

By default, Code nodes in n8n can access environment variables. This creates a security risk if untrusted users can create or modify workflows.

VariableDescriptionDefault
N8N_BLOCK_ENV_ACCESS_IN_NODEPrevent Code nodes from reading env varsfalse
NODES_EXCLUDEJSON array of nodes to completely disable[]

Block environment access:

export N8N_BLOCK_ENV_ACCESS_IN_NODE=true

Disable dangerous nodes entirely:

export NODES_EXCLUDE='["n8n-nodes-base.executeCommand", "n8n-nodes-base.readWriteFile"]'

This blocks the Execute Command and Read/Write Files nodes, preventing workflows from running arbitrary shell commands or accessing the filesystem.

For web-based authentication, configure cookie security appropriately:

VariableDescriptionProduction Value
N8N_SECURE_COOKIERequire HTTPS for cookiestrue
N8N_SAMESITE_COOKIESameSite cookie policylax

Set N8N_SECURE_COOKIE=true when running with HTTPS. This prevents session cookies from being sent over unencrypted connections.

Disabling Telemetry and Templates

n8n collects anonymous usage data by default. For privacy-sensitive deployments:

VariableDescriptionDefault
N8N_DIAGNOSTICS_ENABLEDSend anonymous usage datatrue
N8N_VERSION_NOTIFICATIONS_ENABLEDCheck for updatestrue
N8N_TEMPLATES_ENABLEDShow workflow templatestrue
# Disable all telemetry
export N8N_DIAGNOSTICS_ENABLED=false
export N8N_VERSION_NOTIFICATIONS_ENABLED=false
export N8N_TEMPLATES_ENABLED=false

Disabling templates removes the template gallery from the UI. This is useful in air-gapped environments or when you want users to only work with internally-approved workflows.

External Storage for Binary Data

When processing files (images, PDFs, spreadsheets), n8n stores binary data. In queue mode with multiple workers, each worker needs access to this data. Configure S3-compatible storage:

VariableDescription
N8N_AVAILABLE_BINARY_DATA_MODESAvailable storage modes
N8N_DEFAULT_BINARY_DATA_MODEDefault storage mode
N8N_EXTERNAL_STORAGE_S3_HOSTS3 endpoint hostname
N8N_EXTERNAL_STORAGE_S3_BUCKET_NAMES3 bucket name
N8N_EXTERNAL_STORAGE_S3_BUCKET_REGIONS3 region
N8N_EXTERNAL_STORAGE_S3_ACCESS_KEYS3 access key
N8N_EXTERNAL_STORAGE_S3_ACCESS_SECRETS3 secret key
export N8N_AVAILABLE_BINARY_DATA_MODES=filesystem,s3
export N8N_DEFAULT_BINARY_DATA_MODE=s3
export N8N_EXTERNAL_STORAGE_S3_HOST=s3.amazonaws.com
export N8N_EXTERNAL_STORAGE_S3_BUCKET_NAME=my-n8n-binary-data
export N8N_EXTERNAL_STORAGE_S3_BUCKET_REGION=us-east-1
export N8N_EXTERNAL_STORAGE_S3_ACCESS_KEY=${AWS_ACCESS_KEY}
export N8N_EXTERNAL_STORAGE_S3_ACCESS_SECRET=${AWS_SECRET_KEY}

This works with AWS S3, DigitalOcean Spaces, MinIO, and any S3-compatible storage provider. Without shared storage, workers in queue mode cannot access binary data created by other workers, causing workflow failures.

Database Configuration

Production n8n deployments require PostgreSQL. SQLite works for testing but fails under concurrent load and lacks proper backup capabilities. See our guide on common self-hosting mistakes for why this matters.

PostgreSQL Connection

VariableDescriptionExample
DB_TYPEDatabase typepostgresdb
DB_POSTGRESDB_HOSTPostgreSQL server hostnamepostgres
DB_POSTGRESDB_PORTPostgreSQL port5432
DB_POSTGRESDB_DATABASEDatabase namen8n
DB_POSTGRESDB_USERDatabase usernamen8n_user
DB_POSTGRESDB_PASSWORDDatabase passwordUse _FILE suffix
DB_POSTGRESDB_SCHEMADatabase schemapublic

Complete PostgreSQL configuration:

export DB_TYPE=postgresdb
export DB_POSTGRESDB_HOST=postgres
export DB_POSTGRESDB_PORT=5432
export DB_POSTGRESDB_DATABASE=n8n
export DB_POSTGRESDB_USER=n8n
export DB_POSTGRESDB_PASSWORD_FILE=/run/secrets/db_password
export DB_POSTGRESDB_SCHEMA=n8n

SSL Configuration

For secure database connections (required by most managed PostgreSQL services):

VariableDescription
DB_POSTGRESDB_SSL_CAPath to CA certificate file
DB_POSTGRESDB_SSL_CERTPath to client certificate
DB_POSTGRESDB_SSL_KEYPath to client key
DB_POSTGRESDB_SSL_REJECT_UNAUTHORIZEDReject unauthorized certificates
# For managed PostgreSQL with SSL
export DB_POSTGRESDB_SSL_CA=/path/to/ca-certificate.crt
export DB_POSTGRESDB_SSL_REJECT_UNAUTHORIZED=true

For a complete PostgreSQL setup tutorial, see our n8n PostgreSQL guide.

Connection Pooling Considerations

When running multiple n8n instances (main plus workers), database connections multiply quickly. Each worker maintains its own connection pool. With 5 workers at the default settings, you might have 50+ connections to PostgreSQL.

Monitor your database connection count and adjust PostgreSQL’s max_connections setting accordingly. For managed database services, check your plan’s connection limits.

Some teams place PgBouncer between n8n and PostgreSQL to manage connection pooling more efficiently. This adds complexity but helps at scale.

Execution and Performance

These variables control how n8n handles workflow executions, manages resources, and maintains performance under load.

Execution Mode

VariableDescriptionOptions
EXECUTIONS_MODEHow workflows are executedregular, queue

Regular mode (default): The main n8n process handles everything. Simple but doesn’t scale.

Queue mode: Executions are distributed to worker processes via Redis. Required for high-volume deployments. See our queue mode guide for complete setup instructions.

# Enable queue mode
export EXECUTIONS_MODE=queue

Execution Data Management

Execution history accumulates quickly. Without pruning, your database grows indefinitely and queries slow down.

VariableDescriptionDefault
EXECUTIONS_DATA_PRUNEAuto-delete old executionsfalse
EXECUTIONS_DATA_MAX_AGEHours before pruning336 (14 days)
EXECUTIONS_DATA_PRUNE_MAX_COUNTMaximum executions to keep10000
EXECUTIONS_DATA_SAVE_ON_ERRORSave failed executionsall
EXECUTIONS_DATA_SAVE_ON_SUCCESSSave successful executionsall
EXECUTIONS_DATA_SAVE_ON_PROGRESSSave in-progress datafalse
EXECUTIONS_DATA_SAVE_MANUAL_EXECUTIONSSave manual test runstrue

Production pruning configuration:

environment:
  - EXECUTIONS_DATA_PRUNE=true
  - EXECUTIONS_DATA_MAX_AGE=168  # 7 days
  - EXECUTIONS_DATA_PRUNE_MAX_COUNT=50000
  - EXECUTIONS_DATA_SAVE_ON_ERROR=all
  - EXECUTIONS_DATA_SAVE_ON_SUCCESS=none  # Save storage
  - EXECUTIONS_DATA_SAVE_MANUAL_EXECUTIONS=true

Setting EXECUTIONS_DATA_SAVE_ON_SUCCESS=none significantly reduces database size while preserving failed executions for debugging.

Concurrency Control

VariableDescriptionDefault
N8N_CONCURRENCY_PRODUCTION_LIMITMax simultaneous executions-1 (unlimited)
EXECUTIONS_TIMEOUTWorkflow timeout in seconds3600
EXECUTIONS_TIMEOUT_MAXMaximum allowed timeout3600

Prevent resource exhaustion:

# Limit to 20 concurrent executions
export N8N_CONCURRENCY_PRODUCTION_LIMIT=20

# 30-minute timeout per workflow
export EXECUTIONS_TIMEOUT=1800

For timeout configuration details, see our timeout troubleshooting guide.

Memory Configuration

Node.js has a default memory limit that can cause crashes during heavy operations. Increase it for production:

export NODE_OPTIONS=--max-old-space-size=2048  # 2GB heap

For workflows processing large files or datasets, consider 4096 (4GB) or higher.

VariableDescriptionDefault
N8N_PAYLOAD_SIZE_MAXMaximum request body size in MB16
N8N_RUNNERS_ENABLEDEnable task runners for isolationfalse

Scaling and Queue Mode Variables

When regular mode can’t handle your volume, queue mode distributes work across multiple processes. This requires Redis and additional configuration.

Redis Connection

VariableDescriptionExample
QUEUE_BULL_REDIS_HOSTRedis server hostnameredis
QUEUE_BULL_REDIS_PORTRedis port6379
QUEUE_BULL_REDIS_PASSWORDRedis passwordUse _FILE suffix
QUEUE_BULL_REDIS_DBRedis database number0
export QUEUE_BULL_REDIS_HOST=redis
export QUEUE_BULL_REDIS_PORT=6379
export QUEUE_BULL_REDIS_PASSWORD_FILE=/run/secrets/redis_password

Worker Configuration

Workers are separate n8n processes that execute workflows from the queue.

VariableDescriptionDefault
QUEUE_WORKER_CONCURRENCYExecutions per worker10
QUEUE_HEALTH_CHECK_ACTIVEEnable worker health checksfalse
QUEUE_HEALTH_CHECK_PORTHealth check endpoint port5678

Start a worker:

# Workers need the same encryption key and database config
export N8N_ENCRYPTION_KEY=${MAIN_ENCRYPTION_KEY}
export EXECUTIONS_MODE=queue
export QUEUE_WORKER_CONCURRENCY=10

n8n worker

In Docker Compose:

n8n-worker:
  image: docker.n8n.io/n8nio/n8n
  command: worker
  environment:
    - EXECUTIONS_MODE=queue
    - QUEUE_BULL_REDIS_HOST=redis
    - QUEUE_WORKER_CONCURRENCY=10
    - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
    # ... database variables ...

For scaling strategies and auto-scaling configuration, see our queue mode guide.

Logging and Monitoring

Production deployments need visibility into what’s happening. Configure logging appropriately.

Log Configuration

VariableDescriptionOptions
N8N_LOG_LEVELVerbosity levelerror, warn, info, debug
N8N_LOG_OUTPUTOutput destinationsconsole, file
N8N_LOG_FILE_LOCATIONLog file path/var/log/n8n/n8n.log
N8N_LOG_FILE_SIZE_MAXMax file size in MB50
N8N_LOG_FILE_COUNT_MAXMax log files to keep60

Production logging setup:

export N8N_LOG_LEVEL=info
export N8N_LOG_OUTPUT=console,file
export N8N_LOG_FILE_LOCATION=/var/log/n8n/n8n.log
export N8N_LOG_FILE_SIZE_MAX=50
export N8N_LOG_FILE_COUNT_MAX=30

Use debug level temporarily when troubleshooting, but switch back to info for normal operation. Debug logs are verbose and can fill disks quickly.

Prometheus Metrics

For monitoring dashboards and alerting:

VariableDescriptionDefault
N8N_METRICSEnable metrics endpointfalse
N8N_METRICS_PREFIXMetric name prefixn8n_
N8N_METRICS_INCLUDE_DEFAULT_METRICSInclude Node.js metricstrue
N8N_METRICS_INCLUDE_QUEUE_METRICSInclude queue metricsfalse
export N8N_METRICS=true
export N8N_METRICS_INCLUDE_DEFAULT_METRICS=true
export N8N_METRICS_INCLUDE_QUEUE_METRICS=true

Access metrics at http://your-n8n:5678/metrics.

Complete Production Configuration

Here’s a production-ready Docker Compose configuration incorporating everything we’ve covered.

docker-compose.yml

version: '3.8'

services:
  postgres:
    image: postgres:15
    restart: always
    environment:
      POSTGRES_USER: n8n
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: n8n
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U n8n"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    restart: always
    command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

  n8n:
    image: docker.n8n.io/n8nio/n8n:latest
    restart: always
    ports:
      - "5678:5678"
    environment:
      # Core
      - N8N_HOST=${N8N_HOST}
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - WEBHOOK_URL=https://${N8N_HOST}/
      - GENERIC_TIMEZONE=${TIMEZONE}

      # Security
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - N8N_SECURE_COOKIE=true
      - N8N_BLOCK_ENV_ACCESS_IN_NODE=true

      # Database
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_PORT=5432
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}

      # Queue Mode
      - EXECUTIONS_MODE=queue
      - QUEUE_BULL_REDIS_HOST=redis
      - QUEUE_BULL_REDIS_PORT=6379
      - QUEUE_BULL_REDIS_PASSWORD=${REDIS_PASSWORD}

      # Execution Management
      - EXECUTIONS_DATA_PRUNE=true
      - EXECUTIONS_DATA_MAX_AGE=168
      - EXECUTIONS_DATA_PRUNE_MAX_COUNT=50000
      - EXECUTIONS_DATA_SAVE_ON_ERROR=all
      - EXECUTIONS_DATA_SAVE_ON_SUCCESS=none

      # Performance
      - N8N_CONCURRENCY_PRODUCTION_LIMIT=20
      - NODE_OPTIONS=--max-old-space-size=2048

      # Logging
      - N8N_LOG_LEVEL=info
      - N8N_LOG_OUTPUT=console

      # Metrics
      - N8N_METRICS=true
      - N8N_METRICS_INCLUDE_QUEUE_METRICS=true
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy

  n8n-worker:
    image: docker.n8n.io/n8nio/n8n:latest
    restart: always
    command: worker
    environment:
      # Must match main instance
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}

      # Database
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_PORT=5432
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}

      # Queue Mode
      - EXECUTIONS_MODE=queue
      - QUEUE_BULL_REDIS_HOST=redis
      - QUEUE_BULL_REDIS_PORT=6379
      - QUEUE_BULL_REDIS_PASSWORD=${REDIS_PASSWORD}
      - QUEUE_WORKER_CONCURRENCY=10

      # Performance
      - NODE_OPTIONS=--max-old-space-size=2048
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy

volumes:
  postgres_data:
  redis_data:
  n8n_data:

Environment File (.env)

# Domain Configuration
N8N_HOST=n8n.yourdomain.com
TIMEZONE=America/New_York

# Secrets - Generate these securely!
N8N_ENCRYPTION_KEY=generate-with-openssl-rand-hex-32
POSTGRES_PASSWORD=generate-strong-password-here
REDIS_PASSWORD=generate-another-strong-password

Generate secure values:

# Encryption key (64 hex characters)
openssl rand -hex 32

# Passwords (32 characters)
openssl rand -base64 32

Production Checklist

Before going live, verify:

  • N8N_ENCRYPTION_KEY is set and backed up securely
  • WEBHOOK_URL matches your public domain
  • Database is PostgreSQL (not SQLite)
  • Database credentials use _FILE suffix or secure environment
  • N8N_SECURE_COOKIE=true (when using HTTPS)
  • Execution pruning is enabled
  • Memory limits are configured appropriately
  • Logging is enabled for debugging
  • Backups are configured for database and encryption key

For professional setup assistance, see our n8n self-hosted setup service.

Troubleshooting Common Issues

”Credentials could not be decrypted”

Cause: The N8N_ENCRYPTION_KEY changed or wasn’t set consistently.

Solution:

  1. If you have the original key, restore it in your environment
  2. If the key is lost, you must re-create all credentials manually
  3. Prevent this by always setting the key explicitly and backing it up

See our credential management guide for best practices.

Webhooks Not Receiving Data

Cause: WEBHOOK_URL misconfiguration or network issues.

Diagnostic steps:

  1. Check WEBHOOK_URL matches your public URL exactly
  2. Verify N8N_PROXY_HOPS is set correctly for your proxy setup
  3. Test the webhook URL is accessible from the internet
  4. Check firewall rules allow inbound traffic on port 443
# Test webhook accessibility
curl -I https://your-n8n-domain.com/webhook-test/test

For OAuth callback issues, see our authentication errors guide.

Memory Errors and Crashes

Cause: Node.js heap exhaustion during large data processing.

Solution:

# Increase heap size
export NODE_OPTIONS=--max-old-space-size=4096

# Reduce concurrent executions
export N8N_CONCURRENCY_PRODUCTION_LIMIT=10

Also consider splitting large workflows into sub-workflows that process data in batches.

Performance Degradation Over Time

Cause: Execution history accumulating without pruning.

Solution:

# Enable automatic pruning
export EXECUTIONS_DATA_PRUNE=true
export EXECUTIONS_DATA_MAX_AGE=168
export EXECUTIONS_DATA_PRUNE_MAX_COUNT=50000

# Stop saving successful executions (optional)
export EXECUTIONS_DATA_SAVE_ON_SUCCESS=none

For persistent performance issues, consider migrating to queue mode with dedicated workers.

Container Restarts and Lost Data

Symptom: After a container restart, settings or workflows appear missing.

Cause: Data volumes not properly mounted or persisted.

Solution:

  1. Verify volume mounts in docker-compose.yml point to persistent storage
  2. Check that the n8n data directory (/home/node/.n8n) is mounted
  3. For Kubernetes, ensure PersistentVolumeClaims are bound correctly
volumes:
  - n8n_data:/home/node/.n8n  # Critical for persistence

The .n8n folder contains the auto-generated encryption key (if not set via environment), configuration, and other state. Losing this folder without proper environment variables means losing access to credentials.

Workers Not Processing Jobs

Cause: Queue mode misconfiguration.

Checklist:

  1. Both main and workers have EXECUTIONS_MODE=queue
  2. Redis connection details are identical across all instances
  3. N8N_ENCRYPTION_KEY matches between main and workers
  4. Database connection is accessible from workers
  5. Workers are running (check with docker ps)

Use our workflow debugger tool to analyze execution patterns.

Frequently Asked Questions

What happens if I lose my N8N_ENCRYPTION_KEY?

If you lose your encryption key, all stored credentials become permanently unreadable. There is no recovery option. You must:

  1. Create a new encryption key
  2. Delete the corrupted credentials from the database
  3. Re-create every credential manually (re-authenticate OAuth connections, re-enter API keys)

This is why backing up your encryption key is critical. Store it in a password manager, secrets vault, or secure backup location separate from your database backups.


How do I migrate environment variables when updating n8n?

Environment variables don’t need migration between n8n versions. They’re external to the application. However:

  1. Before updating: Document your current configuration
  2. Keep the same encryption key: Never change N8N_ENCRYPTION_KEY during updates
  3. Use specific version tags: Instead of latest, use explicit versions like 1.67.1
  4. Test in staging first: Verify the new version works before production
# Good practice: explicit versions
image: docker.n8n.io/n8nio/n8n:1.67.1

# Risky: version could change unexpectedly
image: docker.n8n.io/n8nio/n8n:latest

Can I use different environment variables for dev and production?

Yes, and you should. Use separate .env files or environment-specific configurations:

# .env.development
N8N_HOST=localhost
N8N_PROTOCOL=http
WEBHOOK_URL=http://localhost:5678/
N8N_LOG_LEVEL=debug

# .env.production
N8N_HOST=n8n.company.com
N8N_PROTOCOL=https
WEBHOOK_URL=https://n8n.company.com/
N8N_LOG_LEVEL=info

In Docker Compose, use the --env-file flag:

docker compose --env-file .env.production up -d

Note that credentials and variable values must be set manually in each environment. n8n’s source control feature syncs workflow definitions but not secrets.


Why are my webhooks not working after deployment?

The most common causes:

  1. WEBHOOK_URL mismatch: The URL in n8n doesn’t match your public domain
  2. Missing SSL: External services often require HTTPS webhooks
  3. Firewall blocking: Inbound traffic isn’t reaching port 443
  4. Proxy misconfiguration: N8N_PROXY_HOPS isn’t set correctly

Debug by testing the webhook URL externally:

curl -X POST https://your-domain.com/webhook-test/test \
  -H "Content-Type: application/json" \
  -d '{"test": "data"}'

If this fails, the issue is network/proxy configuration. If it succeeds but external services can’t reach you, check their specific requirements (IP whitelisting, SSL certificate validation).


How do I configure n8n behind a reverse proxy?

Set these variables:

export WEBHOOK_URL=https://your-public-domain.com/
export N8N_HOST=your-public-domain.com
export N8N_PROTOCOL=https
export N8N_PROXY_HOPS=1

Configure your reverse proxy (Traefik, Nginx, Caddy) to:

  1. Forward traffic to n8n’s internal port (5678)
  2. Handle SSL termination
  3. Pass original client headers (X-Forwarded-For, X-Forwarded-Proto)

Example Nginx configuration:

server {
    listen 443 ssl;
    server_name n8n.yourdomain.com;

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    location / {
        proxy_pass http://localhost:5678;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

For complete Docker deployment with automatic SSL via Let’s Encrypt, see our Docker setup guide.


Next Steps

Proper configuration is the foundation of a reliable n8n deployment. With the right environment variables in place, you can focus on building workflows instead of debugging infrastructure.

If you’re setting up a new deployment, start with our Docker setup guide. For scaling existing installations, read the queue mode guide.

Need help configuring your n8n instance? Our consulting services include configuration audits and production optimization.


Quick Reference: Environment Variable Cheatsheet

Here’s a condensed reference of the most important variables for quick lookup.

Must-Have Variables

# Always set these explicitly
N8N_ENCRYPTION_KEY=<your-64-char-hex-key>
WEBHOOK_URL=https://your-domain.com/
N8N_HOST=your-domain.com
N8N_PROTOCOL=https
DB_TYPE=postgresdb

Production Defaults

# Recommended production settings
EXECUTIONS_DATA_PRUNE=true
EXECUTIONS_DATA_MAX_AGE=168
N8N_CONCURRENCY_PRODUCTION_LIMIT=20
NODE_OPTIONS=--max-old-space-size=2048
N8N_SECURE_COOKIE=true
N8N_BLOCK_ENV_ACCESS_IN_NODE=true
N8N_LOG_LEVEL=info

Queue Mode Essentials

# Required for queue mode
EXECUTIONS_MODE=queue
QUEUE_BULL_REDIS_HOST=redis
QUEUE_BULL_REDIS_PORT=6379
QUEUE_WORKER_CONCURRENCY=10

For the complete official reference, see the n8n environment variables documentation.

Ready to Automate Your Business?

Tell us what you need automated. We'll build it, test it, and deploy it fast.

âś“ 48-72 Hour Turnaround
âś“ Production Ready
âś“ Free Consultation
⚡

Create Your Free Account

Sign up once, use all tools free forever. We require accounts to prevent abuse and keep our tools running for everyone.

or

You're in!

Check your email for next steps.

By signing up, you agree to our Terms of Service and Privacy Policy. No spam, unsubscribe anytime.

🚀

Get Expert Help

Add your email and one of our n8n experts will reach out to help with your automation needs.

or

We'll be in touch!

One of our experts will reach out soon.

By submitting, you agree to our Terms of Service and Privacy Policy. No spam, unsubscribe anytime.