Last Updated: October 15, 2025
Self-hosting n8n delivers unlimited workflow executions, complete data control, and significant cost savings compared to cloud plans. But in reality, self-hosted instances face unique challenges that cloud users never encounter – specifically around large data handling and webhook configuration with reverse proxies.
In June 2025, we published two troubleshooting guides addressing these issues separately. The problem is that no comprehensive guide exists for production n8n deployments with Traefik reverse proxy that addresses both common issues together.
This guide combines both original fixes, provides complete Traefik configuration with WebSocket support, includes 2025’s new task runner requirements, and delivers production-ready docker-compose files you can deploy immediately.
Table of Contents
- Quick Diagnosis: Which Issue Do You Have?
- Understanding the Two Main Issues
- Fix #1: Execution Data Too Large Error
- Fix #2: Webhook URL Problems
- Complete Production Setup with Traefik
- 2025 Requirement: Task Runners
- Environment Variables Reference
- Docker Compose Examples
- Testing Your Setup
- Troubleshooting Common Issues
Quick Diagnosis: Which Issue Do You Have?
Symptom: “Existing execution data is too large”
You see this error when:
- Clicking “Execute Node” during workflow development
- Testing workflows with large datasets or many items
- Using partial execution mode (testing individual nodes)
- Processing complex transformations with multiple branches
You need: Fix #1: Execution Data Size
Symptom: Webhooks show incorrect URLs or fail to work
You see this when:
- Webhook URLs display with port numbers (e.g.,
:5678) - External services (Slack, GitHub, Stripe) can’t reach your webhooks
- Webhooks work in test mode but fail in production
- You’re using a reverse proxy (Nginx, Traefik, Caddy)
You need: Fix #2: Webhook URL Configuration
Symptom: Deprecation warnings about task runners
You see logs saying:
Running n8n without task runners is deprecated. Task runners will be
turned on by default in a future version.
You need: Task Runners Configuration
Symptom: You want a complete, production-ready setup
You need:
- Both fixes applied correctly
- Traefik reverse proxy with automatic HTTPS
- Production best practices and security
- Resource limits and proper monitoring
Jump to: Complete Production Setup
Understanding the Two Main Issues
Why n8n Cloud Doesn’t Have These Problems
n8n Cloud automatically handles higher memory limits for partial execution, correct webhook URLs, optimized binary data storage, and automatic updates including all new requirements. When you self-host, you’re responsible for these configurations.
The Root Causes
Issue #1: Execution Data Size Limit
The default 16MB limit for partial execution data sent to backend triggers errors when working with large datasets, many workflow branches, or complex transformations. The problem is that workflow development becomes frustrating – you can’t test individual nodes during development. The fix is straightforward: the environment variable N8N_PAYLOAD_SIZE_MAX.
Issue #2: Webhook URL Generation
n8n attempts to auto-detect your public URL, but this auto-detection fails when behind reverse proxy. External services receive incorrect webhook URLs with ports or internal hostnames – integrations break silently. The fix: the environment variable WEBHOOK_URL.
Fix #1: Execution Data Too Large Error
The Problem in Detail
When you execute just part of a workflow (clicking “Execute Node” in the editor), n8n needs to load previous execution data to provide context to that node. By default, n8n limits this data transfer to 16MB to prevent memory issues on smaller servers.
The Error Message
According to official n8n documentation:
Please execute the whole workflow, rather than just the node.
(Existing execution data is too large.)
This error appears when processing thousands of items in a single node, working with large JSON API responses, transforming big datasets with Code nodes, or using workflows with many parallel branches.
The Solution: N8N_PAYLOAD_SIZE_MAX
The fix is simple but requires understanding your server’s available resources.
Recommended Settings by Server RAM
| Server RAM | N8N_PAYLOAD_SIZE_MAX | Value in Bytes | Percentage of RAM |
|---|---|---|---|
| 2GB or less | 64MB | 67108864 | ~3% |
| 4GB | 128MB | 134217728 | ~3% |
| 8GB | 256MB | 268435456 | ~3% |
| 16GB+ | 512MB | 536870912 | ~3% |
Rule of Thumb: Use less than 20% of your available RAM to keep the system stable under load.
Docker Compose Implementation
version: '3.8'
services:
n8n:
image: n8nio/n8n:latest
container_name: n8n
restart: unless-stopped
ports:
- "5678:5678"
environment:
- N8N_PORT=5678
# Payload size fix (256MB for 8GB+ RAM servers)
- N8N_PAYLOAD_SIZE_MAX=268435456
# Binary data optimization (highly recommended)
- N8N_DEFAULT_BINARY_DATA_MODE=filesystem
- N8N_BINARY_DATA_TTL=1440 # 24 hours
volumes:
- n8n_data:/home/node/.n8n
# Resource limits (adjust based on your server)
deploy:
resources:
limits:
memory: 2G
reservations:
memory: 1G
volumes:
n8n_data:
Understanding Binary Data Mode
Default: In-Memory Storage (Not Recommended)
# This is the default - DON'T use in production
N8N_DEFAULT_BINARY_DATA_MODE=default
Problems: Stores files (images, PDFs, etc.) in RAM, wastes precious memory, not suitable for production workloads, limits how many files you can process.
From our testing: Default mode uses ~315MB RAM vs 211MB with filesystem mode – that’s ~100MB RAM saved.
Recommended: Filesystem Storage
N8N_DEFAULT_BINARY_DATA_MODE=filesystem
N8N_BINARY_DATA_TTL=1440 # Clean up after 24 hours (value in minutes)
Benefits: Stores files on disk instead of RAM, significantly better performance with large files, production-ready and recommended by n8n, automatic cleanup with TTL prevents disk bloat.
Important: If using queue mode (Redis-based distributed execution), you must keep the default binary data mode as filesystem storage is not supported with queue mode.
Real-World Impact
From our Docker testing in October 2025 with n8n version 1.115.2:
| Configuration | Memory Usage | Difference |
|---|---|---|
| Default (no fixes) | 315 MB | Baseline |
| With payload fix + filesystem mode | 211 MB | -104 MB |
Key Finding: The combination of increased payload size and filesystem binary mode actually reduces memory usage because data is handled more efficiently on disk rather than in RAM.
Fix #2: Webhook URL Problems
The Problem in Detail
When n8n generates webhook URLs to display in the editor and register with external services, it attempts to auto-detect your public URL. Behind a reverse proxy, this auto-detection fails spectacularly.
What You’ll See (The Wrong URLs)
http://n8n.yourdomain.com:5678/webhook/abc123
Problems with this URL:
- Port number included (
:5678) – external services typically can’t reach non-standard ports - Wrong protocol (http vs https) – many services require HTTPS
- Internal hostname – might be Docker container name instead of public domain
Why External Services Fail
Services like GitHub, Slack, Stripe, Zoom, Google Sheets, and hundreds of others try to send webhooks to these incorrect URLs and fail silently. You set up the integration, it looks correct in the UI, but notifications never arrive.
The Solution: WEBHOOK_URL Environment Variable
According to official n8n documentation:
“The WEBHOOK_URL environment variable is used to manually set the webhook URL so that n8n can display it in the editor UI and register the correct webhook URLs with external services. When running n8n behind a reverse proxy, it’s important to set this variable.”
Basic Configuration
environment:
- WEBHOOK_URL=https://n8n.yourdomain.com
- N8N_EDITOR_BASE_URL=https://n8n.yourdomain.com
- N8N_PROTOCOL=https
- N8N_HOST=n8n.yourdomain.com
- N8N_TRUST_PROXY_HEADER=true
- N8N_PROXY_HOPS=1
What Each Variable Does
WEBHOOK_URL (MOST IMPORTANT)
- The public URL for all webhook endpoints
- Used when registering webhooks with external services
- Must exactly match your Traefik/reverse proxy configuration
- Version note: Renamed from
WEBHOOK_TUNNEL_URLin v0.227.0, old name removed in n8n 1.0
N8N_EDITOR_BASE_URL
- The URL for accessing the n8n web interface
- Usually the same as WEBHOOK_URL
- Shows in browser address bar and email invites
N8N_PROTOCOL
- Set to
httpsfor production (with SSL/TLS) - Set to
httponly for local testing - Must match your reverse proxy termination
N8N_HOST
- Your public domain name only
- Don’t include protocol (
https://) or port - Example:
n8n.yourdomain.comnothttps://n8n.yourdomain.com:443
N8N_TRUST_PROXY_HEADER
- Must be
truewhen behind reverse proxy - Allows n8n to see real client IP addresses from proxy headers
- Required for proper request handling and security
N8N_PROXY_HOPS
- Set to
1when behind one reverse proxy - Set to
2if behind two proxies (rare) - Tells n8n how many proxy layers to trust
Testing Webhook URLs
Before the Fix
In the n8n UI, create a Webhook node and check the URL shown:
http://n8n.example.com:5678/webhook/abc123 ❌ Wrong
After the Fix
Same webhook node now displays:
https://n8n.example.com/webhook/abc123 ✅ Correct
Critical difference: External services can now reach this URL because it uses standard HTTPS port 443 (handled by your reverse proxy) instead of internal port 5678.
Complete Production Setup with Traefik
Why Traefik?
Traefik is a modern reverse proxy perfectly suited for Docker deployments – automatic HTTPS via Let’s Encrypt with no manual certificate management, service discovery that automatically detects containers via Docker labels, WebSocket support critical for n8n webhook functionality, easy configuration with just Docker labels instead of complex config files, and a built-in dashboard to monitor routing and certificates in real-time.
Architecture Overview
Internet
↓
[Traefik Reverse Proxy]
↓ HTTPS (Let's Encrypt)
↓ WebSocket Support
[n8n Container]
↓ Internal Network [PostgreSQL Database]
Critical Configuration: WebSocket Support
This is the most commonly missed configuration and causes webhook failures:
labels:
# WebSocket middleware (ABSOLUTELY REQUIRED)
- "traefik.http.middlewares.n8n-websocket.headers.customrequestheaders.Upgrade=websocket"
- "traefik.http.middlewares.n8n-websocket.headers.customrequestheaders.Connection=Upgrade"
# Apply middleware to router
- "traefik.http.routers.n8n.middlewares=n8n-websocket"
Without WebSocket headers:
- ❌ Real-time webhooks fail
- ❌ Production webhooks timeout
- ❌ External services can’t maintain persistent connections
- ❌ Integration errors appear intermittently and unpredictably
Complete Production Docker Compose
This configuration combines both fixes, includes Traefik with proper WebSocket support, and follows production best practices:
version: '3.8'
networks:
traefik-net:
external: true
n8n-internal:
internal: true
services:
# PostgreSQL Database
postgres:
image: postgres:16-alpine
container_name: n8n-postgres
restart: unless-stopped
networks:
- n8n-internal
environment:
- POSTGRES_USER=n8n
- POSTGRES_PASSWORD=${DB_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
deploy:
resources:
limits:
memory: 512M
# n8n Application
n8n:
image: n8nio/n8n:latest
container_name: n8n
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
networks:
- traefik-net
- n8n-internal
# Traefik Configuration Labels
labels:
# Enable Traefik for this container
- "traefik.enable=true"
- "traefik.docker.network=traefik-net"
# Router configuration
- "traefik.http.routers.n8n.rule=Host(`${N8N_DOMAIN}`)"
- "traefik.http.routers.n8n.entrypoints=websecure"
- "traefik.http.routers.n8n.tls.certresolver=letsencrypt"
# Service configuration
- "traefik.http.services.n8n.loadbalancer.server.port=5678"
# Middleware: Request size limit (100MB)
- "traefik.http.middlewares.n8n-buffering.buffering.maxRequestBodyBytes=104857600"
# Middleware: WebSocket support (CRITICAL - DO NOT SKIP)
- "traefik.http.middlewares.n8n-websocket.headers.customrequestheaders.Upgrade=websocket"
- "traefik.http.middlewares.n8n-websocket.headers.customrequestheaders.Connection=Upgrade"
# Middleware: Security headers
- "traefik.http.middlewares.n8n-security.headers.customResponseHeaders.X-Robots-Tag=noindex,nofollow"
- "traefik.http.middlewares.n8n-security.headers.sslProxyHeaders.X-Forwarded-Proto=https"
# Apply ALL middlewares
- "traefik.http.routers.n8n.middlewares=n8n-buffering,n8n-websocket,n8n-security"
environment:
# Database Configuration
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=n8n
- DB_POSTGRESDB_USER=n8n
- DB_POSTGRESDB_PASSWORD=${DB_PASSWORD}
# FIX #2: Webhook URL Configuration
- WEBHOOK_URL=https://${N8N_DOMAIN}
- N8N_EDITOR_BASE_URL=https://${N8N_DOMAIN}
- N8N_PROTOCOL=https
- N8N_HOST=${N8N_DOMAIN}
- N8N_PORT=5678
- N8N_TRUST_PROXY_HEADER=true
- N8N_PROXY_HOPS=1
# FIX #1: Payload Size Configuration
- N8N_PAYLOAD_SIZE_MAX=268435456 # 256MB
# Binary Data Management
- N8N_DEFAULT_BINARY_DATA_MODE=filesystem
- N8N_BINARY_DATA_TTL=1440 # 24 hours
# 2025 Requirement: Task Runners
- N8N_RUNNERS_ENABLED=true
- N8N_RUNNERS_MODE=internal
- N8N_RUNNERS_MAX_CONCURRENCY=5
# Production Optimizations
- NODE_ENV=production
- EXECUTIONS_DATA_MAX_AGE=168 # 7 days
- EXECUTIONS_DATA_PRUNE_MAX_COUNT=1000
- N8N_LOG_LEVEL=info
- N8N_LOG_OUTPUT=console
# Timezone (adjust to your location)
- GENERIC_TIMEZONE=America/New_York
- TZ=America/New_York
# Security
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
volumes:
- n8n_data:/home/node/.n8n
# Resource Limits (8GB+ RAM server)
deploy:
resources:
limits:
memory: 2G
cpus: '2.0'
reservations:
memory: 1G
cpus: '1.0'
# Health Check
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:5678/healthz"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
volumes:
n8n_data:
postgres_data:
Traefik Setup
If you don’t have Traefik running yet, here’s the complete setup:
Step 1: Create Traefik Network
docker network create traefik-net
Step 2: Create Traefik Configuration
Create traefik/traefik.yml:
api:
dashboard: true
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
network: traefik-net
certificatesResolvers:
letsencrypt:
acme:
email: your-email@example.com # CHANGE THIS
storage: /letsencrypt/acme.json
httpChallenge:
entryPoint: web
log:
level: INFO
accessLog: {}
Step 3: Create Traefik Docker Compose
Create traefik/docker-compose.yml:
version: '3.8'
networks:
traefik-net:
external: true
services:
traefik:
image: traefik:v2.10
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- traefik-net
ports:
- "80:80"
- "443:443"
- "8080:8080" # Dashboard (secure this in production!)
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/traefik.yml:ro
- ./letsencrypt:/letsencrypt
labels:
- "traefik.enable=true"
Step 4: Create Environment File
Create .env in your n8n directory:
# Domain Configuration
N8N_DOMAIN=n8n.yourdomain.com
# Database Password (generate secure password)
DB_PASSWORD=your_secure_db_password_here
# n8n Encryption Key (generate random string)
N8N_ENCRYPTION_KEY=your_encryption_key_here
Generate secure values:
# For DB_PASSWORD
openssl rand -base64 32
# For N8N_ENCRYPTION_KEY
openssl rand -hex 32
Step 5: Launch Everything
# Start Traefik first
cd traefik
docker compose up -d
# Wait a few seconds, then start n8n
cd ../n8n
docker compose up -d
# Watch logs to verify startup
docker compose logs -f n8n
Verifying Your Setup
Check Traefik Dashboard
Visit http://your-server-ip:8080 (or configure domain for dashboard)
Should show:
- ✅ n8n router active with green status
- ✅ Certificate obtained from Let’s Encrypt
- ✅ Service marked as healthy
Check n8n Access
Visit https://n8n.yourdomain.com
Should show:
- ✅ HTTPS working with valid Let’s Encrypt certificate
- ✅ No browser security warnings
- ✅ n8n login/setup page appears correctly
Check Webhook URLs
- Log into n8n
- Create a new workflow
- Add a Webhook node
- Check the “Production URL” shown
Expected:
https://n8n.yourdomain.com/webhook/abc123
NOT this (means configuration is wrong):
http://n8n.yourdomain.com:5678/webhook/abc123 ❌
2025 Requirement: Task Runners
What Are Task Runners?
Task runners execute code defined in Code nodes within isolated processes instead of the main n8n process. This provides better security through sandboxed environments, improved stability where code errors don’t crash the main process, and future compatibility as they’re required in upcoming n8n versions.
Why This Matters Now
From official n8n documentation:
“Running n8n without task runners is deprecated. Task runners will be turned on by default in a future version. Users are advised to set N8N_RUNNERS_ENABLED=true now to avoid potential issues in the future.”
From our testing logs (October 2025):
There are deprecations related to your environment variables:
- N8N_RUNNERS_ENABLED -> Running n8n without task runners is deprecated.
Configuration
Internal Mode (Recommended for Single Server)
environment:
- N8N_RUNNERS_ENABLED=true
- N8N_RUNNERS_MODE=internal
- N8N_RUNNERS_MAX_CONCURRENCY=5
n8n launches task runner as child process – simplest configuration with no additional infrastructure needed, suitable for most self-hosted deployments, minimal performance overhead.
External Mode (For Distributed Setups)
environment:
- N8N_RUNNERS_ENABLED=true
- N8N_RUNNERS_MODE=external
- N8N_RUNNERS_AUTH_TOKEN=your_secure_token
Separate task runner containers provide better resource isolation for high-volume workflows, enable horizontal scaling across multiple servers, but require orchestration (Docker Swarm, Kubernetes).
Verifying Task Runners
Check Process List
docker exec n8n ps aux
Without task runners (3 processes):
PID USER TIME COMMAND
1 node 0:00 tini -- /docker-entrypoint.sh
7 node 0:12 node /usr/local/bin/n8n
With task runners (4 processes):
PID USER TIME COMMAND
1 node 0:00 tini -- /docker-entrypoint.sh
7 node 0:16 node /usr/local/bin/n8n
18 node 0:10 node [...]/task-runner/dist/start.js
Evidence: Task runner process visible with PID 18.
Check Logs
docker logs n8n | grep -i runner
Should see:
n8n Task Broker ready on 127.0.0.1, port 5679
Registered runner "JS Task Runner" (zCWpF0Eb_LJsqWYvLm5t1)
Impact on Resource Usage
From our Docker testing (October 2025, n8n version 1.115.2):
| Configuration | Memory | CPU | Processes |
|---|---|---|---|
| Without task runners | 214 MB | 0.14% | 3 |
| With task runners | 289 MB | 0.29% | 4 |
| Difference | +75 MB | +0.15% | +1 |
Minimal overhead. The benefits – security, stability, future-proofing – far outweigh the small resource cost.
Environment Variables Reference
Complete Variable List
| Variable | Type | Default | Purpose | Priority |
|---|---|---|---|---|
| Critical Variables | ||||
WEBHOOK_URL | String | – | Public webhook URL | REQUIRED with reverse proxy |
N8N_PAYLOAD_SIZE_MAX | Number | 16777216(16MB) | Max execution data size | REQUIRED for large data |
N8N_RUNNERS_ENABLED | Boolean | false | Enable task runners | REQUIRED for 2025 |
N8N_TRUST_PROXY_HEADER | Boolean | false | Trust reverse proxy headers | REQUIRED with proxy |
| Webhook Configuration | ||||
N8N_EDITOR_BASE_URL | String | – | Editor UI URL | Recommended |
N8N_PROTOCOL | String | http | Protocol (http/https) | Production |
N8N_HOST | String | localhost | Public hostname | Production |
N8N_PORT | Number | 5678 | Internal port | Optional |
N8N_PROXY_HOPS | Number | 0 | Number of reverse proxies | Set to 1 with proxy |
| Performance | ||||
N8N_DEFAULT_BINARY_DATA_MODE | String | default | Binary storage mode | Recommended |
N8N_BINARY_DATA_TTL | Number | 60 | Binary cleanup (minutes) | Recommended |
| Task Runners | ||||
N8N_RUNNERS_MODE | String | internal | Task runner mode | If runners enabled |
N8N_RUNNERS_MAX_CONCURRENCY | Number | 5 | Max concurrent task runners | Optional |
Configuration Presets by Scenario
Scenario A: Development (Local Machine)
environment:
- N8N_PORT=5678
Use when: Testing locally, no reverse proxy, no production requirements
Scenario B: Behind Reverse Proxy (No Large Data)
environment:
- N8N_PORT=5678
- WEBHOOK_URL=https://n8n.yourdomain.com
- N8N_EDITOR_BASE_URL=https://n8n.yourdomain.com
- N8N_PROTOCOL=https
- N8N_HOST=n8n.yourdomain.com
- N8N_TRUST_PROXY_HEADER=true
- N8N_PROXY_HOPS=1
- N8N_RUNNERS_ENABLED=true
Use when: Public n8n instance, webhooks needed, smaller workflows
Scenario C: Complete Production Setup
environment:
# Database
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=n8n
- DB_POSTGRESDB_USER=n8n
- DB_POSTGRESDB_PASSWORD=${DB_PASSWORD}
# Webhooks
- WEBHOOK_URL=https://n8n.yourdomain.com
- N8N_EDITOR_BASE_URL=https://n8n.yourdomain.com
- N8N_PROTOCOL=https
- N8N_HOST=n8n.yourdomain.com
- N8N_PORT=5678
- N8N_TRUST_PROXY_HEADER=true
- N8N_PROXY_HOPS=1
# Performance
- N8N_PAYLOAD_SIZE_MAX=268435456 # 256MB
- N8N_DEFAULT_BINARY_DATA_MODE=filesystem
- N8N_BINARY_DATA_TTL=1440
# Task Runners
- N8N_RUNNERS_ENABLED=true
- N8N_RUNNERS_MODE=internal
- N8N_RUNNERS_MAX_CONCURRENCY=5
# Production
- NODE_ENV=production
- EXECUTIONS_DATA_MAX_AGE=168 # 7 days
- EXECUTIONS_DATA_PRUNE_MAX_COUNT=1000
- N8N_LOG_LEVEL=info
# Security
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
Use when: Production deployment with all features, large workflows, public access
Docker Compose Examples
All four scenarios from our testing environment are available. These configurations have been validated with n8n version 1.115.2 in October 2025.
Resource Usage Comparison (From Our Tests)
| Scenario | Memory | CPU | Processes | Description |
|---|---|---|---|---|
| Default | 315 MB | 0.00% | 3 | No fixes, baseline |
| Payload Fix | 211 MB | 0.00% | 3 | Payload + filesystem mode |
| Webhook Fix | 215 MB | 0.14% | 3 | Webhook config only |
| Production | 289 MB | 0.29% | 4 | All fixes + task runners |
Key Insight: The production configuration with all fixes uses LESS memory than default configuration due to filesystem binary mode.
Testing Your Setup
Pre-Deployment Checklist
1. DNS Configuration
# Verify DNS points to your server
nslookup n8n.yourdomain.com
# Should return your server's public IP
2. Port Availability
# Check if required ports are free
sudo netstat -tlnp | grep -E '(80|443|5678)'
# Should show nothing or only Traefik on 80/443
3. Docker Installation
# Verify Docker
docker --version
# Verify Docker Compose
docker compose version
4. Environment Variables
# Verify .env file exists
cat .env
# Should show N8N_DOMAIN, DB_PASSWORD, N8N_ENCRYPTION_KEY
Deployment Steps
# Step 1: Create Traefik network
docker network create traefik-net
# Step 2: Start Traefik
cd traefik
docker compose up -d
# Step 3: Wait for Traefik to be ready
sleep 10
# Step 4: Start n8n
cd ../n8n
docker compose up -d
# Step 5: Watch logs for any errors
docker compose logs -f n8n
Post-Deployment Tests
Test 1: HTTPS Access
curl -I https://n8n.yourdomain.com
Expected: HTTP/2 200 (or HTTP/1.1 200)
Test 2: HTTP to HTTPS Redirect
curl -I http://n8n.yourdomain.com
Expected: HTTP/1.1 308 Permanent Redirect with Location: https://n8n.yourdomain.com
Test 3: Container Health
docker ps
Expected: Both n8n and n8n-postgres showing (healthy) status
Test 4: Webhook URL Format
- Log into n8n web interface
- Create new workflow
- Add Webhook node
- Check Production URL shown
Expected format:
https://n8n.yourdomain.com/webhook/abc123
NOT expected (configuration error):
http://n8n.yourdomain.com:5678/webhook/abc123 ❌
Test 5: Task Runners Active
docker logs n8n | grep -i runner
Expected output:
Registered runner "JS Task Runner"
Test 6: Environment Variables Applied
docker exec n8n env | grep N8N_PAYLOAD_SIZE_MAX
Expected: N8N_PAYLOAD_SIZE_MAX=268435456
Troubleshooting Common Issues
Issue: HTTPS Not Working
Symptoms: Browser shows “Not Secure” warning, certificate error messages, can’t access via HTTPS
Diagnosis:
# Check Traefik logs for errors
docker logs traefik | grep -i error
# Check certificate file exists
ls -la traefik/letsencrypt/acme.json
# Verify DNS resolution
nslookup n8n.yourdomain.com
Solutions:
- DNS not pointing to server: Update your DNS A record to point to server’s public IP, wait for DNS propagation (up to 24 hours, usually much faster), test from different network:
dig n8n.yourdomain.com +short - Port 80 blocked: Let’s Encrypt needs port 80 for HTTP challenge. Check firewall:
sudo ufw status. Allow if blocked:sudo ufw allow 80/tcp && sudo ufw allow 443/tcp - Invalid email in Traefik config: Edit
traefik/traefik.yml, updatecertificatesResolvers.letsencrypt.acme.emailto valid address, restart Traefik:docker compose restart
Issue: Webhooks Return 404
Symptoms: External services report webhook failures, webhook URLs look correct but don’t work, test mode works but production mode fails
Diagnosis:
# Test webhook directly
curl -v https://n8n.yourdomain.com/webhook/test
# Check Traefik routing logs
docker logs traefik | grep webhook
# Verify n8n sees requests
docker logs n8n | grep webhook
Solutions:
- WebSocket middleware missing: Verify these labels in docker-compose.yml:
- "traefik.http.middlewares.n8n-websocket.headers.customrequestheaders.Upgrade=websocket"
- "traefik.http.middlewares.n8n-websocket.headers.customrequestheaders.Connection=Upgrade"
- "traefik.http.routers.n8n.middlewares=n8n-websocket"
- WEBHOOK_URL not set correctly: Check environment variable:
docker exec n8n env | grep WEBHOOK_URL. Should match your domain exactly:WEBHOOK_URL=https://n8n.yourdomain.com - Wrong network configuration: Verify n8n is on traefik-net:
docker inspect n8n | grep -A 5 Networks. Should show “traefik-net” in output
Issue: “Execution Data Too Large” Still Appears
Symptoms: Error still occurs after setting N8N_PAYLOAD_SIZE_MAX, large workflows fail at “Execute Node”
Diagnosis:
# Verify variable is set
docker exec n8n env | grep PAYLOAD
# Should show N8N_PAYLOAD_SIZE_MAX=268435456
Solutions:
- Variable not applied (container not restarted): Restart to apply changes:
docker compose restart n8n. Verify after restart:docker exec n8n env | grep PAYLOAD - Need higher limit for your workflow: For 16GB+ RAM servers, increase to 512MB:
N8N_PAYLOAD_SIZE_MAX=536870912 - Traefik request size too small: Also increase Traefik limit to match:
"traefik.http.middlewares.n8n-buffering.buffering.maxRequestBodyBytes=209715200"
Issue: High Memory Usage
Symptoms: Container using >1.5GB RAM at idle, memory usage grows over time, out of memory errors
Diagnosis:
# Monitor memory
docker stats n8n
# Check binary data mode
docker exec n8n env | grep BINARY_DATA_MODE
Solutions:
- Not using filesystem mode: Add to environment:
N8N_DEFAULT_BINARY_DATA_MODE=filesystemandN8N_BINARY_DATA_TTL=1440. Impact: Saves ~100MB RAM based on our testing - Old executions accumulating: Reduce retention period:
EXECUTIONS_DATA_MAX_AGE=168(7 days instead of 14) andEXECUTIONS_DATA_PRUNE_MAX_COUNT=1000 - Container limit too low: Increase if server has capacity. Change memory limit from 2G to 4G in deploy resources section
Conclusion
What We’ve Solved
This comprehensive guide addresses the two most common self-hosted n8n issues:
- ✅ Execution Data Too Large Error – Fixed with
N8N_PAYLOAD_SIZE_MAXand filesystem binary mode - ✅ Webhook URL Problems – Fixed with
WEBHOOK_URLand proper reverse proxy configuration
Plus these critical additions:
- ✅ Complete Traefik Setup – Production-ready configuration with WebSocket support
- ✅ Task Runners Configuration – 2025 requirement for future compatibility
- ✅ Production Best Practices – Resource limits, healthchecks, security headers, monitoring
- ✅ Validated Configurations – All docker-compose files tested with n8n 1.115.2 in October 2025
Key Takeaways
For Quick Fixes:
- Set
N8N_PAYLOAD_SIZE_MAX=268435456for execution data issues (256MB for 8GB+ RAM) - Set
WEBHOOK_URL=https://your-domain.comfor webhook problems - Set
N8N_RUNNERS_ENABLED=trueto eliminate deprecation warnings - Use
N8N_DEFAULT_BINARY_DATA_MODE=filesystemto save ~100MB RAM
For Production Deployment:
- Use our complete docker-compose.yml with Traefik configuration
- Don’t skip WebSocket middleware – absolutely required for webhooks
- Include PostgreSQL for better performance under load
- Set appropriate resource limits based on your server capacity
- Implement healthchecks for automatic recovery
For Traefik Users (CRITICAL):
- WebSocket middleware is non-negotiable for webhook functionality
- Set request body size limit to match or exceed payload size
- Configure security headers (X-Robots-Tag, X-Forwarded-Proto)
- Ensure DNS points to your server before starting Traefik (Let’s Encrypt requirement)
What’s New Compared to June 2025 Posts
| Feature | June 2025 Posts | This Guide |
|---|---|---|
| Execution data fix | ✅ Detailed | ✅ Included + resource measurements |
| Webhook fix | ✅ Detailed | ✅ Included + Traefik integration |
| Traefik configuration | ❌ Not covered | ✅ Complete setup |
| WebSocket support | ❌ Not covered | ✅ Emphasized |
| Task runners | ❌ Not covered | ✅ 2025 requirement |
| Combined docker-compose | ❌ Separate | ✅ Production-ready |
| Resource measurements | ❌ Theoretical | ✅ Actual test data |
| Environment variables | ✅ Covered | ✅ Complete reference |
Testing and Validation
Our testing environment (October 2025):
- ✅ n8n version 1.115.2
- ✅ Docker containers running for 2+ hours
- ✅ All environment variables verified in running containers
- ✅ Resource usage measured with
docker stats - ✅ Task runner process confirmed in process list
- ✅ HTTP endpoints tested and accessible
- ✅ Configurations validated as working
Next Steps
- Choose your scenario:
- Development: Minimal configuration
- Behind reverse proxy: Webhook fix + task runners
- Production: Complete setup with Traefik (recommended)
- Deploy:
- Copy the appropriate docker-compose.yml
- Create .env file with your domain and secure passwords
- Start Traefik first, then n8n
- Run post-deployment tests
- Validate:
- Verify HTTPS works with valid certificate
- Check webhook URLs show correct format
- Test with large dataset (if needed)
- Confirm task runners are registered
- Monitor:
- Watch resource usage with
docker stats - Set up healthcheck alerts (external monitoring)
- Implement log rotation to prevent disk filling
- Plan regular backups of data volumes
- Watch resource usage with
Related Resources
From June 2025:
- Solving n8n “Existing execution data is too large” Error – In-depth troubleshooting guide
- Fixing n8n Webhook Problems – Complete webhook debugging guide
Official n8n Documentation:
- Webhook URL Configuration
- Environment Variables Reference
- Task Runners
- Binary Data Management
- Execution Data Scaling
Questions or Issues?
If you encounter problems not covered in this guide:
- Review our June 2025 detailed troubleshooting posts for additional guidance
- Consult official n8n documentation for latest features
- Search n8n Community forums for similar issues
- Check the Troubleshooting section above for common problems
- Contact tva for professional implementation support
Reproducible Testing
All configurations in this guide can be reproduced in your own environment – Docker Compose files are production-ready, environment variables are documented and verified, test commands are provided for validation, and expected outputs are clearly specified. You can validate every claim in this guide by deploying the configurations yourself and running the provided tests.
Need Help with Implementation?
If you’d like tva to handle your n8n deployment or need assistance with production setup, get in touch with us. We implement these configurations for organizations looking for reliable, production-ready n8n infrastructure.
Published: October 15, 2025
Tested With: n8n v1.115.2, Docker Compose v3.8, Traefik v2.10
Server Requirements: 4GB+ RAM, 2+ CPU cores recommended for production
Based On: Official n8n documentation, validated Docker testing, and community best practices