Una instalación simple de n8n puede saturarse cuando aumentan los webhooks, las ejecuciones largas o las automatizaciones críticas. En estos escenarios, queue mode permite separar la recepción y administración de workflows de su procesamiento.
La instancia Main mantiene la interfaz, los triggers y la coordinación general. PostgreSQL conserva workflows, credenciales y ejecuciones; Redis transporta la cola; los workers consumen los trabajos y escriben los resultados nuevamente en PostgreSQL.
Redis no sustituye a la base de datos ni a sus backups. Es un componente de coordinación cuya indisponibilidad afecta la ejecución de nuevos trabajos.
Cuándo conviene aplicarlo
Este enfoque resulta útil para:
- Automatizaciones internas.
- Integraciones DevOps y SecOps.
- Workflows largos o con consumo variable.
- Equipos que necesitan control sobre sus datos.
- Instalaciones con backlog o picos de webhooks.
- Entornos que necesitan ampliar capacidad sin duplicar el editor.
Queue mode agrega componentes y operación. Para cargas pequeñas, una única instancia puede seguir siendo la opción más sencilla.
Requisitos previos
Necesitarás:
- Docker Compose.
- Un dominio con HTTPS y proxy inverso.
- PostgreSQL 13 o posterior.
- Redis protegido y accesible únicamente desde la red interna.
- Una versión de n8n fijada y probada.
- Una clave de cifrado respaldada.
- Backups y restauraciones ensayados.
- Métricas para ejecuciones, cola, workers y base de datos.
El escalado con múltiples procesos Main y algunas funciones de almacenamiento, roles o colaboración dependen de la edición o licencia. Esta guía utiliza un único Main y varios workers.
Arquitectura de queue mode
El flujo es el siguiente:
- Main o un webhook processor recibe el evento.
- n8n crea la ejecución y conserva sus datos en PostgreSQL.
- El identificador del trabajo se incorpora a Redis.
- Un worker toma el trabajo.
- El worker carga workflow y credenciales desde PostgreSQL.
- El worker ejecuta los nodos.
- El resultado se escribe en PostgreSQL.
Todos los procesos deben utilizar:
- La misma versión de n8n.
- La misma
N8N_ENCRYPTION_KEY. - La misma base PostgreSQL.
- La misma instancia Redis.
- Los mismos custom nodes, si existen.
La clave permite descifrar las credenciales almacenadas. Si un worker utiliza otra clave, no podrá abrirlas. Configuración oficial de queue mode.
Paso 1: generar y proteger los secretos
Genera valores independientes:
openssl rand -hex 32 # N8N_ENCRYPTION_KEY
openssl rand -hex 32 # POSTGRES_PASSWORD
openssl rand -hex 32 # REDIS_PASSWORDGuárdalos en un gestor de secretos. Para una prueba local con .env, restringe permisos antes de escribirlo:
umask 077
touch .env
chmod 600 .envPlantilla mínima:
N8N_VERSION=VERSION_PROBADA
N8N_HOST=n8n.ejemplo.com
N8N_ENCRYPTION_KEY=REEMPLAZAR
POSTGRES_USER=n8n
POSTGRES_DB=n8n
POSTGRES_PASSWORD=REEMPLAZAR
REDIS_PASSWORD=REEMPLAZARNo agregues .env al repositorio. Conserva una copia recuperable de N8N_ENCRYPTION_KEY separada del backup de PostgreSQL.
Paso 2: definir PostgreSQL y Redis
Este Compose muestra la configuración base. En producción, fija todas las imágenes a una versión o digest:
services:
postgres:
image: postgres:18
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql
healthcheck:
test:
- CMD-SHELL
- pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}
interval: 10s
timeout: 5s
retries: 10
networks:
- backend
redis:
image: redis:8
restart: unless-stopped
command:
- redis-server
- --appendonly
- "yes"
- --requirepass
- ${REDIS_PASSWORD}
environment:
REDIS_PASSWORD: ${REDIS_PASSWORD}
volumes:
- redis_data:/data
healthcheck:
test:
- CMD-SHELL
- REDISCLI_AUTH="$${REDIS_PASSWORD}" redis-cli ping | grep PONG
interval: 10s
timeout: 5s
retries: 10
networks:
- backend
volumes:
postgres_data:
redis_data:
networks:
backend:
internal: trueNo se publican los puertos 5432 ni 6379.
En la imagen oficial de PostgreSQL 18, el volumen debe montarse en /var/lib/postgresql; el directorio predeterminado cambió respecto de PostgreSQL 17 y versiones anteriores. Reutilizar una configuración antigua con /var/lib/postgresql/data puede impedir que el volumen esperado conserve los datos. Documentación de la imagen oficial de PostgreSQL.
La persistencia AOF de Redis ayuda durante reinicios, pero no elimina la necesidad de controlar ejecuciones interrumpidas y recuperación de cola.
Paso 3: compartir la configuración de n8n
Agrega una plantilla común al Compose:
x-n8n-common: &n8n-common
image: n8nio/n8n:${N8N_VERSION}
restart: unless-stopped
environment: &n8n-environment
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_PORT: 5432
DB_POSTGRESDB_DATABASE: ${POSTGRES_DB}
DB_POSTGRESDB_USER: ${POSTGRES_USER}
DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
EXECUTIONS_MODE: queue
QUEUE_BULL_REDIS_HOST: redis
QUEUE_BULL_REDIS_PORT: 6379
QUEUE_BULL_REDIS_PASSWORD: ${REDIS_PASSWORD}
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
N8N_HOST: ${N8N_HOST}
N8N_PORT: 5678
N8N_PROTOCOL: https
N8N_EDITOR_BASE_URL: https://${N8N_HOST}/
WEBHOOK_URL: https://${N8N_HOST}/
N8N_PROXY_HOPS: 1
N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS: "true"
N8N_METRICS: "true"
EXECUTIONS_DATA_PRUNE: "true"
EXECUTIONS_DATA_MAX_AGE: 336
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
networks:
- backendWEBHOOK_URL permite que n8n muestre y registre la URL pública correcta detrás del proxy. N8N_PROXY_HOPS debe coincidir con la cantidad real de proxies confiables.
No utilices un valor alto “por si acaso”: confiar en más saltos de los existentes puede hacer que n8n acepte cabeceras reenviadas por clientes no confiables.
Paso 4: crear Main y los workers
Añade los servicios:
services:
n8n:
<<: *n8n-common
command: start
volumes:
- n8n_data:/home/node/.n8n
ports:
- 127.0.0.1:5678:5678
stop_grace_period: 60s
worker:
<<: *n8n-common
command: worker --concurrency=5
environment:
<<: *n8n-environment
QUEUE_HEALTH_CHECK_ACTIVE: "true"
QUEUE_HEALTH_CHECK_PORT: 5678
expose:
- "5678"
stop_grace_period: 60s
volumes:
n8n_data:No declares container_name en worker, porque impediría escalar varias réplicas mediante Compose.
La concurrencia cinco es un punto inicial, no una recomendación universal. Cada ejecución puede abrir conexiones, procesar archivos o consumir mucha memoria. Ajusta después de medir:
- Memoria por worker.
- CPU.
- Duración p95.
- Conexiones a PostgreSQL.
- Límites de las APIs externas.
- Backlog de Redis.
Escala workers:
docker compose up -d --scale worker=3Aumentar workers sin ampliar PostgreSQL, Redis o los servicios externos puede trasladar el cuello de botella.
Paso 5: validar antes de iniciar n8n
Comprueba la configuración:
docker compose config --quietInicia primero los servicios persistentes:
docker compose up -d postgres redis
docker compose psComprueba PostgreSQL:
docker compose exec postgres \
pg_isready \
--username "$POSTGRES_USER" \
--dbname "$POSTGRES_DB"Comprueba Redis:
docker compose exec redis \
sh -c 'REDISCLI_AUTH="$REDIS_PASSWORD" redis-cli ping'Solo después inicia Main y workers:
docker compose up -d n8n worker
docker compose psRevisa los logs iniciales:
docker compose logs \
--tail 200 \
n8n worker postgres redisDetén la migración si Main y worker informan versiones distintas, errores de cifrado o conexiones intermitentes.
Paso 6: validar una ejecución en cola
Crea en staging un workflow de prueba:
- Webhook.
- Set o Edit Fields.
- Espera breve.
- Respond to Webhook.
Invócalo con un identificador ficticio:
curl \
--fail-with-body \
--header 'Content-Type: application/json' \
--data '{"test_id":"queue-smoke-001"}' \
https://n8n.ejemplo.com/webhook/queue-smokeBusca el identificador en los logs:
docker compose logs \
--since 5m \
n8n worker |
grep 'queue-smoke-001'También verifica en la interfaz que:
- La ejecución se creó.
- Un worker la procesó.
- Terminó una sola vez.
- La respuesta del webhook fue correcta.
- Redis volvió a un estado sin backlog.
- PostgreSQL conservó el resultado esperado.
Los nombres internos de las claves de Redis no forman parte de una interfaz estable. Para monitoreo, utiliza métricas de n8n y Redis en lugar de depender de nombres de claves internos.
Paso 7: agregar webhook processors cuando sean necesarios
Queue mode separa ejecución y recepción, pero el Main puede seguir siendo el punto de entrada de los webhooks. Si la recepción se convierte en cuello de botella, agrega procesos específicos:
services:
webhook:
<<: *n8n-common
command: webhook
deploy:
replicas: 2El proxy debe separar rutas:
- Editor, API y administración hacia Main.
- Webhooks de producción hacia los webhook processors.
- Rutas de prueba y administración según la topología documentada para la versión utilizada.
No envíes la interfaz del editor a los webhook processors. Mantén Main fuera del pool dedicado a webhooks.
Antes de habilitarlos, prueba workflows con Respond to Webhook, archivos y respuestas largas, porque el worker puede completar la ejecución después de que el procesador haya recibido la solicitud.
Paso 8: tratar correctamente los datos binarios
El almacenamiento local filesystem no es apropiado para queue mode distribuido: el worker que necesita el archivo puede ejecutarse en otro host o contenedor.
Para cargas pequeñas, utiliza el modo predeterminado compatible con la versión de n8n y mide el efecto sobre PostgreSQL y memoria. Para archivos grandes, evalúa almacenamiento externo compartido.
El almacenamiento S3 de n8n es una función Self-hosted Enterprise y requiere configurar su propio ciclo de vida y retención. Además, Main, workers y runners deben actualizarse juntos para evitar incompatibilidades. Almacenamiento externo de datos binarios.
No habilites filesystem simplemente montando un volumen en Main; todos los procesos necesitarían ver exactamente el mismo almacenamiento y n8n no lo admite como solución general para queue mode.
Paso 9: respaldar antes de migrar
Crea un backup lógico:
docker compose exec -T postgres \
pg_dump \
--username "$POSTGRES_USER" \
--dbname "$POSTGRES_DB" \
--format custom \
> n8n-before-queue.dumpConserva por separado:
N8N_ENCRYPTION_KEY.- Versión y digest de n8n.
- Definición del Compose.
- Configuración del proxy.
- Custom nodes y sus versiones.
- Datos binarios externos, si existen.
El backup no está validado hasta restaurarlo en una instancia aislada y comprobar que las credenciales pueden descifrarse.
Paso 10: observar y escalar
Supervisa como mínimo:
- Ejecuciones pendientes, activas, completas y fallidas.
- Edad del trabajo más antiguo.
- Duración p50, p95 y p99.
- Concurrencia utilizada por worker.
- Reinicios y terminaciones por memoria.
- Conexiones y latencia de PostgreSQL.
- Memoria, persistencia y conexiones de Redis.
- Tasa y latencia de webhooks.
- Tamaño de tablas de ejecuciones.
- Errores de APIs externas.
Escala cuando el backlog crezca de forma sostenida, no por un pico aislado. Reduce concurrencia si PostgreSQL o los servicios externos se saturan.
Pruebas de funcionamiento
Antes de producción:
- Restaura un backup en staging.
- Confirma que Main y workers usan la misma versión.
- Ejecuta un workflow con una credencial cifrada.
- Prueba un webhook y una ejecución programada.
- Detén un worker durante una ejecución controlada.
- Confirma la recuperación esperada.
- Reinicia Redis y revisa trabajos pendientes.
- Prueba límites de concurrencia.
- Verifica pruning y crecimiento de PostgreSQL.
- Comprueba logs, métricas y alertas.
- Ensaya el rollback a la instalación anterior.
- Ejecuta el audit de seguridad de n8n.
n8n incluye un comando de auditoría que detecta, entre otros riesgos, webhooks sin protección, nodos riesgosos, custom nodes y configuraciones de seguridad ausentes. Auditoría de seguridad de n8n.
Problemas frecuentes
Los workflows quedan esperando
Comprueba:
docker compose ps
docker compose logs --tail 200 worker redisRevisa EXECUTIONS_MODE, conexión a Redis, password, disponibilidad de workers y límites de concurrencia.
Las credenciales no pueden descifrarse
Confirma que Main, workers y webhook processors utilizan exactamente la misma N8N_ENCRYPTION_KEY. Recupera la clave original; generar una nueva no repara las credenciales existentes.
El worker aparece activo, pero no procesa trabajos
Verifica que use la misma base, Redis, versión y custom nodes que Main. Comprueba también que la concurrencia no sea cero y que PostgreSQL permita nuevas conexiones.
Los archivos desaparecen entre nodos
Revisa el modo de datos binarios. Un archivo almacenado en el filesystem de Main no estará disponible automáticamente en otro worker.
PostgreSQL pierde datos después de recrear el contenedor
En PostgreSQL 18, comprueba que el volumen esté montado en /var/lib/postgresql, no en la ruta histórica de versiones anteriores.
Redis consume demasiada memoria
Configura alertas, retención adecuada y límites evaluados. No apliques una política de expulsión arbitraria: eliminar claves de la cola puede afectar ejecuciones activas.
Advertencias de seguridad

- No publiques PostgreSQL ni Redis.
- Protege Redis con autenticación y TLS si cruza hosts.
- Guarda
N8N_ENCRYPTION_KEYfuera del repositorio. - Restringe el editor por VPN, SSO o controles del proxy.
- Protege los webhooks con autenticación o firmas.
- Revisa nodos Code, Execute Command y community nodes.
- Ejecuta todos los procesos con la misma versión.
- No almacenes secretos directamente en variables de workflow.
- Desactiva endpoints y nodos que no necesites.
- Revisa las funciones disponibles en tu plan antes de diseñar RBAC o multi-main.

Buenas prácticas para producción
- Fija imágenes a versiones o digests.
- Mantén un único Main hasta justificar multi-main.
- Escala workers según backlog y recursos.
- Agrega webhook processors solo cuando la recepción lo requiera.
- Respalda PostgreSQL y la encryption key.
- Prueba restauraciones periódicamente.
- Configura pruning de ejecuciones.
- Usa almacenamiento compartido para archivos.
- Mantén custom nodes idénticos en todos los procesos.
- Actualiza Main, workers y runners simultáneamente.
- Separa staging y producción.
- Ejecuta auditorías de seguridad.
- Mide antes y después de cada cambio de concurrencia.