Cómo diseñar un sistema de versionado y control de cambios en tu aplicación web a medida
"Quien cambio esto y cuando?" Esa pregunta aparece en toda aplicacion empresarial que madura lo suficiente. A veces es un requisito legal: el RGPD exige trazabilidad sobre quien modifica datos personales. Otras veces es operativo: el departamento financiero necesita reconstruir el estado de una factura tal como estaba hace tres meses. Y muchas veces es funcional: los usuarios quieren deshacer cambios o comparar versiones.
He visto aplicaciones donde la respuesta a esa pregunta es un encoger de hombros. Un campo updated_at y poco mas. La realidad es que eso no sirve cuando un cliente te llama preguntando por que su contrato tiene un importe diferente al que firmo.
Implementar versionado de verdad no es trivial. Pero tampoco es ciencia espacial si eliges la estrategia adecuada. Vamos a recorrer las opciones, desde lo mas sencillo hasta event sourcing completo.
Tres niveles de trazabilidad: elige el tuyo
Antes de escribir codigo, necesitas decidir hasta donde quieres llegar. No es lo mismo "saber que algo cambio" que "poder rebobinar al estado exacto de hace seis meses".
Nivel 1: Audit trail basico
Registra quien hizo que y cuando. No almacena el estado anterior ni permite restaurarlo. Se implementa con una tabla de logs que guarda la accion (crear, editar, eliminar), el usuario, la fecha y la entidad afectada. Es el minimo para cumplir con el RGPD y la LOPDGDD.
Rapido de montar. Util para auditorias basicas. Pero limitado cuando alguien necesita saber que cambio exactamente.
Nivel 2: Versionado de entidades
Aqui almacenas el estado completo de cada entidad en cada momento de modificacion. Puedes responder "como estaba este registro el 15 de marzo" y comparar diferencias entre versiones. Es lo que necesitan la mayoria de aplicaciones empresariales: CRMs con historial de cambios en fichas de cliente, ERPs con trazabilidad de precios, plataformas de contenido con historial editorial.
Nivel 3: Event sourcing completo
No almacenas el estado actual. Almacenas la secuencia completa de eventos que lo produjeron. El estado se reconstruye reproduciendo los eventos desde el inicio (o desde un snapshot). Potente. Tambien complejo. Adecuado para sistemas financieros, plataformas de trading o cualquier dominio donde la integridad temporal del dato es critica.
Estrategias de implementacion
Tablas de historico
La estrategia mas directa. Para cada entidad que requiera versionado, creas una tabla espejo. Si tienes contratos, creas contratos_historico con las mismas columnas mas version_id, version_number, modified_by, modified_at y operation (INSERT, UPDATE, DELETE).
Cada vez que un registro cambia, un trigger o un hook del ORM copia el estado anterior a la tabla de historico antes de aplicar la modificacion. En PostgreSQL, un trigger BEFORE UPDATE lo resuelve limpiamente:
CREATE OR REPLACE FUNCTION contratos_audit()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO contratos_historico
(contrato_id, version_number, titulo, importe, estado,
modified_by, modified_at, operation)
VALUES
(OLD.id, OLD.version, OLD.titulo, OLD.importe, OLD.estado,
current_setting('app.current_user'), now(), TG_OP);
NEW.version := OLD.version + 1;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
Funciona bien. Se consulta con SQL estandar. Compatible con cualquier ORM. El inconveniente: cada vez que tocas el esquema de la tabla principal, tienes que actualizar tambien la tabla de historico. Y el almacenamiento crece con cada cambio.
Tabla de auditoria generica con JSONB
En lugar de una tabla espejo por entidad, metes todos los cambios en una unica tabla generica. Los estados anterior y posterior se guardan como documentos JSON:
CREATE TABLE audit_log (
id BIGSERIAL PRIMARY KEY,
entity_type VARCHAR(100) NOT NULL,
entity_id BIGINT NOT NULL,
version INT NOT NULL,
old_data JSONB,
new_data JSONB,
diff JSONB,
user_id BIGINT NOT NULL,
ip_address INET,
created_at TIMESTAMPTZ DEFAULT now()
);
El campo diff almacena solo los campos que cambiaron, calculado por la aplicacion. Esto te permite consultas como "todos los cambios que el usuario X hizo en contratos durante junio" con un solo query indexado.
Esta es la estrategia que implementan librerias populares: django-auditlog en Python, paper_trail en Ruby on Rails, laravel-auditing en PHP. En Java/Spring, Hibernate Envers ofrece una implementacion madura e integrada con JPA.
Ventaja clara: esquema unificado, funciona con cualquier entidad, y los indices GIN de PostgreSQL sobre JSONB hacen que las busquedas dentro del JSON sean rapidas. El trade-off: reconstruir el estado completo de una version antigua requiere recorrer la cadena de diffs o almacenar snapshots completos.
Event Sourcing
Event sourcing le da la vuelta al modelo mental. Los eventos son la fuente de verdad. El estado actual es una proyeccion derivada.
Para un sistema de contratos, los eventos serian algo asi:
ContratoCreado { id: 42, titulo: "Servicio anual", importe: 24000 }ImporteModificado { id: 42, importe_anterior: 24000, importe_nuevo: 28000, motivo: "Ampliacion de alcance" }ContratoFirmado { id: 42, firmante: "Maria Lopez", fecha_firma: "2026-03-15" }ContratoRenovado { id: 42, nueva_fecha_fin: "2027-12-31" }
El estado actual del contrato 42 se obtiene reproduciendo esos cuatro eventos. Para saber como estaba en cualquier fecha pasada, reproduces hasta esa fecha y paras.
En Espana, event sourcing encaja especialmente en tres sectores. El financiero, donde el Banco de Espana y MiFID II exigen trazabilidad completa. El sanitario, donde la Ley 41/2002 sobre el historial clinico pide inmutabilidad. Y el legal, donde la contratacion publica (Ley 9/2017) requiere un registro inmutable de cada paso.
Las tecnologias mas usadas: EventStoreDB (disenada para este patron), Apache Kafka (como log distribuido), y Axon Framework o Marten para Java/.NET.
La realidad es que event sourcing trae complejidad seria. Necesitas CQRS para consultas eficientes. La curva de aprendizaje es pronunciada. Y migrar esquemas de eventos una vez en produccion es doloroso. Pero cuando el dominio lo pide, no hay nada mejor.
Comparacion y diffing: mostrar que cambio
Un sistema de versionado que almacena todo pero no lo muestra bien es como un archivador donde nadie encuentra nada.
Diffing para datos JSON
El estandar de facto es JSON Patch (RFC 6902): operaciones atomicas (add, remove, replace, move, copy, test). Librerias como jsondiffpatch, dictdiffer o zjsonpatch generan estos diffs automaticamente.
Un diff entre dos versiones de un contrato:
[
{ "op": "replace", "path": "/importe", "value": 28000 },
{ "op": "add", "path": "/clausulas/5", "value": "Penalizacion por retraso: 0,5% diario" }
]
Diffing de texto enriquecido
Para campos de texto largo, los algoritmos linea a linea se quedan cortos. La libreria diff-match-patch de Google implementa el algoritmo de Myer con optimizaciones semanticas que producen diffs legibles a nivel de palabra. Si trabajas con editores como TinyMCE, CKEditor o ProseMirror, el versionado se implementa almacenando el HTML o JSON del editor y usando diffing a nivel de nodo DOM.
La interfaz de usuario marca la diferencia
He visto sistemas de versionado tecnicamente impecables que nadie usa porque la interfaz es impenetrable. Los tres componentes que hacen falta son claros.
Un timeline cronologico que muestre quien cambio que y cuando, filtrable por usuario, fechas o campo modificado. Una vista de comparacion lado a lado que resalte las diferencias entre dos versiones cualesquiera. Y una funcion de restauracion que cree una nueva version con los datos de la version seleccionada, sin borrar el historico.
Ojo con la restauracion: es un evento en si mismo que debe quedar registrado. Y no todos los usuarios deberian tener permisos para ejecutarla.
Rendimiento y almacenamiento: los numeros asustan
El volumen de datos de auditoria crece rapido. Una aplicacion con 10 000 usuarios activos modificando registros 20 veces al dia genera 200 000 entradas diarias. Unos 73 millones al ano. Como lo controlas?
Particionamiento temporal en PostgreSQL. Divides la tabla de auditoria por mes: las consultas recientes van contra particiones pequenas, el historico antiguo se queda en almacenamiento mas barato.
Politica de retencion sensata. Los ultimos 12 meses online. De 1 a 5 anos en almacenamiento frio (S3, Azure Blob Storage). Eliminar despues del periodo legal, conforme al principio de minimizacion del RGPD.
Snapshots periodicos en event sourcing. Cada 100 eventos, guardas un snapshot para evitar reconstrucciones lentas desde el evento cero.
Cumplimiento normativo en Espana
El marco regulatorio espanol tiene requisitos especificos. La LOPDGDD y el RGPD exigen registros de quien accede y modifica datos personales. La Ley 11/2007 pide trazabilidad en expedientes administrativos electronicos. Y el Reglamento VeriFactu de la AEAT obligara a mantener registros inalterables y secuenciales de facturas, con hash encadenado que impida manipulacion retroactiva.
Un sistema de versionado bien disenado convierte estos requisitos legales en funcionalidad que el usuario ni nota. Cumples porque la arquitectura cumple, no porque alguien se acuerde de rellenar un log a mano.
Errores que vemos una y otra vez
Los mas comunes: registrar solo el estado nuevo sin el anterior (imposible calcular diffs), no capturar el contexto del cambio (IP, sesion, motivo), y almacenar la auditoria en la misma transaccion que el cambio principal. Ese ultimo error acopla los dos procesos innecesariamente. Si la escritura de auditoria falla, falla tambien el cambio de negocio. La solucion: colas asincronas para la auditoria.
Cuando invertir en cada nivel
Para un MVP o una aplicacion con menos de 50 usuarios, un audit trail basico con tabla generica JSONB basta. Se monta en uno o dos dias. Para aplicaciones empresariales con cientos de usuarios y requisitos regulatorios, versionado de entidades con tablas de historico o JSONB generico cubre casi todo.
Event sourcing completo se justifica cuando los eventos de negocio son el modelo mental natural del dominio y cuando poder reconstruir el estado en cualquier punto temporal es un requisito de negocio, no solo de auditoria.
Si necesitas implementar versionado y control de cambios en tu aplicacion web y quieres saber que estrategia encaja mejor, contacta con nuestro equipo para una consulta tecnica sin compromiso.
Para cerrar
Un sistema de versionado no es un complemento que anades despues. Es una pieza estructural que afecta al modelo de datos, la arquitectura y la confianza que los usuarios tienen en el sistema. Disenarlo desde el principio sale mucho mas barato que injertarlo cuando ya hay datos en produccion. Audit trail, versionado de entidades o event sourcing: cada estrategia tiene su sitio. Lo que no cambia es la pregunta fundamental que tu sistema debe responder: que cambio, quien lo hizo, cuando y por que.
Artículos relacionados
- Cómo diseñar un sistema de versionado de contenido y auditoría de cambios para tu aplicación web a medida
- Cómo diseñar un sistema de gestión de archivos y documentos en tu aplicación web a medida
- Cómo diseñar un sistema de caché multicapa para mejorar el rendimiento de tu aplicación web a medida
Preguntas frecuentes
Las dudas más comunes. Si la tuya no está, pregúntanos
En Tangram no queremos que la información pase por una cadena interminable de intermediarios donde se pierden los detalles importantes.
Contarás con un interlocutor que coordinará la comunicación y trasladará las decisiones al equipo responsable de tu proyecto.
Cuando sea necesario profundizar en cuestiones de estrategia, diseño o tecnología, podremos involucrar a los especialistas correspondientes.
Así tendrás una comunicación organizada, sin necesidad de gestionar personalmente a todos los profesionales que intervienen.
Queremos que tengas acceso al conocimiento de un equipo especializado, sin sufrir la complejidad de coordinarlo.
No tendrás que averiguar a quién escribir cada vez que tengas una duda.
En Tangram contemplamos la figura del Account Manager como interlocutor principal, encargado de acompañarte durante el proyecto, coordinar la comunicación y facilitar el seguimiento de las decisiones.
Nuestra metodología incluye reuniones de revisión, canales de comunicación y herramientas para que puedas participar en el trabajo.
La organización concreta, la frecuencia de las reuniones y los canales disponibles se establecerán según el proyecto contratado.
Lo importante es que sepas con quién hablar, en qué punto está tu proyecto y qué decisiones necesitan tu participación.
Sí, podemos valorar una colaboración con los profesionales que ya trabajan en tu empresa.
No siempre tiene sentido sustituir un equipo que conoce bien tu negocio. En muchas situaciones, lo más útil es complementar sus conocimientos con especialistas en determinadas áreas.
Podemos estudiar qué responsabilidades asumiría Tangram, cuáles mantendría tu equipo y cómo coordinar las decisiones para evitar duplicidades.
La forma concreta de colaboración dependerá de la organización, las herramientas y las necesidades del proyecto.
No se trata de reemplazar lo que ya funciona, sino de aportar el conocimiento que necesitas para llegar más lejos.
No tienes por qué cambiar de proveedor para explorar una colaboración con Tangram.
Durante nuestra trayectoria hemos trabajado con agencias y consultoras, participando en proyectos en los que cada empresa asumía una parte diferente del trabajo.
Esa experiencia nos permite comprender la importancia de definir responsabilidades y coordinar a los profesionales implicados.
Podemos valorar una colaboración para cubrir necesidades concretas que tu proveedor actual no ofrece o para reforzar determinadas áreas.
Si tienes una relación profesional que funciona, no queremos que la rompas sin motivo. Queremos encontrar dónde podemos aportar valor.
La confidencialidad es especialmente importante cuando hablamos de nuevas ideas de negocio, información económica, estrategias comerciales o desarrollos tecnológicos.
En Tangram tenemos experiencia trabajando en proyectos sujetos a acuerdos de confidencialidad, motivo por el que no podemos mostrar públicamente muchos de los trabajos en los que hemos participado.
Si tu proyecto requiere un acuerdo de confidencialidad (NDA) antes de compartir información sensible, podemos revisar sus condiciones y acordar cómo proteger esa información antes de entrar en los detalles.
Entendemos que la confianza empieza por respetar lo que todavía no quieres hacer público.