Harness publicó una post-mortem sobre refactorizar la tabla SQL en el núcleo de su Test Intelligence Service—el backend para selección de pruebas, detección de fragilidad y seguimiento de tendencias en pipelines CI. El ingeniero Moshe Tsur documentó qué se rompió a escala, la corrección del equipo y los principios de ingeniería que aseguraron antes del rollout en producción.

El esquema original era plano y desnormalizado: una fila por resultado de prueba, con identificadores de cuenta, proyecto, pipeline y build almacenados como strings de texto plano en cada fila. Funcionaba con miles de filas. Con millones, falló de tres formas.

Primero, el 93% del almacenamiento de filas eran strings de scope duplicados. Un pipeline ejecutando 10.000 pruebas producía 10.000 copias idénticas de identificadores de cuenta y proyecto. Segundo, esas columnas de string no podían indexarse como claves foráneas enteras sobre la marcha, así que cada filtro hacía comparaciones de string completas en millones de filas—aproximadamente 10x más lento que búsquedas enteras. Tercero, el path de escritura era O(N) dentro de la solicitud HTTP: 50.000 resultados de prueba significaban 50.000 sentencias INSERT antes de que la API retornara. Bajo carga concurrente, los servicios se quedaban sin memoria y agotaban el tiempo.

La corrección fue estructural. Harness dividió la tabla en relaciones normalizadas, reemplazando identificadores de string repetidos por referencias enteras. El scope jerárquico se convirtió en claves foráneas. Los blobs de salida de prueba—stdout y stderr—fueron separados de metadatos ligeros para que las consultas de resumen dejaran de cargar columnas innecesarias. Agregados precomputados reemplazaron escaneos completos de tabla para conteos de éxito/fallo a nivel de build.

Tres principios rigieron la reescritura. La API debe realizar un número fijo de operaciones independientemente del tamaño de payload: almacenar entrada, retornar inmediatamente, procesar asíncronamente. Todo trabajo proporcional al tamaño de datos se ejecuta en pools de workers en background vía cola. Cada componente obtiene un límite de memoria explícito; procesar en chunks de tamaño fijo y liberar entre iteraciones.

Harness stress-testó antes del rollout en escenarios de ráfaga que el esquema original nunca enfrentó: 1.000 pipelines completándose simultáneamente, reportes únicos con 100.000 resultados de prueba. Esa disciplina—romper cosas en labs de prueba, no en producción—es cómo identificaron los límites originales.

Los esquemas desnormalizados optimizados para simplicidad de escritura acumulan costos de lectura ocultos. La duplicación del 93% y la lentitud de query de 10x son números reales que Harness alcanzó a escala de producción, no curvas teóricas. La penalidad string-versus-entero es fácil de descartar en tablas pequeñas; con millones de filas es el término dominante en latencia. Un path de inserción O(N) permanece invisible hasta que un reporte grande dispara OOM. Las decisiones de esquema tomadas temprano tienden a sobrevivir mucho más allá del punto donde permanecen neutras.

Si la latencia de tu write handler se escala con el tamaño de payload, has bloqueado un límite.