La mayoría de este hilo contiene consejos genéricos de observabilidad. Las partes específicas de n8n son donde viven realmente las respuestas a tus cinco preguntas, así que:
La profundidad de la cola y la carga por inquilino ya están expuestas — no tienes que construirlas. n8n incluye un endpoint de Prometheus que está desactivado por defecto: N8N_METRICS=true te da /metrics en el principal. Las banderas que importan para tu caso son N8N_METRICS_INCLUDE_QUEUE_METRICS (esa es tu queue_depth), N8N_METRICS_INCLUDE_WORKFLOW_ID_LABEL y N8N_METRICS_INCLUDE_NODE_TYPE_LABEL (series por flujo de trabajo y por tipo de nodo, que es cómo “qué inquilino está generando más carga” y “qué API externa es lenta” se convierten en una sola consulta de PromQL en lugar de un proyecto de registros). Extrae los datos a lo que ya ejecutes. Observa la cardinalidad si tienes muchos flujos de trabajo — la etiqueta workflow-id es lo que la hace útil y también lo que la hace costosa.
Tu métrica error_rate te mentirá, y esta es la que muerde a escala multiinquilino. Una ejecución de n8n finaliza con estado success en muchos casos donde en realidad no sucedió nada: un nodo que devuelve cero elementos simplemente pasa cero elementos aguas abajo y todo lo que viene después se omite silenciosamente; un IF sin rama coincidente; la salida done de un Split In Batches que nadie conectó. La ejecución está en verde, la tasa de error se mantiene plana, y los datos del inquilino simplemente no se movieron. Así que no solo monitorees los errores — afirma los resultados. Emite un recuento de elementos al final de cada flujo de trabajo del inquilino y alerta en processed == 0 cuando cero no es un resultado legítimo. El éxito silencioso es el modo de fallo que llega a tus clientes antes de que llegue a tu panel.
“Detectar problemas antes de que los clientes lo noten” necesita un interruptor de vigilancia, no una alerta. El Error Trigger / Error Workflow es el gancho de alertas correcto por inquilino — configúralo por flujo de trabajo, e incluye lo suficiente en la carga útil para que sea procesable ($execution.id, el nombre del flujo de trabajo, el nodo que falla, y los datos del último nodo; una alerta que solo dice “flujo de trabajo fallido” te cuesta una sesión de depuración cada vez). Pero ten en cuenta qué es lo que estructuralmente no puede hacer: el Error Trigger nunca se dispara para una ejecución que nunca comenzó. Un disparador de programa atascado, un worker bloqueado, un flujo de trabajo que alguien desactivó — todos producen silencio, y el silencio se ve exactamente como “todo está bien.” La solución es invertida: haz que cada flujo de trabajo del inquilino envíe un ping a un perro guardián al completarse, y alerta cuando el ping está ausente. Esa única verificación detecta toda la clase de fallo que tus registros no pueden ver por construcción.
Tu cuello de botella es probablemente execution_entity. A volumen multiinquilino, la tabla de datos de ejecución es lo que hace que Postgres sea lenta, y crece silenciosamente. EXECUTIONS_DATA_PRUNE=true con un verdadero EXECUTIONS_DATA_MAX_AGE y EXECUTIONS_DATA_PRUNE_MAX_COUNT, y para inquilinos de alto volumen considera EXECUTIONS_DATA_SAVE_ON_SUCCESS=none — mantener cargas útiles de éxito completas para cada ejecución es un costo grande para datos que nunca abrirás. Limpia antes de optimizar consultas; mucho de “n8n es lento” resulta ser esto.
Una cosa que vale la pena decidir temprano ya que eres multiinquilino: esa tabla de ejecución contiene las cargas útiles reales de tus inquilinos. Si alguno de ellos está en la UE, la base de datos de ejecución es una ubicación de procesamiento, y la retención allí es una pregunta de cumplimiento, no solo una de espacio en disco. Es mucho más barato establecer la política ahora que explicarla después.