Evolución de una plataforma documental
Asumí la dirección técnica de una plataforma documental y ayudé a modernizarla por etapas, mientras seguíamos entregando mejoras a sus usuarios.
-
Menos trabajo repetido
Construí componentes compartidos que facilitaron el desarrollo de nuevas funciones.
-
Procesamiento más fiable
Ayudé a mejorar el procesamiento de documentos y el seguimiento del trabajo.
-
Continuidad del producto
El producto siguió evolucionando durante la modernización.
Contexto
La plataforma permitía cargar documentos, buscar en su contenido y organizar el conocimiento que contenían. Había crecido sobre un monolito: muchas funciones compartían la misma aplicación y acumulaban dependencias. Añadir capacidades exigía entender qué otras partes podían verse afectadas, mientras los usuarios seguían esperando mejoras.
El procesamiento documental tenía además un ritmo distinto al de la interfaz. Extraer texto de un archivo o reconocerlo en una imagen podía tardar, fallar o necesitar otro intento. El producto tenía que mostrar ese avance y permitir investigar qué había ocurrido cuando un documento no quedaba disponible.
Mi papel y liderazgo técnico
Asumí la dirección técnica de la aplicación. Decidía con el equipo qué capacidades extraer del monolito, cómo estructurar los nuevos servicios y qué trabajo de calidad necesitaba acompañar la evolución. Participé directamente en el desarrollo y coordiné los cambios con las personas responsables de infraestructura y pruebas.
Creé una base común para que los demás desarrolladores pudieran construir sobre ella. Incluía una plantilla de servicio preparada junto con infraestructura y una librería para las operaciones de datos que se repetían. Acompañé su adopción y mentoricé a perfiles con menos experiencia, ayudándoles a entender las convenciones y a aplicarlas en nuevas funcionalidades.
Mi ámbito de decisión era la aplicación. La infraestructura tenía sus propios responsables y las prioridades se acordaban con producto. Esa coordinación importaba cuando un cambio requería modificar código y despliegue a la vez: una pieza podía estar terminada para desarrollo y seguir necesitando trabajo para funcionar en el conjunto.
Desafíos y trade-offs
Optamos por una modernización gradual, ligada a las funcionalidades que el producto necesitaba entregar. Extraer una capacidad concreta permitía mejorarla sin esperar a sustituir toda la aplicación. A cambio, convivían partes del monolito con servicios nuevos y había que mantener su integración durante la transición.
La separación también añadía coste operativo. Cada servicio necesitaba despliegue, configuración y diagnóstico propios. Algunas dependencias de datos seguían compartidas, de modo que separar el código no daba autonomía completa. Había que valorar si el beneficio de cada extracción compensaba el esfuerzo adicional de mantenerla.
La base reutilizable tenía un límite parecido. Compartir operaciones repetidas ayudaba a trabajar con consistencia; intentar resolver cualquier caso desde una misma abstracción podía hacer más difícil entenderlo. Concentré esa base en el trabajo común de los servicios y mantuve las reglas particulares en cada funcionalidad.
Una base de desarrollo compartida
La plantilla establecía la estructura de un servicio y su preparación para desplegarlo. La construí en colaboración con infraestructura para que las nuevas piezas partieran de una base conocida. Los desarrolladores podían dedicar antes su atención a la funcionalidad que debían implementar.
La librería común reunía operaciones repetitivas de creación, consulta y modificación de registros. Permitía declarar esos comportamientos de forma consistente, reduciendo código que de otro modo se habría copiado entre servicios. También construí una capa para acceder al almacenamiento de archivos sin repetir la integración en cada parte de la aplicación.
Estas piezas se utilizaron dentro del equipo. Mi trabajo de liderazgo incluía explicar su funcionamiento y acompañar a otros desarrolladores cuando las incorporaban. La reutilización empezó a formar parte de la manera de desarrollar nuevas capacidades, con menos diferencias accidentales entre implementaciones.
Procesamiento documental asíncrono
Uno de los cambios más concretos fue extraer el procesamiento de documentos a un flujo asíncrono. Al recibir un archivo se generaba trabajo en una cola. Procesos en segundo plano, o workers, recogían ese trabajo y ejecutaban la extracción de texto o el reconocimiento de caracteres cuando el documento lo requería.
El estado de cada fase quedaba registrado en la base de datos. La aplicación podía distinguir entre trabajo pendiente, en curso, terminado o fallido sin depender de que la petición inicial permaneciera abierta. Esto separaba la recepción de un documento del tiempo necesario para procesarlo y hacía más fácil seguir su avance.
También revisé el acceso a datos. Encontré consultas poco eficientes y un mismo modelo utilizado para necesidades muy distintas. Propuse diferenciar los registros estructurados de las relaciones entre documentos, que requerían otra forma de consulta. Esa propuesta quedó como una línea de evolución; no fue una migración de datos completada.
Operación y límites de la migración
El procesamiento seguía teniendo fallos difíciles de investigar. Algunos trabajos quedaban incompletos y los registros de ejecución no siempre se conservaban. En ocasiones había que reproducir el problema para obtener información suficiente. Mejorar los estados ayudó al diagnóstico, pero la recuperación de ejecuciones interrumpidas seguía necesitando trabajo.
Los reintentos tampoco distinguían bien entre errores temporales y problemas que iban a repetirse. Volver a ejecutar un trabajo podía resolver una interrupción puntual o consumir recursos sin cambiar el resultado. Esa diferencia debía quedar representada en el comportamiento del sistema.
La coordinación entre aplicación y despliegue fue otra dificultad. Los cambios de configuración requerían pasos separados y podían quedar desacompasados con el código. Señalé esa fricción, aunque no conseguí cambiar el modelo de trabajo durante mi etapa. La extracción de servicios avanzó, pero las nuevas necesidades del producto siguieron entrando y la modernización quedó incompleta.
Resultados
El equipo siguió entregando funcionalidades mientras renovaba partes de la plataforma. El procesamiento documental ganó fiabilidad, se amplió el soporte de formatos y fue más fácil reconocer en qué estado se encontraba un trabajo.
La plantilla y los componentes compartidos redujeron la repetición y facilitaron crear nuevos servicios. Dejé una base utilizada por otros desarrolladores y acompañé su adopción, además de dirigir las decisiones de evolución de la aplicación. Las mejoras fueron observables en el trabajo del equipo, aunque no dispongo de una medición que permita expresarlas como un porcentaje.
La plataforma conservó partes del monolito y limitaciones operativas. La separación de responsabilidades había avanzado; terminarla y mejorar la recuperación de fallos requería continuar la inversión.
La separación de responsabilidades mejoró el producto mientras seguía en uso. La modernización quedó en curso.
Qué aprendí y qué cambiaría
Hoy exigiría que cada extracción incluyera una forma de observar el servicio y recuperar el trabajo interrumpido. En el procesamiento asíncrono definiría cuándo se confirma que una tarea ha terminado, qué ocurre si se repite y cómo se detiene un worker sin abandonar trabajo en curso. También conservaría los registros necesarios para investigar errores sin tener que reproducirlos.
Haría más explícito el coste de cada nueva petición antes de incorporarla al plan. En este proyecto acepté cambios sin aclarar siempre qué desplazaban o cuánto complicaban la transición.
Para los desacuerdos sobre operación, llevaría propuestas más pequeñas, con un responsable y una comprobación concreta del resultado. Detecté fricciones, pero me faltó convertir algunas de ellas en cambios que el equipo pudiera priorizar y ejecutar.