Saltar al contenido

Volver a proyectos

Rendimiento

Recortando segundos de latencia con una caché que en realidad no existía

· 6 min

Un backend corriendo en un entorno serverless, con una base de datos compatible con SQLite en el borde, tenía un puñado de endpoints consistentemente lentos, no bajo picos de tráfico, sino incluso en uso normal, con una única solicitud aislada. La lógica de negocio detrás de ellos era simple; nada explicaba la demora.

Ilustración de un cronómetro marcado con una X

Rastreando la lentitud hasta la capa de datos

Los logs mostraban que el tiempo no estaba en las rutas ni en el motor de la base de datos en sí, sino en algo que ocurría antes de que corriera cualquier query útil. Toda la aplicación pasaba por un contenedor de dependencias que armaba más de diez repositorios en cada solicitud, y cada repositorio, al instanciarse, tenía un método de inicialización de esquema que debía correr solo una vez por proceso.

La caché que existía en el papel, pero no en el código

El mecanismo para evitar ese trabajo repetido ya estaba diseñado: cada repositorio guardaba una referencia pensada para funcionar como caché del estado "esquema ya validado". El problema es que esa referencia nunca se leía ni se llenaba de verdad, existía como campo, pero nada en el flujo verificaba su valor antes de repetir el trabajo. En la práctica, esto equivalía a no tener ninguna caché: cada solicitud recreaba el contenedor entero y, para cada uno de los repositorios, rehacía verificaciones y ajustes de esquema, CREATE TABLE, verificación de columnas, alteraciones condicionales, creación de índice, incluso en un proceso ya calentado, que había hecho exactamente el mismo trabajo en la solicitud anterior.

La corrección: hacer que la caché funcionara de verdad

La corrección no fue arquitectónica, fue hacer que el mecanismo de caché que ya existía funcionara de verdad: llenar y verificar esa referencia de estado por repositorio, para que la validación de esquema solo corriera la primera vez que el proceso lidiaba con él, y guardar la instancia del contenedor de dependencias en el ámbito del módulo en vez de recrearla en cada llamada. El cambio se aplicó de forma uniforme en todos los repositorios del sistema, no solo en los identificados como lentos, evitando dejar el mismo problema latente en otro lugar.

Resultado

Las solicitudes que antes llegaban a tardar segundos por este trabajo repetido pasaron a responder en pocos milisegundos, sin ningún cambio de infraestructura, solo haciendo que la caché que ya estaba diseñada en el código funcionara como debía desde el principio.