Módulo 6: Reintentos, alertas y recuperación
8. Capstone: un sistema multi-workflow confiable de punta a punta
Descripción
Al terminar esta lección vas a tener construido, corriendo y defendible un sistema de automatización de varios workflows confiable de punta a punta: el sistema de Cumbre que recibe pedidos por un webhook que a veces dispara dos veces, valida cada entrada contra un contrato, deduplica con un ledger en Postgres, ejecuta efectos idempotentes, coordina cuatro sub-workflows con el patrón outbox, reintenta sin duplicar, compensa lo que queda a medias, alerta solo donde importa, y enruta los fallos reales a una cola de mensajes muertos. Y —la prueba corona— vas a poder mostrar un replay que demuestra que un disparo duplicado no crea un segundo efecto. Este es el entregable de portafolio de toda la guía: el "armador de flujos contra dueño de un sistema de automatización" convertido en algo que puedes abrir en una entrevista y defender decisión por decisión.
Esto importa porque un capstone no es un ejercicio más: es la evidencia. Cualquiera puede decir "sé de idempotencia y manejo de errores". Muy pocos pueden abrir un sistema real, mostrar el grafo de dependencias, señalar la clave de idempotencia elegida y por qué, y ejecutar un replay en vivo que prueba que el sistema no se duplica. Esa diferencia —entre afirmar y demostrar— es exactamente la que separa a quien se contrata como dueño de un sistema de quien se contrata como armador de flujos. El capstone es donde construyes esa evidencia, con tu nombre, sobre un caso que dominas.
Conexión con el módulo y la guía: esta lección no introduce ningún concepto nuevo. Integra los seis módulos. La idempotencia del Módulo 2, los contratos del Módulo 3, el ledger del Módulo 4, la coordinación con outbox del Módulo 5, y las cinco piezas de este Módulo 6 —reintentos, compensaciones, alertas, error workflow con cola de mensajes muertos, y replay— se juntan aquí en un solo sistema. Si algo de lo que sigue no te resulta familiar, ese es el módulo al que conviene volver un momento. Y honra la frontera de la lección 7: el capstone demuestra correctitud, no operación; usar las credenciales de n8n y una sola instancia es lo correcto para este alcance.
Lo que vas a entregar
Un sistema con esta forma, funcionando de punta a punta, más tres artefactos que valen tanto como el sistema:
webhook (a veces dispara 2 veces)
│
▼
┌─────────────┐
│ order-triage│ 1. dedup contra run_ledger
│ │ 2. valida contra el contrato
└──────┬──────┘ 3. escribe intents en outbox
│
┌───────────┼───────────┐
▼ ▼ ▼
┌────────────┐ ┌──────────┐ (consumidores del outbox)
│check-credit│ │inventory-│
│ (efecto) │ │sync(efec)│
└─────┬──────┘ └────┬─────┘
│ falla a media│ falla al reservar
▼ ▼
┌──────────────────┐ ┌────────────────────┐
│ issue-refund │ │ cumbre-error-handler│
│ (compensación) │ │ (Error Trigger) │
└──────────────────┘ │ ├─ alerta (crítico)│
│ └─ dead_letter │
└────────────────────┘
Los cuatro workflows de negocio (order-triage, check-credit, inventory-sync, issue-refund), más el error workflow central (cumbre-error-handler), más las tablas en Postgres (run_ledger, outbox, dead_letter). Y los tres artefactos de defensa:
- El grafo de dependencias, con las claves de idempotencia anotadas en cada efecto.
- La justificación de diseño: por qué cada decisión, y qué se rompería con la alternativa.
- El replay de prueba: la evidencia grabada de que un disparo duplicado no crea un segundo efecto.
Sobre el tiempo: si vienes construyendo los proyectos de cada módulo, la mayor parte de las piezas ya existe y este capstone es sobre todo integrarlas y defenderlas —unas dos o tres horas—. Si empiezas de cero, cuenta una jornada. La parte de defensa —los tres artefactos— no es opcional ni es "documentación al final": es la mitad del valor del entregable.
Fase 1 — El esqueleto: entrada, dedup y contrato
Dónde estás: con una instancia Community y el Postgres del Starter Kit, y las tablas del Módulo 4 creadas.
El corazón de la confiabilidad empieza en la puerta: order-triage es lo que hace que el webhook poco fiable —que a veces dispara dos veces— no ensucie todo lo que viene después.
Paso 1.1 — El webhook y la clave de idempotencia. El Webhook recibe el pedido. Lo primero es calcular la clave de idempotencia del pedido, con un nodo Code de pura lógica —recuerda: la clave se deriva de datos estables, nunca de la hora—:
// ============================================================
// Nodo: Code — "Build order key" (en order-triage)
// Modo: Run Once for Each Item
//
// ENTRADA: el pedido crudo del webhook
// SALIDA: el pedido con su clave de idempotencia estable
// POR QUÉ: esta clave gobierna el dedup y sobrevive a un disparo doble
// ============================================================
const order = $json;
// Estable: mismo pedido -> misma clave, aunque el webhook dispare 2 veces.
// NUNCA metas Date.now() ni un random aquí (ver lección 6).
const orderKey = `order:${order.order_id}`;
return { json: { ...order, idempotency_key: orderKey } };
Paso 1.2 — El dedup atómico contra el ledger. Aquí está la lección más importante del sistema, y la que la lección 6 te enseñó a depurar. El dedup no es "consulta el ledger, y si no está, sigue" —eso es la trampa de verificar-y-luego-actuar, que produce el duplicado cuando dos disparos corren a la vez—. El dedup es una escritura condicional atómica: intentas insertar la clave en el ledger, y la propia base de datos, con una restricción de unicidad, garantiza que solo una de dos ejecuciones simultáneas lo logre. La otra choca y se detiene. Con el nodo Postgres:
-- Nodo: Postgres — "Claim order in ledger"
-- Solo UNA ejecución logra insertar; la segunda no afecta filas.
INSERT INTO run_ledger (order_id, idempotency_key, status, created_at)
VALUES ($1, $2, 'claimed', now())
ON CONFLICT (idempotency_key) DO NOTHING
RETURNING order_id;
Qué esperar. Si el webhook disparó una vez, el INSERT devuelve el order_id y el flujo sigue. Si disparó dos veces casi simultáneas, solo una de las dos ejecuciones recibe una fila de vuelta; la otra recibe cero filas —porque ON CONFLICT DO NOTHING—, y con un nodo If que revise si volvió una fila, esa segunda ejecución se detiene sin hacer nada. El disparo duplicado muere aquí, en la puerta, de forma atómica. Esta es la pieza que el replay de la fase 6 va a probar.
Paso 1.3 — Validar el contrato. Antes de despachar el trabajo, order-triage valida que el pedido cumple el contrato de entrada del Módulo 3: que order_id, amount y line_items estén presentes y con el tipo correcto. Si no cumple, el pedido no sigue: se enruta al fallo (que la fase 5 captura). Un pedido mal formado no debe llegar a check-credit.
Paso 1.4 — Escribir los intents en el outbox. En vez de llamar directo a check-credit e inventory-sync, order-triage escribe intenciones en la tabla outbox (Módulo 5): "para este pedido, hay que verificar crédito y reservar inventario". La decisión de qué hacer se separa de la ejecución, para que el fan-out sea confiable aunque algo falle en el momento.
Fase 2 — Los efectos idempotentes
Dónde estás: con el pedido deduplicado, validado, y sus intents en el outbox.
Los consumidores del outbox ejecutan los efectos. Cada uno es idempotente, porque cada uno puede reintentarse (fase 4) o reprocesarse desde la cola (fase 5).
Paso 2.1 — check-credit. Lee su intent del outbox, y coloca la retención de crédito con un HTTP Request que lleva la clave de idempotencia como header (Módulo 2 + lección 2). La API de crédito reconoce claves repetidas: dos intentos con la misma clave colocan una sola retención. Al éxito, registra en el ledger que este pedido tiene una retención activa —dato que la compensación de la fase 3 necesita—.
Paso 2.2 — inventory-sync. Lee su intent, y reserva el stock con un upsert idempotente por order_id (Módulo 2): reservar dos veces el mismo pedido deja el inventario en el mismo estado que reservarlo una vez. Nunca un decremento ciego.
Qué esperar. Con los dos efectos idempotentes, todo el fan-out es seguro de repetir. No importa cuántas veces se procese un intent —por un reintento, por un reproceso—: el resultado es el mismo que procesarlo una vez. Esta es la propiedad que hace que el resto del sistema (reintentos, cola) pueda existir sin miedo.
Fase 3 — La compensación
Dónde estás: con check-credit habiendo colocado la retención, e inventory-sync que acaba de fallar porque no hay stock.
Es el escenario de la lección 3: un efecto (la retención) quedó huérfano porque un paso posterior falló, y no se puede "no haber hecho". Se compensa.
Paso 3.1 — Detectar y decidir compensar. Cuando inventory-sync no puede reservar, escribe una intención de compensación en el outbox: release_credit_hold para este order_id, con el credit_hold_id guardado en el ledger. Decidir compensar y ejecutar la compensación son pasos separados (patrón outbox), para que la compensación no dependa de que todo funcione en el instante caótico del fallo.
Paso 3.2 — Ejecutar la compensación. issue-refund lee las intenciones release_credit_hold y libera la retención con un HTTP Request que lleva su propia clave de idempotencia (derivada del credit_hold_id), con Retry On Fail activado —seguro, porque la liberación es idempotente—. Al éxito, marca en el ledger hold_status = 'released' y el intent como done.
Qué esperar. El pedido que no se pudo surtir termina con su retención liberada automáticamente, sin dejar crédito bloqueado. Y como la compensación es idempotente, liberar dos veces cuenta como una. El sistema se limpia solo.
Fase 4 — Reintentos seguros
Dónde estás: con los efectos y la compensación funcionando en el camino feliz.
Ahora endureces contra los fallos transitorios. En cada nodo HTTP Request que tiene un efecto —check-credit, issue-refund, y las reservas de inventory-sync— activas Retry On Fail (lección 2), con Max Tries en 2 o 3 y una Wait Between Tries de al menos 1000 ms.
La regla que gobierna esta fase: cada reintento que activas es seguro porque el efecto que reintenta es idempotente (fase 2). No activas Retry On Fail en nada que no esté protegido por una clave de idempotencia o un upsert. Los nodos que reciben respuestas de negocio —"crédito rechazado", "sin stock"— no llevan reintento: esas no son fallas transitorias, son resultados que un If enruta.
Qué esperar. Un timeout aislado de la API de crédito ahora se cura solo: n8n espera un segundo, reintenta, la API responde, y el pedido sigue sin que nadie se entere. Los fallos transitorios dejan de ser incidentes.
Fase 5 — Alertas y cola de mensajes muertos
Dónde estás: con reintentos absorbiendo lo transitorio; falta capturar lo terminal.
Paso 5.1 — El error workflow central. Creas cumbre-error-handler con un Error Trigger como primer nodo (lección 5), y lo asignas en Options > Settings > Error workflow de los cuatro workflows de negocio. Un solo embudo para todos los fallos.
Paso 5.2 — Clasificar y enrutar. Un nodo Code lee el payload del Error Trigger (workflow.name, execution.lastNodeExecuted, execution.error.message, execution.id) y decide la severidad según la política de la lección 4: issue-refund es critical siempre; el resto, warning. Un Switch enruta: los críticos disparan un HTTP Request de alerta a finanzas y se guardan; todos se guardan en dead_letter.
Paso 5.3 — No perder nada. Cada fallo terminal se inserta en dead_letter con el payload completo del pedido, status = 'pending', para reprocesarlo después con su clave de idempotencia original.
Qué esperar. En un día normal, con reintentos y compensaciones trabajando, este handler produce cero o una alerta. Cuando issue-refund agota sus reintentos, finanzas recibe una alerta útil —con order_id y enlace a la ejecución— y el pedido queda guardado, no perdido. Señal, no ruido.
Fase 6 — El replay que lo demuestra
Dónde estás: con el sistema completo. Ahora produces la evidencia corona.
Esta fase es la que convierte tu capstone de "confía en mí, no se duplica" a "míralo con tus propios ojos". Vas a demostrar que un disparo duplicado no crea un segundo efecto.
Paso 6.1 — Producir un disparo duplicado. Con el efecto real desconectado o simulado (lección 6: nunca contra la API real), dispara el webhook dos veces con el mismo pedido ORD-3180, lo más simultáneas que puedas.
Paso 6.2 — Observar las dos ejecuciones. En la lista de ejecuciones vas a ver dos ejecuciones de order-triage. Cárgalas con Debug in editor y traza, en cada una, el INSERT ... ON CONFLICT del paso 1.2.
Qué esperar, y esta es la prueba. Una de las dos ejecuciones recibió una fila de vuelta del INSERT y siguió adelante hasta colocar la retención. La otra recibió cero filas —chocó contra la restricción de unicidad— y se detuvo en el If posterior, sin llegar a ningún efecto. Resultado: una retención, un pedido procesado, a pesar de dos disparos. El grafo, la clave de idempotencia y estas dos ejecuciones lado a lado son tu prueba grabada. Guárdala: es lo que abres en la entrevista.
Paso 6.3 — El contraejemplo (opcional pero potente). Para que la prueba tenga fuerza, muestra también qué pasaría sin la protección. Reemplaza temporalmente el dedup atómico por un "consulta y luego actúa" (la trampa del Módulo 2), reproduce el disparo doble, y observa que ahora ambas ejecuciones ven el ledger vacío y colocan retención: dos retenciones. Restaura el dedup atómico. Ese contraste —duplicado con la trampa, no-duplicado con la escritura atómica— es la demostración más contundente que puedes dar de que entiendes por qué funciona, no solo que funciona.
Criterios de evaluación
Repásalos antes de dar por cerrado el capstone. No son opcionales: son lo que hace el entregable defendible.
- Idempotencia: cada efecto (
check-credit,inventory-sync,issue-refund) lleva una clave de idempotencia derivada de datos estables, o un upsert idempotente. Puedes señalar cada una en el grafo. - Dedup atómico:
order-triagededuplica con una escritura condicional atómica (ON CONFLICT), no con verificar-y-luego-actuar. Puedes explicar por qué esa diferencia importa. - Contratos: cada sub-workflow valida sus entradas en la frontera (Módulo 3); un pedido mal formado no llega a los efectos.
- Coordinación con outbox: el fan-out y las compensaciones pasan por la tabla
outbox; decidir y ejecutar están separados. - Reintentos seguros: Retry On Fail está activado solo en efectos idempotentes; los resultados de negocio se enrutan, no se reintentan.
- Compensación: existe una compensación para cada efecto reversible, y es idempotente.
- Alertas calibradas: el error workflow alerta solo de fallos reales según una política por workflow; en un día normal produce cero o una alerta.
- Cola de mensajes muertos: ningún fallo terminal se pierde;
dead_letterguarda el pedido completo para reproceso. - Replay de prueba: tienes grabadas dos ejecuciones de un disparo duplicado que muestran una sola retención, y puedes explicar por qué.
- Frontera declarada: puedes decir qué de tu sistema es correctitud (todo lo anterior) y qué sería operación (secretos externos, staging, Git, backups), sin confundirlos.
Las decisiones de diseño, argumentadas
El último artefacto, y el que más pesa en una entrevista, no es código: es tu capacidad de justificar cada decisión. Aquí están las cinco que más te van a preguntar, con el nivel de respuesta esperado. Escríbelas para tu propio sistema.
1. ¿Por qué el dedup es una escritura atómica y no una consulta previa? Porque el webhook dispara dos veces casi simultáneas, y una consulta previa ("¿existe? no, entonces sigo") deja una ventana en la que las dos ejecuciones ven el ledger vacío antes de que ninguna escriba, y ambas siguen. La escritura condicional con restricción de unicidad no tiene esa ventana: la base de datos garantiza que solo una inserción gana, sin importar cuán cerca corran. Es la diferencia entre confiar en el tiempo y hacer que el tiempo no importe.
2. ¿Por qué la clave de idempotencia se deriva del order_id y no del momento? Porque una clave tiene que ser estable para que un reintento, un disparo doble o un reproceso tardío la reconozcan como la misma. Una clave con Date.now() cambia en cada ejecución, y la protección se cae —es el bug que trazaste en la lección 6—. El order_id identifica el pedido sin importar cuándo se procese.
3. ¿Por qué compensar en vez de evitar el efecto? Porque no hay una transacción atómica que abarque la API de crédito y el sistema de inventario —son sistemas distintos—. No puedes garantizar "los dos o ninguno". Lo mejor posible es: si el segundo falla, deshaces el primero. Eso es una saga, y la compensación es su mecanismo.
4. ¿Por qué issue-refund alerta siempre y un timeout de crédito no? Porque un reembolso atascado es dinero real en el limbo que ningún mecanismo automático va a soltar —terminal—, mientras que un timeout que se cura al reintentar es transitorio. Alertar de los dos igual produciría fatiga de alertas y enterraría el que importa. La política es por workflow y por gravedad.
5. ¿Está listo para producción? Es correcto —idempotente, con contratos, con recuperación, demostrable con el replay— y corre gratis en Community. Lo que faltaría para operarlo con un equipo —secretos externos, staging, Git, backups— es operación, un proyecto aparte con sus propias decisiones, tratado en n8n-production-maintenance-guide. El diseño está listo; la puesta en producción es el siguiente paso. (Esta es la respuesta de la lección 7, y es la que cierra la entrevista.)
Errores comunes
Presentar el sistema sin poder demostrar el no-duplicado (conceptual). Qué pasa: se construye todo correctamente pero, en la entrevista, ante "¿cómo sé que no se duplica?", solo se puede afirmar que no lo hace, sin mostrarlo. La respuesta pierde toda su fuerza. Por qué pasa: construir se siente como el trabajo, y la demostración parece un extra. Es al revés: la demostración es el entregable. Cómo detectarlo: si no tienes grabadas dos ejecuciones de un disparo doble mostrando una sola retención, te falta la prueba. Cómo corregirlo: haz la fase 6 y guarda la evidencia. Un sistema que no puedes demostrar correcto es, en una entrevista, indistinguible de uno que no lo es.
Confundir "más piezas" con "mejor" (conceptual). Qué pasa: se agregan reintentos en todos los nodos, alertas de todo, compensaciones para efectos que ya eran idempotentes —"por robustez"—, y el sistema se vuelve un enredo que produce fatiga de alertas y reintentos inútiles. Por qué pasa: cada pieza del módulo se siente buena, y más buenas parece mejor. Cómo detectarlo: si tienes reintentos en lecturas, alertas de fallos transitorios, o compensaciones de cosas que no crean nada, sobra maquinaria. Cómo corregirlo: cada pieza responde a un modo de falla concreto. Reintenta lo que falla transitoriamente y es idempotente; compensa lo que crea algo irreversible; alerta lo terminal. Un sistema confiable es preciso, no recargado. Poder explicar por qué no pusiste una pieza es tan valioso como explicar por qué pusiste otra.
Tratar el capstone como el final del camino (conceptual). Qué pasa: se termina el capstone y se archiva, como quien cierra un libro. Pero un capstone es un punto de partida: es el sistema que llevas a producción, el que muestras en entrevistas, el que adaptas a tu próximo trabajo. Por qué pasa: el formato "proyecto final" sugiere clausura. Cómo detectarlo: si tu capstone vive en una carpeta que no vas a volver a abrir, lo estás desperdiciando. Cómo corregirlo: trátalo como portafolio vivo. Actualízalo cuando aprendas algo nuevo, adáptalo cuando cambies de caso, y —cuando estés listo— llévalo a producción de verdad con la guía de operación. El capstone no cierra tu aprendizaje; lo inaugura como práctica.
Ejercicios
Ejercicio 1 — Defiende una decisión. Elige una de las cinco decisiones de diseño argumentadas de esta lección y reescríbela con tus palabras, en tu contexto, como si respondieras a un entrevistador que acaba de preguntarte "¿y por qué lo hiciste así?". Incluye qué se rompería con la alternativa.
Ver solución
No hay una respuesta única, porque el punto es que suene tuya. Una respuesta fuerte tiene tres partes: (1) la decisión, (2) el porqué en términos del modo de falla que previene, y (3) qué se rompería con la alternativa —esto último es lo que la mayoría olvida y lo que más impresiona—.
Ejemplo, para la decisión del dedup atómico: "Deduplico con un INSERT ... ON CONFLICT, no consultando primero el ledger. Lo hice así porque el webhook a veces dispara dos veces casi al mismo tiempo, y si consultara primero, las dos ejecuciones verían el ledger vacío antes de que ninguna escriba, y ambas procesarían el pedido: dos retenciones. Con la escritura atómica, la base garantiza que solo una inserción gana, sin importar cuán cerca corran. Lo probé reproduciendo un disparo doble: una ejecución sigue, la otra choca y se detiene. Con la alternativa —consultar primero— pude reproducir el duplicado a voluntad."
Fíjate en que la respuesta nombra el modo de falla (disparo doble simultáneo), explica el mecanismo (la restricción de unicidad no tiene ventana), y cierra con evidencia (lo probé, y el contraejemplo lo confirma). Esa estructura convierte una decisión técnica en una respuesta de entrevista memorable.
Por qué funciona: en una entrevista para dueño de sistemas, no se evalúa si conoces la sintaxis —eso se asume—; se evalúa si entiendes por qué una decisión es correcta y qué falla previene. Practicar la defensa de tus propias decisiones es practicar exactamente lo que se contrata.
Ejercicio 2 — Encuentra el eslabón débil. Un compañero te muestra su sistema de Cumbre. Deduplica con un INSERT ... ON CONFLICT, valida contratos, coordina con outbox, tiene reintentos y alertas. Pero su clave de idempotencia para el reembolso es `refund:${order.order_id}:${Date.now()}`. ¿Está su sistema realmente protegido contra reembolsos dobles? Explica.
Ver solución
No, tiene una grieta grave, y es sutil porque todo lo demás está bien. El dedup atómico de order-triage protege contra el disparo doble del webhook —dos eventos casi simultáneos—. Pero la clave del reembolso lleva Date.now(), que cambia en cada ejecución. Eso significa que si issue-refund se reintenta (fase 4) o se reprocesa desde la cola (fase 5) en un momento distinto, genera una clave nueva, y la API de pagos la ve como un reembolso diferente. El reintento seguro de la lección 2 y el reproceso de la lección 5 —las dos cosas que su sistema tiene— se convierten, con esa clave, en máquinas de duplicados.
Es exactamente el bug de la lección 6. El sistema está protegido contra un modo de falla (disparo doble) pero abierto de par en par a otros dos (reintento y reproceso), y el eslabón débil es una sola línea que "parece" correcta porque incluye el order_id. El arreglo: quitar Date.now(), dejando `refund:${order.order_id}`.
Por qué funciona: este ejercicio entrena el ojo para el fallo más común y más escondido de estos sistemas. La correctitud no es "tener todas las piezas"; es que las piezas sean coherentes entre sí. Una clave inestable rompe silenciosamente todas las protecciones que dependen de repetir con seguridad, aunque cada pieza por separado se vea bien.
Ejercicio 3 — Extiende el sistema. Cumbre agrega un quinto efecto: cuando un pedido se surte por completo, hay que enviar la factura por correo (send-invoice). Sin construirlo, responde: ¿en qué posición del orden de efectos va y por qué?, ¿necesita clave de idempotencia y de qué se deriva?, ¿qué severidad de alerta le corresponde si falla?, y ¿tiene compensación?
Ver solución
Orden: al final, después de que crédito, inventario y —si aplica— el cobro tuvieron éxito. El correo es un efecto irreversible (lección 3): una vez enviado no se retira, así que solo debe salir cuando el pedido es seguro y no hay riesgo de tener que desmentirlo.
Clave de idempotencia: sí la necesita, derivada de datos estables como `invoice:${order.order_id}` —nunca con la hora—. Sin ella, un reintento del envío mandaría dos facturas iguales del mismo pedido, un duplicado que en un documento fiscal sí importa.
Severidad si falla: media, en general. Una factura que no salió hoy puede salir mañana sin drama —no hay dinero en movimiento como en un reembolso atascado—. Va a la cola de mensajes muertos como warning, para que finanzas reintente el envío o corrija el dato del correo. La política es por workflow (lección 4), y este no es issue-refund.
Compensación: no tiene una limpia, porque el correo es irreversible. La "compensación" posible es otra comunicación que corrija —"hubo un error con tu factura"—, que no deshace la primera. Por eso el orden importa tanto: al ir al final, casi nunca hay que corregir, porque solo se envía cuando el pedido ya está firme.
Por qué funciona: extender el sistema con un efecto nuevo es aplicar todo el módulo junto en una sola decisión. Orden (lección 3), idempotencia (Módulo 2 + lección 2), severidad (lección 4), compensación (lección 3): cada efecto nuevo que agregues a cualquier sistema pasa por estas mismas cuatro preguntas. Que las respondas sin dudar es la señal de que el módulo quedó internalizado.
Resumen y cierre de la guía
Llegaste al final, y vale la pena mirar el camino completo antes de cerrar.
Empezaste esta guía sabiendo construir workflows que funcionan una vez. Terminas siendo dueño de un sistema de automatización que sobrevive a lo que el mundo real le tira. En el Módulo 1 hiciste el cambio de mentalidad —de armador de flujos a dueño de sistema— y aprendiste a ver la diferencia entre una lectura y un efecto, entre "al menos una vez" y "exactamente una vez". En el Módulo 2 hiciste idempotentes tus efectos, para que repetir no duplique. En el Módulo 3 pusiste contratos entre workflows, para que se hablen sin romperse. En el Módulo 4 diseñaste el ledger, para que la verdad del sistema viva en un lugar y la deduplicación sobreviva entre ejecuciones. En el Módulo 5 coordinaste varios workflows con el patrón outbox, separando decidir de ejecutar. Y en este Módulo 6 lo volviste resiliente: reintentos que no duplican, compensaciones que deshacen lo que quedó a medias, alertas que suenan solo donde importa, un error workflow con una cola de mensajes muertos que no pierde nada, un replay que convierte un bug intermitente en uno reproducible, y una frontera clara con lo que sigue.
Y en este capstone lo juntaste todo en un sistema de Cumbre que puedes abrir, ejecutar y defender: con su grafo, sus claves de idempotencia, y un replay que prueba —no afirma, prueba— que un disparo duplicado no crea un segundo efecto. Eso es el entregable. Eso es lo que separa, en una entrevista y en un trabajo real, a quien arma flujos de quien posee un sistema.
Hay una honestidad final que esta guía se debe a sí misma. Lo que construiste es correcto, y correr un sistema correcto gratis en Community es un logro real. Lo que sigue —operarlo en producción con un equipo: secretos externos, entornos, Git, backups, escalado, monitoreo— es otra disciplina, tratada en serio en n8n-production-maintenance-guide. No es que tu sistema esté incompleto; es que el diseño de la correctitud, que es lo que esta guía prometió enseñarte, está terminado. La operación es el siguiente capítulo, y ahora sabes exactamente dónde empieza.
Te felicito por llegar hasta aquí. Seis módulos de disciplina —idempotencia, contratos, ledgers, coordinación, recuperación— no son un camino corto, y el sistema que tienes al final lo demuestra. Cuando alguien te pregunte "¿qué pasa si la API se cae a media ejecución?", ya no tienes que improvisar: tienes un sistema que responde esa pregunta, y sabes por qué responde así. Ese es el resultado. No está nada mal para quien empezó armando flujos que funcionaban una vez.
Recursos
- Error handling — n8n Docs — la referencia que reúne los reintentos, el Error Trigger y los error workflows que integraste en el capstone.
- Error Trigger — n8n Docs — el nodo del
cumbre-error-handlercentral, con el payload que clasificas en la fase 5. - Debug and re-run past executions — n8n Docs — la herramienta del replay de la fase 6, con la que produces la prueba del no-duplicado.
- Postgres node — n8n Docs — el nodo del ledger, el outbox y la cola de mensajes muertos, con el
INSERT ... ON CONFLICTdel dedup atómico. - Self-hosted AI Starter Kit — n8n — el kit gratuito con Postgres sobre el que corre todo el sistema del capstone a costo cero.
- n8n production maintenance — n8n Docs — el punto de partida hacia la operación en producción, el siguiente paso una vez que tu sistema es correcto.