n8n en Producción: Alta Disponibilidad con Docker, Redis y PostgreSQL
- Fabrizio Piminchumo
- Application , Technology
- 15 Apr, 2026
Si ya tienes n8n funcionando con Docker en su configuración básica, sabes que es una herramienta poderosa. Pero cuando los flujos de trabajo se vuelven críticos para tu operación — automatizaciones que deben ejecutarse sin fallas, con concurrencia real y soporte para cargas altas — la instalación básica se queda corta.
En este post vamos a desplegar n8n en producción con una arquitectura diseñada para escalar: modo queue con Redis, múltiples workers, task runner externo y PostgreSQL como base de datos. Esta es la configuración que usamos en ECODING para nuestros flujos internos.
Prerequisito: Se recomienda haber leído el post anterior Instalación de n8n con Docker para entender los conceptos base antes de continuar.
¿Por qué esta arquitectura?
La instalación básica de n8n corre todo en un solo proceso: recibe los triggers, encola las ejecuciones y las procesa. Esto funciona bien para uso personal o equipos pequeños. Los problemas aparecen cuando:
- Múltiples flujos se disparan al mismo tiempo y se bloquean entre sí
- Un flujo pesado congela la interfaz web
- Necesitas escalar horizontalmente sin bajar el servicio
- La base de datos SQLite no aguanta la concurrencia
La solución es separar responsabilidades en componentes independientes:
┌─────────────────────────────────────────────────────┐
│ backend-net │
│ │
│ ┌──────────┐ ┌───────┐ ┌──────────────────┐ │
│ │ n8n │───▶│ Redis │ │ PostgreSQL │ │
│ │ (main) │ │(queue)│ │ (persistencia) │ │
│ └──────────┘ └───────┘ └──────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────────────┐ ┌──────────────────┐ │
│ │ n8n-worker (x3) │ │ n8n-task-runner │ │
│ │ concurrency=5 cada │ │ (código JS/TS) │ │
│ └──────────────────────┘ └──────────────────┘ │
└─────────────────────────────────────────────────────┘
Componentes de la arquitectura
n8n (proceso principal)
El proceso principal se encarga de:
- Servir la interfaz web
- Recibir webhooks y triggers
- Encolar las ejecuciones en Redis (no ejecutarlas directamente)
- Coordinar los workers
n8n-worker
Procesos independientes cuya única función es tomar trabajos de la cola Redis y ejecutarlos. Al tener 3 réplicas con concurrencia de 5 cada una, tienes capacidad para 15 ejecuciones simultáneas. Puedes ajustar ambos números según tu carga.
n8n-task-runner
Componente relativamente nuevo en n8n: ejecuta el código JavaScript/TypeScript de los nodos “Code” en un proceso aislado, separado del worker. Esto tiene dos ventajas clave:
- Seguridad: el código de usuario no corre dentro del proceso principal de n8n
- Estabilidad: si un script falla o consume demasiada memoria, no afecta al worker
Redis
Actúa como broker de cola (Bull queue). El proceso principal deposita trabajos ahí y los workers los consumen. También persiste el estado de ejecuciones en curso.
PostgreSQL
Reemplaza a SQLite como base de datos principal. Indispensable cuando tienes múltiples workers accediendo concurrentemente al mismo estado.
Preparación previa
Antes de levantar el stack, necesitas crear la red y el volumen externos. Solo se hace una vez por servidor:
docker network create backend-net
docker volume create n8n_data
La red backend-net es compartida con otros servicios (Redis, PostgreSQL). Esto permite que los contenedores se comuniquen entre sí por nombre de host sin exponer puertos al host.
Si ya tienes Redis y PostgreSQL corriendo en esta red desde otros stacks, solo asegúrate de que el nombre de red coincida.
El docker-compose.yml
services:
n8n:
image: docker.n8n.io/n8nio/n8n
restart: always
user: node
ports:
- "127.0.0.1:5678:5678"
environment:
# Identidad del servicio
- N8N_HOST=tu-dominio.com
- N8N_PROTOCOL=https
- WEBHOOK_URL=https://tu-dominio.com/
- N8N_PORT=5678
- N8N_TRUST_PROXY=true
- N8N_PROXY_HOPS=1
# Zona horaria
- TZ=America/Lima
- GENERIC_TIMEZONE=America/Lima
- NODE_ENV=production
# Base de datos PostgreSQL
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=n8n_db
- DB_POSTGRESDB_USER=n8n_user
- DB_POSTGRESDB_PASSWORD=TU_PASSWORD_SEGURO
# Cola con Redis (modo queue)
- EXECUTIONS_MODE=queue
- QUEUE_BULL_REDIS_HOST=redis
- QUEUE_BULL_REDIS_PORT=6379
- QUEUE_BULL_REDIS_PASSWORD=TU_REDIS_PASSWORD
- QUEUE_BULL_REDIS_DB=0
# Task runner externo
- N8N_RUNNERS_MODE=external
- N8N_RUNNERS_BROKER_LISTEN_ADDRESS=0.0.0.0
- N8N_RUNNERS_AUTH_TOKEN=TU_TOKEN_SECRETO
# Ejecuciones manuales también van a workers
- OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=true
# Almacenamiento de datos binarios
- N8N_DEFAULT_BINARY_DATA_MODE=filesystem
- N8N_STORAGE_PATH=/home/node/.n8n/binaryData
# Configuración de permisos
- N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
# SMTP (opcional, para notificaciones por email)
- N8N_EMAIL_MODE=smtp
- N8N_SMTP_HOST=TU_SMTP_HOST
- N8N_SMTP_PORT=465
- N8N_SMTP_USER=TU_SMTP_USER
- N8N_SMTP_PASS=TU_SMTP_PASSWORD
- N8N_SMTP_SENDER=noreply@tu-dominio.com
- N8N_SMTP_SSL=true
# Módulos Node.js adicionales (opcional)
- N8N_NODE_MODULES_INCLUDE=cheerio
volumes:
- n8n_data:/home/node/.n8n
networks:
- backend-net
n8n-worker:
image: docker.n8n.io/n8nio/n8n
restart: always
user: node
command: worker --concurrency=5
deploy:
replicas: 3
environment:
- N8N_HOST=tu-dominio.com
- N8N_PROTOCOL=https
- TZ=America/Lima
- GENERIC_TIMEZONE=America/Lima
- NODE_ENV=production
# Los workers también necesitan acceso a la base de datos
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=n8n_db
- DB_POSTGRESDB_USER=n8n_user
- DB_POSTGRESDB_PASSWORD=TU_PASSWORD_SEGURO
# Y a Redis para consumir la cola
- EXECUTIONS_MODE=queue
- QUEUE_BULL_REDIS_HOST=redis
- QUEUE_BULL_REDIS_PORT=6379
- QUEUE_BULL_REDIS_PASSWORD=TU_REDIS_PASSWORD
- QUEUE_BULL_REDIS_DB=0
# Almacenamiento binario compartido con el proceso principal
- N8N_DEFAULT_BINARY_DATA_MODE=filesystem
- N8N_STORAGE_PATH=/home/node/.n8n/binaryData
volumes:
- n8n_data:/home/node/.n8n
networks:
- backend-net
n8n-task-runner:
image: n8nio/runners:latest
restart: always
environment:
- N8N_RUNNERS_AUTH_TOKEN=TU_TOKEN_SECRETO
- N8N_RUNNERS_TASK_BROKER_URI=http://n8n:5679
networks:
- backend-net
depends_on:
- n8n
volumes:
n8n_data:
external: true
networks:
backend-net:
external: true
Análisis de las decisiones de configuración
Puerto solo en localhost
ports:
- "127.0.0.1:5678:5678"
El puerto solo se expone en la interfaz de loopback del host. Esto significa que n8n no es accesible directamente desde internet — necesitas un reverse proxy (Nginx, Caddy, etc.) por delante. Es una buena práctica de seguridad: el reverse proxy se encarga de TLS y de filtrar tráfico antes de que llegue a la aplicación.
EXECUTIONS_MODE=queue
- EXECUTIONS_MODE=queue
Este es el cambio más importante. En modo regular (defecto), n8n ejecuta todo en el proceso principal. En modo queue, el proceso principal solo recibe y encola — los workers hacen el trabajo real. Esto desacopla la interfaz web de la ejecución de flujos.
Workers con réplicas y concurrencia
command: worker --concurrency=5
deploy:
replicas: 3
Cada worker puede procesar 5 ejecuciones simultáneas (--concurrency=5). Con 3 réplicas tienes 15 ejecuciones paralelas en todo momento. Ajusta según tus necesidades:
- Flujos simples y rápidos → más concurrencia, menos réplicas
- Flujos pesados (mucha CPU/memoria) → menos concurrencia, más réplicas
- Para empezar:
replicas: 2,concurrency: 3es razonable en un VPS pequeño
Nota:
deploy.replicasfunciona con Docker Swarm o Docker Compose v3. Si usas Compose standalone, levanta los workers manualmente con--scale n8n-worker=3.
OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS
- OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=true
Por defecto, cuando ejecutas un flujo manualmente desde la interfaz (botón “Execute Workflow”), n8n lo corre en el proceso principal aunque estés en modo queue. Con esta variable, todas las ejecuciones — automáticas y manuales — pasan por los workers. Así el proceso principal nunca queda bloqueado.
Task Runner externo
- N8N_RUNNERS_MODE=external
- N8N_RUNNERS_BROKER_LISTEN_ADDRESS=0.0.0.0
- N8N_RUNNERS_AUTH_TOKEN=TU_TOKEN_SECRETO
El proceso principal actúa como broker en el puerto 5679 (interno, no expuesto). El contenedor n8n-task-runner se conecta a él para recibir tareas de ejecución de código. La autenticación se hace con el token compartido.
Para generar un token seguro:
openssl rand -hex 32
Almacenamiento binario en filesystem
- N8N_DEFAULT_BINARY_DATA_MODE=filesystem
- N8N_STORAGE_PATH=/home/node/.n8n/binaryData
Cuando los flujos manejan archivos (PDFs, imágenes, CSVs), n8n necesita almacenarlos temporalmente. En modo memory (defecto) se guardan en RAM — con múltiples workers y archivos grandes, esto puede agotar la memoria rápidamente. En modo filesystem se guardan en disco y se comparte el volumen n8n_data entre el proceso principal y todos los workers.
Redis en una base de datos separada
- QUEUE_BULL_REDIS_DB=0
Redis soporta múltiples bases de datos lógicas (0-15) en la misma instancia. Si compartes Redis con otras aplicaciones, cambia el número para aislar los datos de n8n. Por ejemplo, si otra app usa DB 0, puedes poner n8n en DB 3 y no habrá interferencia.
N8N_NODE_MODULES_INCLUDE
- N8N_NODE_MODULES_INCLUDE=cheerio
Por seguridad, n8n restringe qué módulos de Node.js pueden usarse en los nodos “Code”. Esta variable lista en blanco los módulos adicionales que quieres habilitar. cheerio es útil para parsear HTML. Puedes agregar múltiples módulos separados por coma: cheerio,lodash,axios.
Variables que debes personalizar
| Variable | Descripción | Cómo obtenerlo |
|---|---|---|
N8N_HOST | Tu dominio | El dominio que apunta a tu servidor |
WEBHOOK_URL | URL base para webhooks | https://tu-dominio.com/ |
DB_POSTGRESDB_PASSWORD | Contraseña de PostgreSQL | Generar con openssl rand -base64 24 |
QUEUE_BULL_REDIS_PASSWORD | Contraseña de Redis | Generar con openssl rand -base64 24 |
N8N_RUNNERS_AUTH_TOKEN | Token para task runner | Generar con openssl rand -hex 32 |
N8N_SMTP_* | Configuración de correo | Datos de tu proveedor SMTP |
TZ / GENERIC_TIMEZONE | Zona horaria | Ver lista en Wikipedia |
Levantar el stack
# 1. Crear red y volumen (solo la primera vez)
docker network create backend-net
docker volume create n8n_data
# 2. Levantar los servicios
docker compose up -d
# 3. Verificar que todo esté corriendo
docker compose ps
# 4. Ver logs del proceso principal
docker compose logs -f n8n
# 5. Ver logs de los workers
docker compose logs -f n8n-worker
Verificar que el modo queue funciona
Una vez levantado, entra a la interfaz web y ve a Settings → About. Deberías ver el modo de ejecución como queue. Si ves regular, revisa las variables de entorno.
Para verificar que los workers están conectados, ejecuta cualquier flujo simple y en los logs de n8n-worker deberías ver la ejecución siendo procesada.
Consideraciones para producción
- Backups de PostgreSQL: Los datos críticos de n8n (flujos, credenciales, historial) están en PostgreSQL. Configura backups automáticos.
- Persistencia de Redis: Si Redis se reinicia, las ejecuciones en cola se pierden. Considera habilitar AOF persistence en tu configuración de Redis.
- Monitoreo: Agrega healthchecks a los contenedores y monitoreа el tamaño de la cola en Redis con
LLEN bull:jobs:wait. - Escalado: Puedes agregar más workers en caliente con
docker compose up --scale n8n-worker=5 -dsin reiniciar el proceso principal.
En los próximos posts de esta serie vamos a ver cómo configurar Redis y PostgreSQL con sus propios stacks de Docker, listos para conectarse a esta arquitectura y a otros servicios que vayas sumando.