Qué desbloquea: auditoría, tiempo y preguntas futuras
Los patrones anteriores describen un mecanismo; esta lección justifica por qué alguien pagaría su precio, y lo hace mostrando tres capacidades que no son mejoras graduales de lo que ya tenías sino cosas que sencillamente no existían. La primera es la auditoría completa por construcción: el registro no es un artefacto añadido para cumplir una norma sino el propio almacén de la aplicación, lo que elimina la posibilidad estructural de que la traza y los datos discrepen. La segunda es el viaje en el tiempo genuino, que no consiste en deshacer sino en poder proyectar el estado exacto de cualquier entidad en cualquier instante pasado, y que habilita depuración forense, reproducción de incidentes y simulaciones contrafactuales sobre historia real. La tercera, y la más valiosa a largo plazo, es la capacidad de contestar preguntas que nadie había formulado cuando se diseñó el sistema, porque plegar un registro con un reductor nuevo produce hoy respuestas sobre un pasado que en un modelo de estado actual se habría perdido para siempre. Cierra explicando por qué estas tres capacidades son la misma consecuencia de una sola decisión: no destruir información.
Hasta aquí has visto la maquinaria: un registro que solo crece, un pliegue que reconstruye y dos modelos que se reparten el trabajo. Es un montaje considerablemente más laborioso que una tabla con una sentencia de actualización, y sería razonable preguntarse qué compra exactamente ese esfuerzo. La respuesta no es rendimiento, ni elegancia, ni escalabilidad, aunque a veces caigan de propina. Lo que compra son tres capacidades que en una arquitectura de estado actual no están disponibles ni con presupuesto ilimitado, porque no dependen de cuánto trabajo hagas después sino de una información que fue destruida antes: la trazabilidad total sin coste añadido, la posibilidad de situarse en cualquier instante del pasado y verlo tal como fue, y la libertad de hacerle al pasado preguntas que nadie había imaginado cuando ese pasado ocurría. Las tres suenan a lujos de sistemas financieros, y esa impresión es el mayor obstáculo para valorarlas bien, porque las tres se vuelven urgentes en el momento más incómodo: cuando un cliente reclama, cuando un incidente hay que explicarlo, cuando alguien de negocio pregunta algo perfectamente razonable y descubres que la respuesta se sobrescribió hace catorce meses. Esta lección detalla las tres y muestra que no son tres beneficios, sino tres caras de una única decisión.
- Distinguir la auditoría por construcción de la auditoría añadida y entender por qué la segunda diverge siempre.
- Definir el viaje en el tiempo como proyección hasta una posición y separarlo del deshacer de una interfaz.
- Usar el registro para depuración forense y para simulaciones contrafactuales sobre historia real.
- Explicar por qué el modelo permite contestar preguntas no anticipadas y qué límite tiene esa promesa.
Auditoría por construcción, no por añadido
Toda organización con clientes acaba necesitando una traza de cambios, y el camino habitual para conseguirla es el mismo en todas partes: se añaden tablas de historial, disparadores que copian la fila antes de pisarla y una capa de registro en el código de servicio. Ese montaje tiene un defecto que ninguna cantidad de cuidado corrige, y es que la traza vive separada de los datos y se mantiene por convención. Basta un servicio nuevo que escriba directo, una migración que actualice en bloque, una tarea de mantenimiento nocturna o un desarrollador con prisa para que el historial y la realidad diverjan. La divergencia además es silenciosa: nadie se entera hasta que un auditor cruza ambas fuentes, normalmente dos años después, y encuentra cambios sin registrar cuya explicación ya nadie recuerda.
Merece la pena poner nombre a esa fragilidad porque explica un fenómeno que habrás visto sin identificarlo. Un sistema de auditoría añadido depende de que todo el mundo recuerde usarlo, y la memoria colectiva de un equipo es una garantía pésima cuando hay rotación de personal, presión de fechas o herramientas de administración que escriben directamente contra la base de datos. La traza es correcta mientras nadie se salte la convención, y basta una excepción para invalidar el conjunto, porque una traza incompleta es peor que ninguna: da confianza injustificada. Las garantías que dependen de la disciplina humana no escalan en el tiempo; las que dependen de la estructura sí.
Con event sourcing esa divergencia es imposible, y conviene entender bien por qué. No es que la traza esté mejor mantenida: es que no hay traza. El registro de eventos es el almacén, el único sitio donde se escribe, de modo que no puede haber un cambio no auditado por la misma razón que no puede haber un cambio no persistido. Serían el mismo cambio. La auditoría deja de ser una funcionalidad que hay que construir, probar y vigilar, y pasa a ser una propiedad estructural que se obtiene por no haber tirado nada. A eso se suma que un evento bien diseñado responde la pregunta completa —qué ocurrió, cuándo, quién lo provocó y en respuesta a qué comando—, mientras que una tabla de historial suele responder solo qué columna cambió, que es justo la mitad menos interesante.
// La consulta de auditoria no es un informe especial: es leer el almacen
const historia = await almacen.leer('cuenta-42')
for (const e of historia) {
console.log(e.en, e.tipo, e.actor, e.causadoPor)
}
// 2026-01-04 CuentaAbierta ana@banco cmd-8831
// 2026-02-11 DineroRetirado ana@banco cmd-9120
// 2026-02-11 DineroRetirado sistema job-nocturno-4 <-- el cargo disputado
Ese metadato de la última columna es el que convierte la lectura en una explicación. Saber que un cargo lo emitió un proceso automático y no una persona, y poder seguir el identificador del comando que lo originó hasta la petición que lo desencadenó, es la diferencia entre cerrar una incidencia en veinte minutos y abrir una investigación de tres días. Por eso la disciplina de incluir actor y causa en cada evento no es burocracia: es lo que hace que el registro sirva para lo que fue construido.
Un cliente afirma que nunca autorizó un cargo. Con una tabla de estado actual y su historial paralelo, el equipo reconstruye una hipótesis a partir de registros de servidor, correos y memoria. Con un registro de eventos se abre el flujo de esa cuenta y se lee la secuencia literal de lo que pasó, con instantes y actores, en el mismo lugar donde la aplicación lee el saldo. No es un informe mejor: es la diferencia entre reconstruir un relato y consultar un hecho.
Existe además una propiedad que solo aparece cuando la traza es el almacén y que interesa a cualquiera que trabaje con requisitos regulatorios: la verificabilidad. Un registro de solo anexado admite encadenar cada entrada con un resumen criptográfico de la anterior, de modo que alterar un hecho antiguo obligaría a recalcular todos los posteriores y sería inmediatamente detectable. Esa técnica, la misma que sostiene los registros distribuidos y el historial de Git, convierte la traza en algo que no solo es completo sino demostrablemente íntegro. Con tablas de historial mantenidas por convención esa garantía es sencillamente inalcanzable.
Viaje en el tiempo de verdad
El viaje en el tiempo que ofrece este modelo no tiene nada que ver con el botón de deshacer de una interfaz, y confundirlos empobrece la idea. Deshacer revierte la última acción del usuario en la sesión actual y es una función de la vista. Aquí hablamos de otra cosa: de proyectar el estado de cualquier entidad hasta una posición arbitraria del registro y obtener exactamente lo que ese objeto era en aquel momento, sin aproximaciones. Y la implementación es decepcionantemente simple, porque el mecanismo ya está construido: es el pliegue de la lección anterior, detenido antes de tiempo.
// Estado tal como era justo despues del evento numero n
const proyectarHasta = (eventos: readonly Evento[], n: number) =>
eventos.slice(0, n).reduce(aplicar, inicial)
// Estado tal como era en un instante concreto
const proyectarEn = (eventos: readonly Evento[], momento: string) =>
eventos.filter((e) => e.en <= momento).reduce(aplicar, inicial)
// Reproducir un incidente: el estado justo antes del evento sospechoso
const antesDelFallo = proyectarHasta(eventos, indiceSospechoso)
Conviene distinguir dos formas de situarse en el pasado que se confunden con facilidad, porque no responden a la misma pregunta. Una es plegar hasta la posición n, que devuelve el estado tal como el sistema lo conocía tras aquel evento. La otra es filtrar por instante, que devuelve el estado tal como era en aquella fecha del calendario. Coinciden mientras los eventos se escriban en el mismo orden en que ocurren, y dejan de coincidir en cuanto llega un hecho con retraso: una liquidación bancaria que se registra el jueves pero corresponde al lunes. Los sistemas serios distinguen por eso dos ejes temporales, el del suceso y el de su registro, y guardan ambas marcas en cada evento, porque saber qué sabíamos el martes es una pregunta distinta de saber qué pasó el martes.
De esas tres líneas cuelgan capacidades muy distintas entre sí. La primera es la depuración forense: cuando un usuario reporta un comportamiento extraño, no necesitas reproducir su entorno ni adivinar en qué estado se encontraba, porque puedes situarte en el instante exacto y observar el estado real que su código estaba viendo. La segunda es la reproducción de incidentes en pruebas: el registro de producción, anonimizado, es el mejor conjunto de casos de prueba que tendrás nunca, porque contiene secuencias que ningún equipo habría imaginado. La tercera es la más ambiciosa y se llama simulación contrafactual: como el reductor es una función pura sobre la historia, puedes cambiar el reductor y volver a plegar los mismos hechos para responder qué habría pasado si la regla hubiera sido otra. Qué ingresos habríamos tenido con la política de descuentos nueva aplicada al año pasado no es una estimación con este modelo: es un pliegue sobre datos reales.
Depuracion forense
Situarte en el estado exacto que el usuario tenía cuando falló. Sin reproducir su entorno, sin adivinar, sin pedirle capturas de pantalla que nunca llegan.
Reproduccion en pruebas
El registro real, anonimizado, es el mejor banco de casos que tendrás. Contiene secuencias que ningún equipo habría inventado porque nacieron de usuarios reales.
Simulacion contrafactual
Cambiar la regla en el reductor y volver a plegar los mismos hechos para ver qué habría ocurrido. Comparación entre mundos sobre datos verdaderos.
Diagnostico de regresiones
Plegar el registro con el reductor viejo y con el nuevo y comparar. Si divergen donde no debían, la regresión aparece antes de llegar a producción.
flowchart LR E0[evento 0] --> E1[evento 1] --> E2[evento 2] --> E3[evento 3] --> EN[evento n] E1 -.pliegue parcial.-> S1[estado en enero] E3 -.pliegue parcial.-> S3[estado antes del incidente] EN -.pliegue completo.-> SN[estado actual] style S3 fill:#f9e2af,color:#11111b style SN fill:#a6e3a1,color:#11111b
Preguntas que aún no sabes que tendrás
Hay una advertencia práctica que acompaña a estas capacidades y que conviene no pasar por alto: reproducir historia real en un entorno de pruebas exige tratar esos datos con el mismo cuidado que en producción. Un registro completo de eventos es, por definición, el conjunto de datos más sensible de la organización, porque contiene no solo el presente sino todo lo que alguna vez fue cierto. Anonimizar antes de reproducir no es una formalidad de cumplimiento sino una condición para poder usar la técnica sin crear un riesgo mayor que el problema que se estaba depurando.
La última de esas cuatro capacidades tiene una implicación que trasciende la depuración y llega hasta el proceso de desarrollo. Cuando el estado se deriva de una función pura sobre hechos persistidos, cualquier cambio en esa función se puede evaluar contra la historia completa antes de desplegarlo. No hablamos de pruebas con datos inventados por un programador optimista, sino de ejecutar la lógica nueva sobre cinco años de comportamiento real y observar exactamente qué entidades cambian de estado y cuáles no. Pocas técnicas dan tanta confianza antes de un despliegue, y ninguna está disponible si los hechos no se guardaron.
Las dos capacidades anteriores son valiosas, pero la tercera es la que decide el retorno de la inversión a largo plazo, y es también la más difícil de defender en una reunión porque su beneficio es futuro y su coste es presente. Formulada con precisión: un modelo de estado actual solo puede contestar las preguntas que su diseñador anticipó, porque solo se guardó lo que hacía falta para contestarlas. Un registro de eventos puede contestar cualquier pregunta que los hechos registrados soporten, incluidas las que nadie había formulado cuando esos hechos ocurrieron.
Analitica retroactiva
Escribes hoy un reductor nuevo y lo pliegas sobre cinco años de historia. Obtienes la métrica como si la hubieras estado midiendo desde el principio, no una estimación.
Contrafactuales
Cambias la regla en el reductor y vuelves a plegar los mismos hechos. Comparas dos mundos sobre datos reales en lugar de discutir sobre intuiciones.
Comportamiento, no solo resultado
El registro guarda el camino, no solo el destino. Cuántas veces se dudó, qué se probó y se descartó, cuánto se tardó entre dos pasos: intención observable.
Modelos nuevos gratis
Una función del producto que nadie había pensado puede arrancar con historia completa el día uno, porque sus datos ya estaban ahí esperando un reductor.
La objeción razonable a este entusiasmo es que ya existe una industria entera dedicada a capturar comportamiento con herramientas de analítica, y que instalar una es más barato que rediseñar la persistencia. Es verdad y también incompleto. Esas herramientas capturan lo que alguien decidió instrumentar, viven fuera del sistema, no comparten su noción de verdad y con frecuencia discrepan de él en las cifras, lo que obliga a reconciliaciones penosas. El registro de eventos no compite con ellas en visualización, pero tiene una propiedad que ninguna posee: es el mismo dato que la aplicación usa para funcionar, de modo que no puede estar en desacuerdo consigo mismo.
Un ejemplo concreto ayuda a calibrar el valor de esto. Una empresa decide en marzo medir el abandono de carrito por franja horaria, una métrica que nunca existió. Con un modelo de estado actual, la respuesta es que se empieza a instrumentar hoy y en junio habrá tres meses de datos, con el matiz incómodo de que esos tres meses no incluyen la campaña de Navidad, que es justo lo que se quería estudiar. Con un registro de eventos, la respuesta es que mañana hay cinco años de la métrica, incluidas todas las campañas, porque los hechos que la componen se llevan escribiendo desde el principio y solo faltaba alguien que los plegara con la pregunta adecuada. La diferencia no es de velocidad: es que en un caso la respuesta existe y en el otro no.
El techo lo pone la calidad del evento
Conviene poner el límite de la promesa, porque exagerarla es la vía rápida al desengaño. El registro contesta cualquier pregunta que sus eventos soporten, no cualquier pregunta imaginable. Si tus eventos son pobres —si se llaman RegistroActualizado y llevan un volcado de columnas— tendrás toda la historia y ninguna comprensión, porque conservaste el qué y volviste a perder el porqué. La capacidad de contestar preguntas futuras no la da el mecanismo: la da la calidad semántica con que nombraste y modelaste los hechos. Ese es el trabajo intelectual real de este enfoque, y no admite atajos ni automatización.
De ahí se deduce una regla de diseño que va contra el instinto de todo programador entrenado en normalizar: los eventos deben ser generosos, no mínimos. Guardar el identificador del producto y confiar en que la tabla de precios responderá luego es un error, porque esa tabla cambiará y el pasado quedará reescrito por accidente. Un evento debe capturar el valor que se aplicó en aquel momento, la regla que estaba vigente y el contexto que la explicaba, porque nada de eso se puede volver a consultar. La redundancia que en un esquema relacional sería un defecto aquí es una condición de fidelidad histórica, y es la diferencia entre un registro que explica el pasado y uno que solo lo apunta.
Esa generosidad tiene un límite que también conviene fijar, porque un evento no es un contenedor donde volcarlo todo por si acaso. Lo que debe viajar dentro es aquello que forma parte del hecho: los valores aplicados, la identidad de quien actuó, la causa que lo originó y la versión de la regla vigente. Lo que no debe viajar es el estado completo de la entidad tras el cambio, porque eso es una proyección disfrazada de hecho y ata el registro a una interpretación concreta que mañana querrás cambiar. La línea entre ambas cosas es fina y se aprende equivocándose, pero la pregunta que la marca es simple: esto que estoy metiendo, es parte de lo que ocurrió o es una conclusión que saqué de ello.
Antes de dar por bueno el diseño de un evento, imagina a alguien que dentro de diez años lo lee sin acceso al código, a la base de datos ni a nadie del equipo original. Si con lo que hay dentro del evento puede reconstruir qué pasó, por qué se permitió y con qué reglas, el diseño es bueno. Si necesita consultar otra tabla que quizá ya no exista, o interpretar un identificador cuyo significado nadie recuerda, el evento está incompleto y lo descubrirás cuando ya sea tarde.
Hay además un tipo de información que solo este modelo captura y que suele pasar desapercibido: el comportamiento, no el resultado. Un estado actual dice que el usuario compró; el registro dice que dudó cuatro veces, que quitó el artículo y lo volvió a poner, que tardó once minutos y que abandonó dos veces antes de decidirse. Esa diferencia entre destino y trayecto es la materia prima de la investigación de producto, y en la mayoría de las empresas se compra a un proveedor externo de analítica precisamente porque la aplicación la tiró. Cuando el registro es el almacén, esa información ya está en casa y no ha costado nada adicional recogerla.
Merece la pena ver estas tres ventajas por lo que realmente son, porque presentarlas como una lista de funcionalidades oculta lo esencial. No son tres cosas que event sourcing hace bien: son tres manifestaciones de una única decisión tomada al principio, la de no destruir información. La auditoría es esa decisión mirada desde el cumplimiento normativo. El viaje en el tiempo es la misma decisión mirada desde la depuración. La analítica retroactiva es la misma decisión mirada desde el negocio. Y como las tres brotan de la misma raíz, no se pueden comprar por separado ni instalar después: no existe una librería que te devuelva la auditoría de los tres años en que estuviste sobrescribiendo filas, porque el problema nunca fue de herramientas sino de que los datos ya no están. Esto invierte la forma correcta de evaluar el patrón. La pregunta útil no es si necesitas event sourcing hoy, que casi siempre se responde que no, sino cuánto te costará no tenerlo el día que lo necesites, y ese día suele llegar sin avisar, con forma de reclamación, de auditoría o de una pregunta razonable de alguien de producto. La destrucción de información es la única decisión de arquitectura verdaderamente irreversible que tomas: todo lo demás —el lenguaje, el framework, el motor, la estructura de carpetas— se puede migrar con suficiente dinero y paciencia, pero un hecho que no escribiste no vuelve. Por eso conviene decidirlo con los ojos abiertos y no por costumbre, que es como se decide casi siempre.
- Implementa
proyectarHastayproyectarEny reconstruye el estado de una entidad en tres instantes distintos de su historia. - Inserta un error a mitad del registro, sitúate en el estado justo anterior y explica qué habrías podido diagnosticar que hoy no puedes.
- Escribe un reductor nuevo que responda una métrica que nunca mediste y pliégalo sobre todo el registro. Compara el resultado con lo que podrías estimar sin él.
- Diseña un contrafactual: cambia una regla de negocio en el reductor, vuelve a plegar y contrasta ambos mundos sobre los mismos hechos.
- Revisa tus nombres de eventos y marca cuáles son mecánicos y cuáles capturan intención. Reescribe los mecánicos y razona qué preguntas desbloquea cada cambio.
- Estima en horas lo que costaría hoy contestar una auditoría de dos años en tu proyecto actual, y compáralo con abrir un flujo de eventos.
- Añade a tus eventos las dos marcas temporales, la del suceso y la de su registro, y construye un caso con retraso donde ambas proyecciones difieran.
- Aplica la prueba del arqueólogo a tres eventos de tu diseño y reescribe los que necesiten consultar otra tabla para ser comprensibles.