tva
← Insights

Fixing n8n Webhook Problems: The Complete Troubleshooting Guide for Self-Hosted Instances

Self-hosting n8n gives you control and cost savings, but webhook integrations can sometimes fail in ways that don’t occur with cloud-hosted solutions. If you’re seeing “Execution cancelled” errors or webhooks that simply don’t trigger, you’re not alone. We’ll show you how to diagnose and fix the most common webhook problems in self-hosted n8n installations.

The Problem: When Webhooks Go Silent

You’ve successfully set up your n8n instance following our complete tutorial, and everything looks perfect. But suddenly your Telegram bots stop responding, API webhooks time out, and executions get canceled with cryptic error messages. This is typically caused by a missing but critical configuration that cloud-hosted n8n handles automatically.

What You’ll Fix

By the end of this guide, you’ll have:

  • ✅ Properly configured webhook URLs for all external services
  • ✅ Working Telegram bot integrations with reliable message handling
  • ✅ Functional API webhooks from third-party services
  • ✅ Fewer “execution cancelled” errors caused by webhook misconfiguration
  • ✅ Production-ready webhook configuration that survives server restarts
  • ✅ Advanced troubleshooting skills for future webhook issues

Prerequisites

  • Working n8n installation (preferably from our Hetzner setup guide)
  • n8n running behind a reverse proxy (Traefik, Nginx, etc.)
  • HTTPS enabled with valid SSL certificates
  • SSH access to your server
  • Basic Docker and command-line knowledge

Understanding the Root Cause

Why Self-Hosted n8n Webhooks Fail

When you run n8n behind a reverse proxy (which you should for security and SSL), n8n needs to know its public URL to generate correct webhook endpoints. Without this configuration, n8n creates webhook URLs like:

❌ Wrong: https://yourdomain.com:5678/webhook/abc123
❌ Wrong: http://localhost:5678/webhook/abc123

Instead of the correct format:

✅ Correct: https://yourdomain.com/webhook/abc123

The Missing Environment Variable

The solution is the WEBHOOK_URL environment variable that tells n8n exactly where it’s publicly accessible. This is automatic in cloud solutions but must be manually configured in self-hosted setups. As of October 2026, n8n 2.35.0 and later document it as N8N_WEBHOOK_URL; WEBHOOK_URL still works as a deprecated alias that logs a warning at startup.

Step 1: Diagnose Your Current Setup

Check Your Container Configuration

First, let’s see what your current n8n configuration looks like:

# Navigate to your n8n directory
cd /opt/n8n

# Check current environment variables
cat docker-compose.yml | grep -A 20 "environment:"

Test Webhook URL Generation

Create a simple webhook workflow to see what URLs n8n is generating:

  1. Open your n8n interface
  2. Create a new workflow
  3. Add a “Webhook” trigger node
  4. Note the generated webhook URL

If the URL includes :5678 or uses localhost, you have the problem we’re fixing.

Check Container Logs

Look for webhook-related errors:

# Check n8n logs for webhook issues
docker logs n8n-n8n-1 | grep -i webhook

# Look for execution errors
docker logs n8n-n8n-1 | grep -i "cancelled\|timeout\|failed"

Step 2: Fix the Primary Issue – Add WEBHOOK_URL

For a Single n8n Instance

If you followed our original setup guide, edit your Docker Compose file:

cd /opt/n8n
# Create backup first
cp docker-compose.yml docker-compose.yml.backup

# Edit the configuration
nano docker-compose.yml

Add the WEBHOOK_URL environment variable to your existing configuration. The example also sets N8N_PROXY_HOPS=1, which n8n’s reverse-proxy guide recommends behind a single proxy such as Traefik:

version: '3'

services:
  n8n:
    image: n8nio/n8n:1.95.2
    restart: always
    environment:
      - N8N_HOST=n8n.yourdomain.com
      - NODE_ENV=production
      - N8N_PROTOCOL=https
      - N8N_PORT=5678
      - N8N_EDITOR_BASE_URL=https://n8n.yourdomain.com
      - N8N_EMAIL_MODE=smtp
      - N8N_SMTP_HOST=mailserver
      - N8N_SMTP_PORT=25
      - N8N_SMTP_SSL=false
      - N8N_SMTP_USER=
      - N8N_SMTP_PASS=
      - [email protected]
      - N8N_PROXY_HOPS=1
      - N8N_RUNNERS_ENABLED=true
      # 🔧 ADD THIS LINE - Critical for webhook functionality
      - WEBHOOK_URL=https://n8n.yourdomain.com
    volumes:
      - ./data:/home/node/.n8n
    networks:
      - proxy
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.n8n.rule=Host(`n8n.yourdomain.com`)"
      - "traefik.http.routers.n8n.entrypoints=https"
      - "traefik.http.routers.n8n.tls.certresolver=letsencrypt"
      - "traefik.http.services.n8n.loadbalancer.server.port=5678"

networks:
  proxy:
    external: true

For Multiple n8n Instances

If you’re running multiple n8n instances (e.g., for different teams), each needs its own WEBHOOK_URL:

# First instance (/opt/n8n/docker-compose.yml)
environment:
  - WEBHOOK_URL=https://n8n.yourdomain.com

# Second instance (/opt/n8n-team2/docker-compose.yml)  
environment:
  - WEBHOOK_URL=https://team2.yourdomain.com

Restart Your Container

Apply the changes:

# Stop the container
docker compose down

# Start with new configuration
docker compose up -d

# Verify it's running
docker ps | grep n8n

Step 3: Verify the Fix

Check the Container Logs

The startup log shows the editor URL. It confirms that n8n knows its public address, but not that webhooks are registered, so also check the URL in a Webhook node (next step):

docker logs n8n-n8n-1 --tail 10

Look for this line:

Editor is now accessible via:
https://n8n.yourdomain.com  # ✅ Should NOT include :5678

Test Webhook Generation

  1. Go back to your test webhook workflow
  2. Delete the old webhook node
  3. Add a new webhook node
  4. Verify the generated URL is correct: https://yourdomain.com/webhook/... (no port number)

Test an External Webhook

Create a simple test workflow with a Webhook node set to POST and the path test, then activate (publish) it so its production URL is registered, and call it:

# Test with curl
curl -X POST https://n8n.yourdomain.com/webhook/test \
  -H "Content-Type: application/json" \
  -d '{"test": "webhook working"}'

Step 4: Configure Telegram Bot Integration

The Telegram-Specific Challenge

Telegram requires HTTPS webhooks and has strict URL requirements. Here’s how to set up a working Telegram bot:

Create a Telegram Bot Workflow

  1. Create a new workflow in n8n
  2. Add a “Telegram Trigger” node
  3. Configure your bot token
  4. The webhook URL should now be correctly formatted

Register a Webhook with Telegram

# Replace YOUR_BOT_TOKEN with your actual token
# Replace the webhook URL with your actual webhook URL from n8n

curl -F "url=https://n8n.yourdomain.com/webhook/abc123" \
https://api.telegram.org/botYOUR_BOT_TOKEN/setWebhook

Verify the Telegram Webhook

Check if Telegram can reach your webhook:

curl https://api.telegram.org/botYOUR_BOT_TOKEN/getWebhookInfo

You should see:

{
  "ok": true,
  "result": {
    "url": "https://n8n.yourdomain.com/webhook/abc123",
    "has_custom_certificate": false,
    "pending_update_count": 0
  }
}

Step 5: Advanced Webhook Configuration

Enable WebSocket Support in Traefik

Ordinary webhook requests are plain HTTP and do not need WebSocket support. The n8n editor’s push connection uses WebSockets, which Traefik supports out of the box, so the standard labels are normally enough. Do not add a middleware that forces Connection: Upgrade headers onto every request; these labels are all Traefik needs:

# Standard labels in your n8n docker-compose.yml (no extra middleware needed)
labels:
  - "traefik.enable=true"
  - "traefik.http.routers.n8n.rule=Host(`n8n.yourdomain.com`)"
  - "traefik.http.routers.n8n.entrypoints=https"
  - "traefik.http.routers.n8n.tls.certresolver=letsencrypt"
  - "traefik.http.services.n8n.loadbalancer.server.port=5678"

Configure Payload and Execution Data Settings

These settings do not change timeouts: they store binary data on disk, set the maximum payload size and keep execution data for debugging. N8N_PAYLOAD_SIZE_MAX takes a number in MiB (default 16), so write 16 rather than 16MB. For execution timeouts, see EXECUTIONS_TIMEOUT under Webhook Queue Management below:

environment:
  # Add these for webhook reliability
  - N8N_DEFAULT_BINARY_DATA_MODE=filesystem
  - N8N_PAYLOAD_SIZE_MAX=16
  - EXECUTIONS_DATA_SAVE_ON_ERROR=all
  - EXECUTIONS_DATA_SAVE_ON_SUCCESS=all
  - EXECUTIONS_DATA_SAVE_MANUAL_EXECUTIONS=true

Troubleshooting Common Issues

Problem: Still Getting Port Numbers in URLs

Symptoms:

  • Webhook URLs still show :5678
  • External services can’t reach webhooks

Solution:

# Check if environment variable is properly set
docker exec n8n-n8n-1 env | grep WEBHOOK_URL

# If missing, recreate container:
docker compose down
docker compose up -d --force-recreate

Problem: “Bad webhook: HTTPS URL must be provided”

Symptoms:

  • Telegram bot setup fails
  • Error mentions HTTPS requirement

Cause: Your webhook URL is not using HTTPS or has SSL certificate issues.

Solution:

# Test SSL certificate
curl -I https://n8n.yourdomain.com

# Check Traefik logs for SSL issues
docker logs traefik | grep -i certificate

# Verify domain DNS points to your server
nslookup n8n.yourdomain.com

Problem: Webhooks Work in Test Mode but Fail in Production

Symptoms:

  • Test webhook executions work fine
  • Production webhooks time out or fail

Solution:

# Check for webhook URL conflicts
docker logs n8n-n8n-1 | grep "webhook.*test"

# Ensure production workflows use production URLs
# Deactivate test workflows before activating production ones

Problem: “Connection reset by peer” or 502 Bad Gateway

Symptoms:

  • Intermittent webhook failures
  • Gateway errors in logs

Solution:

# Check if container is running out of memory
docker stats n8n-n8n-1

# Increase container resources if needed:
# Add to docker-compose.yml under the n8n service:
deploy:
  resources:
    limits:
      memory: 2G
    reservations:
      memory: 1G

Security Considerations

Webhook IP Whitelisting

For sensitive webhooks, consider IP restrictions:

# In your webhook node configuration
"ipWhitelist": ["192.168.1.0/24", "10.0.0.0/8"]

Webhook Authentication

Always use webhook authentication when possible:

# In your webhook configuration
"authenticationMethod": "headerAuth"
"authenticationData": {
  "name": "X-API-Key",
  "value": "your-secret-key"
}

Rate Limiting

Protect against webhook abuse. A router takes a single middlewares label, and a second label with the same key replaces the first, so if the router already uses other middlewares, list them all in one comma-separated label:

# Add to Traefik labels
- "traefik.http.middlewares.rate-limit.ratelimit.average=10"
- "traefik.http.middlewares.rate-limit.ratelimit.burst=20"
- "traefik.http.routers.n8n.middlewares=rate-limit"

Monitoring and Maintenance

Monitor Webhook Health

Create a monitoring workflow:

  1. Add a “Cron” trigger (every 5 minutes)
  2. Add an “HTTP Request” node to test your webhook
  3. Add notification logic for failures

Log Webhook Activity

Enable detailed webhook logging:

environment:
  - N8N_LOG_LEVEL=debug
  - N8N_LOG_OUTPUT=console,file
  - N8N_LOG_FILE_COUNT_MAX=100
  - N8N_LOG_FILE_SIZE_MAX=16

Back Up Webhook Configurations

The script exports all workflows and all credentials into one file each with --all. Exported credentials stay encrypted, so keep the instance’s encryption key with your backups.

#!/bin/bash
# Create webhook backup script
mkdir -p /opt/backups/webhook-configs
cd /opt/n8n

# Backup workflow definitions
docker exec n8n-n8n-1 n8n export:workflow --all --output=/tmp/workflows-backup.json
docker cp n8n-n8n-1:/tmp/workflows-backup.json /opt/backups/webhook-configs/workflows-$(date +%Y%m%d).json

# Backup credentials
docker exec n8n-n8n-1 n8n export:credentials --all --output=/tmp/credentials-backup.json  
docker cp n8n-n8n-1:/tmp/credentials-backup.json /opt/backups/webhook-configs/credentials-$(date +%Y%m%d).json

Performance Optimization

Webhook Response Optimization

Configure efficient webhook responses. Older guides also set N8N_BINARY_DATA_TTL and N8N_PERSISTED_BINARY_DATA_TTL; n8n no longer uses them and asks you to remove them:

environment:
  # Optimize for webhook performance
  - N8N_DISABLE_UI=false
  - GENERIC_TIMEZONE=UTC

Database Cleanup for Webhooks

High-volume webhooks can fill your database. n8n prunes execution data by default (EXECUTIONS_DATA_PRUNE=true, keeping up to 336 hours and 10,000 executions); lower EXECUTIONS_DATA_MAX_AGE (hours) and EXECUTIONS_DATA_PRUNE_MAX_COUNT to keep less. n8n’s CLI has no execution cleanup command, so set the limits in the n8n service’s environment instead of a cron job, for example 30 days and at most 1,000 executions:

environment:
  # Prune executions older than 30 days (720 hours), keep at most 1,000
  - EXECUTIONS_DATA_PRUNE=true
  - EXECUTIONS_DATA_MAX_AGE=720
  - EXECUTIONS_DATA_PRUNE_MAX_COUNT=1000

Testing Webhook Integrations

Test Suite for Common Webhook Types

Create test workflows for different webhook types:

Simple REST API Webhook:

{
  "method": "POST",
  "url": "https://n8n.yourdomain.com/webhook/test-api",
  "headers": {
    "Content-Type": "application/json"
  },
  "body": {
    "test": true,
    "timestamp": "{{new Date().toISOString()}}"
  }
}

Telegram Bot Test: Send a message to your bot and verify the workflow triggers correctly.

Form Submission Test:

<form action="https://n8n.yourdomain.com/webhook/form-test" method="POST">
  <input type="text" name="name" value="Test User">
  <input type="email" name="email" value="[email protected]">
  <button type="submit">Test Webhook</button>
</form>

Scaling Webhook Infrastructure

Multiple n8n Instances with Load Balancing

For high-volume webhook processing, run dedicated webhook processors (n8n webhook) in queue mode. They need the same PostgreSQL database, Redis and encryption key as the main instance and the workers. Traefik adds a server for each container of a service, so both replicas share one port label, and the longer rule sends /webhook/ requests to the processors while the editor stays on the main instance:

# docker-compose.yml sketch: two webhook processors in queue mode
# (main instance, workers, PostgreSQL and Redis configured as in the queue section below)
services:
  n8n-webhook:
    image: n8nio/n8n:1.95.2
    command: webhook
    restart: always
    deploy:
      replicas: 2
    environment:
      - EXECUTIONS_MODE=queue
      - WEBHOOK_URL=https://n8n.yourdomain.com
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      # ... same database and Redis settings as the main instance
    networks:
      - proxy
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.n8n-webhook.rule=Host(`n8n.yourdomain.com`) && PathPrefix(`/webhook/`)"
      - "traefik.http.routers.n8n-webhook.entrypoints=https"
      - "traefik.http.routers.n8n-webhook.tls.certresolver=letsencrypt"
      - "traefik.http.services.n8n-webhook.loadbalancer.server.port=5678"

networks:
  proxy:
    external: true

Webhook Queue Management

For handling webhook bursts, queue mode also needs PostgreSQL (SQLite isn’t supported), separate worker processes and the same encryption key on the main instance and all workers. EXECUTIONS_TIMEOUT and EXECUTIONS_TIMEOUT_MAX are in seconds:

environment:
  - QUEUE_BULL_REDIS_HOST=redis
  - QUEUE_BULL_REDIS_PORT=6379
  - EXECUTIONS_MODE=queue
  - EXECUTIONS_TIMEOUT=3600
  - EXECUTIONS_TIMEOUT_MAX=7200

Cost and Performance Impact

Webhook Processing Costs

When properly configured, webhook processing is extremely efficient:

  • Server Resources: Minimal CPU/memory impact for most webhooks
  • Storage: Execution data scales with webhook volume
  • Network: Bandwidth scales with payload sizes

Cost Comparison

Self-hosted webhook processing vs. cloud alternatives:

  • n8n Cloud Starter: €20/month billed annually (2,500 executions, as of October 2026)
  • Self-hosted (Hetzner CX23): €5.99/month excl. VAT, incl. a primary IPv4 address, as of October 2026 (no per-execution fees; capacity limited by server resources)
  • Savings: about €168 annually, without execution quotas

Advanced Integration Examples

Webhook to Database Pipeline

Complete example for webhook-to-database integration:

# Workflow: API Webhook → Data Validation → Database Insert
# 1. Webhook Trigger (receives data)
# 2. Function Node (validates/transforms data)  
# 3. Database Node (inserts processed data)
# 4. HTTP Response (confirms receipt)

Multi-Service Webhook Router

Route different webhook types to appropriate handlers:

# Workflow: Webhook Router
# 1. Webhook Trigger (catches all webhooks)
# 2. Switch Node (routes by webhook source)
# 3. Multiple branches for different services
# 4. Appropriate response formatting

Conclusion

Properly configured webhooks are essential for a production-ready n8n installation. The WEBHOOK_URL environment variable is the single most important setting for webhook reliability in self-hosted setups. Combined with proper SSL configuration and monitoring, your self-hosted n8n instance can handle webhook workloads that would otherwise need a higher-tier cloud plan.

Key Benefits of This Configuration

  • Cost-effective: No per-execution fees on a server from about €6/month (as of October 2026)
  • Reliable: Production-tested configuration handles high-volume scenarios
  • Secure: HTTPS, authentication, and rate limiting protect your infrastructure
  • Scalable: Architecture supports growth from personal projects to enterprise workflows
  • Private: Webhook payloads are processed on your own server; data leaves it only when your workflows send it to external services such as Telegram

This guide builds upon our original n8n setup tutorial to create a complete, webhook-ready automation platform. Whether you’re processing Telegram messages, API callbacks, or form submissions, your self-hosted n8n instance now handles them all reliably and cost-effectively.

For complex webhook scenarios or enterprise-grade implementations, consider seeking professional advice to optimize your specific use case.


About tva

tva ensures comprehensive infrastructure management of database systems, cloud environments, and global supply chains. Our methodical approach combines rigorous security protocols with performance optimization, while strategic advisory services enable precise coordination of both digital capabilities and physical assets – maintaining the highest standards of operational excellence and compliance throughout all engagements.

Visit tva.sg for more information about our services and additional automation tutorials.

Further Reading