4. El análisis del incidente: convertir un susto en una regla
Nivel 11: Cuando falla
Ha pasado algo. Ya está arreglado, el sistema vuelve a operar y todo el mundo tiene ganas de olvidarlo. Ese es exactamente el momento en que un equipo decide si va a mejorar o si va a repetir el mismo incidente dentro de siete meses con otro disfraz. El análisis del incidente es el mecanismo que convierte un susto en una regla, y es la pieza que separa un sistema que envejece bien de uno que solo acumula cicatrices.
Sin culpables, y no por educación
La regla de no buscar culpables no es una cortesía: es lo que hace que la información aparezca. En cuanto alguien intuye que el análisis termina con un nombre, los detalles incómodos dejan de contarse, y son justo los detalles incómodos los que explican el fallo. Además, casi siempre la persona que apretó el botón es el último eslabón de una cadena que llevaba meses montada.
Que no haya culpables no significa que no haya responsables del arreglo. Cada acción correctiva sale del análisis con un nombre y una fecha, o no existe.
La cronología con marcas de tiempo
El análisis empieza siempre por la misma tabla mental: qué pasó y cuándo, con la hora exacta y en zona horaria única. Y aquí se ve para qué servía todo el registro que montaste antes:
- Hora del primer evento anómalo, que casi nunca coincide con la hora en que alguien se dio cuenta.
- Hora de detección, y por qué medio: una alarma automática, un cliente, la casualidad.
- Hora de la primera acción, y qué se hizo.
- Hora de contención y hora de resolución, que tampoco son la misma cosa.
La distancia entre el primer evento y la detección es la métrica más reveladora de todas. Si tu incidente empezó a las 09:31 y lo detectaste a las 11:40 porque te llamó alguien, tu problema principal no es el fallo: es que estuviste dos horas ciego. Sin marcas de tiempo fiables en tus propios registros, esta cronología no se puede construir; el extracto del bróker te dice qué se ejecutó, pero no qué creía tu sistema en cada instante ni por qué decidió lo que decidió.
Causa aparente y causa raíz
La causa aparente es la última cosa que se rompió. La causa raíz es la razón por la que esa rotura pudo llegar hasta el dinero. Un método sencillo es seguir preguntando por qué hasta que la respuesta deje de ser técnica:
- El sistema vendió el doble de lo debido. ¿Por qué? Porque el proceso se reinició y reenvió la orden.
- ¿Por qué la reenvió? Porque al arrancar se creyó el estado en disco.
- ¿Por qué se lo creyó? Porque el arranque no consultaba al bróker.
- ¿Por qué no lo consultaba? Porque nadie había escrito nunca qué debía pasar al arrancar con posición abierta.
La causa aparente era el reinicio. La causa raíz es que no existía una política de arranque. Fíjate en que la cadena atraviesa los tres módulos anteriores: un fallo de infraestructura, una decisión de arranque y la ausencia de un límite que lo atrapara.
Todo incidente termina en una comprobación nueva o en un límite nuevo
Esta es la regla práctica del módulo, y es innegociable. Un análisis que termina en tendremos más cuidado, hay que revisar mejor los despliegues o el operador ya sabe que no debe hacer eso no ha producido nada. La atención no es un mecanismo: no se puede desplegar, no se puede probar y se agota a las tres de la tarde. Las salidas válidas son tres: una comprobación automática nueva, un límite duro nuevo o la eliminación de la posibilidad de cometer el error.
def test_no_reenvia_orden_tras_reinicio():
"""Reproduce el incidente 2026-03-11 con sus datos exactos."""
broker = BrokerFalso(posiciones={'ACME': 0})
estado = EstadoFalso(intencion={'ACME': -300, 'confirmada': False})
resultado = arranque_seguro(broker, estado, politica_quieta)
assert estado.freno_activo()
assert broker.ordenes_enviadas == []
assert 'intervencion' in resultadoEsa prueba es el verdadero producto del incidente. Mientras exista, el fallo no puede volver en silencio: cualquiera que rompa esa propiedad lo sabrá antes de desplegar. Y la ficha del incidente se guarda con la misma disciplina, versionada junto al código:
incidente = {
'id': '2026-03-11-01',
'primer_evento': '2026-03-11T09:31:04Z',
'deteccion': '2026-03-11T11:40:12Z',
'medio_deteccion': 'aviso de un tercero',
'causa_aparente': 'reinicio del proceso',
'causa_raiz': 'no existia politica de arranque con posicion abierta',
'impacto_eur': -4120,
'control_nuevo': 'arranque_seguro obligatorio + freno por divergencia',
'prueba': 'test_no_reenvia_orden_tras_reinicio',
'responsable': 'pol',
'fecha_limite': '2026-03-18',
}El campo que más duele es el del medio de detección. Si la mayoría de tus incidentes los descubre alguien de fuera, tu problema no está en el código: está en que tus alarmas no vigilan lo que importa.
Caso real: la cronología de Knight y qué habría cambiado
Volvamos al 1 de agosto de 2012. La causa aparente de aquel incidente fue un despliegue incompleto: código nuevo que no llegó a todos los servidores de enrutamiento, dejando activo un componente antiguo. La causa raíz es más incómoda y mucho más útil: no existía ninguna verificación automática de que el despliegue hubiera quedado igual en todas las máquinas, ni un procedimiento que obligara a atender los avisos automáticos que llegaron antes de la apertura, ni un límite propio capaz de decir que el volumen de órdenes de esa mañana era imposible.
Ese es el resumen del nivel entero. La detección tardó demasiado, la respuesta no estaba escrita de antemano y no había ningún tope que actuara sin pedir permiso. Unos 440 millones de dólares en menos de una hora, y las tres acciones correctivas que lo habrían evitado son aburridísimas: comprobar el despliegue, escalar los avisos y contar las órdenes.