El evento de verano de Pixel Spree se lanza sin un entorno de staging realista y sin pruebas de carga. La infraestructura de Hassan se agrieta bajo un tráfico tres veces mayor al previsto por el modelo. Mariana empuja arreglos de emergencia mientras Stefan confronta a Katja por meses de evitar las preguntas difíciles sobre la planificación de capacidad. Para el viernes, el equipo ha aprendido que la exactitud del código no significa nada sin realismo operativo, pero también han quemado dos semanas de avance en la adopción de TDD en un solo fin de semana.
Katja sabía antes de abrir su portátil que el lunes iba a ser una pelea.
Había pasado el domingo leyendo los registros de Hassan del sábado por la noche: tres pruebas de carga fallidas, un entorno de staging incapaz de reflejar el comportamiento de escalado de producción, ninguna manera de saber si la infraestructura del evento de verano aguantaría el triple de tráfico sin romper algo costoso. Los había leído dos veces y luego había llamado a Stefan antes de tomarse el café.
Él había hecho una pregunta: «¿Cuál es tu tolerancia al riesgo?»
Ella había respondido con honestidad: «Cero.»
Por eso estaba de pie en la oficina de Lukas a las 08:47 con su portátil abierto, la síntesis de Navigator mostrando las mismas advertencias que la habían mantenido despierta hasta las 02:30.
—No voy a aprobar este lanzamiento —dijo.
Lukas no levantó la vista de su teléfono. —Hassan dice que estamos listos.
—Hassan dice que puede monitorear y reaccionar —corrigió Katja—. Hay una diferencia entre vigilar un incendio y tener aspersores que realmente funcionen.
Stefan estaba apoyado contra la pared con los brazos cruzados, viendo cómo la expresión de Lukas cambiaba en cámara lenta. Llevaba aquí tres días cuando Katja lo llamó la noche del domingo. Había leído los registros. Había pedido ver el entorno de staging. Había visto lo mismo que ella: un espejo que se rompía bajo carga porque en realidad no reflejaba nada, excepto los archivos de configuración de la superficie.
—No tenemos tiempo para otra ronda de pruebas de carga —dijo finalmente Lukas, sin levantar la vista de su teléfono—. Marketing ya envió la campaña de correos. Los community managers publicarán en redes sociales al mediodía. Estamos comprometidos.
—Entonces te estás comprometiendo a un desastre —dijo Katja—. Eso es todo lo que digo. No tenemos realismo operativo. Tenemos archivos de configuración y esperanza.
Lukas por fin levantó la mirada. Su rostro reflejaba ese tipo de cansancio que no mejora durmiendo. —¿Qué necesitas?
—Una semana para construir una paridad adecuada en staging. Dos semanas para pruebas de carga realistas. Un plan de contingencia que no implique editar bases de datos de producción manualmente a las 03:00.
—¿Y si lanzamos hoy y algo se rompe? —preguntó Lukas.
—Entonces lo rompemos frente a los jugadores en lugar de romper permanentemente la experiencia del jugador —dijo Katja—. Tenemos un pipeline para arreglos en caliente. Podemos parchear. Pero si lanzamos esto sin saber dónde se agrieta la infraestructura, no estamos lanzando un evento. Estamos lanzando una prueba de estrés a la paciencia de nuestro equipo.
Lukas se volvió hacia Stefan. —Tú eres el forastero aquí. ¿Qué piensas?
Stefan se despegó de la pared y caminó hacia el panel. Las proyecciones de tráfico del evento de verano se mostraban en líneas verdes brillantes que subían con el tiempo: un pico esperado de 180.000 usuarios concurrentes el sábado por la mañana. Un número que le parecía erróneo porque provenía de un modelo basado en datos del trimestre pasado sin tener en cuenta la amplificación de las redes sociales o las asociaciones con influencers que acababan de firmar.
—Llevamos meses teniendo esta conversación —dijo Stefan en voz baja—. Cada vez que decimos «necesitamos pruebas de carga», alguien dice «no tenemos tiempo». Cada vez que decimos «staging necesita paridad», alguien dice «lo podemos arreglar más tarde». El patrón es claro.
La mandíbula de Lukas se tensó. —¿Y a qué conclusión has llegado?
—A que la exactitud del código no importa si las suposiciones operativas son erróneas —dijo Stefan—. Vi a Mariana escribir una prueba el viernes que demostró que su lógica de pagos era a prueba de balas. Pasó cada prueba unitaria. Cada prueba de integración. El problema es que nadie ha probado si la infraestructura puede manejar a 180.000 jugadores intentando hacer pagos simultáneamente.
Se volvió de nuevo hacia Lukas. —Me estás preguntando si deberíamos lanzar hoy. Mi respuesta es no. No porque me oponga a enviar código a producción. Sino porque ya he visto esta película antes y termina con tres desarrolladores trabajando el domingo por la noche mientras el resto fingimos que no lo veíamos venir.
Lukas miró a Katja otra vez. Su rostro había cambiado. Ese tipo de cambio que proviene de darse cuenta de que estás a punto de tomar una decisión de la que te arrepentirás en seis meses.
—De acuerdo —dijo finalmente—. ¿Cuál es la comprobación de seguridad mínima viable?
Katja exhaló tan fuerte que lo sintió en las rodillas. —Hacemos un lanzamiento canary controlado. El 5% de los jugadores reciben el evento el lunes. Monitoreamos durante dos horas. Si nada se rompe catastróficamente, lo ampliamos al 20%. Luego al 50%. Y por último, al cien por cien.
Lukas asintió una vez. —Hacedlo.
Se dio la vuelta y salió antes de que ninguno de los dos pudiera decir nada más.
Stefan miró a Katja. —Eso salió mejor de lo que esperaba.
—Le dije la verdad —respondió ella—. A veces eso es todo lo que la gente necesita escuchar.
Cerró su portátil. —Ahora tenemos dos horas antes de que marketing lance el anuncio. Probablemente deberíamos decirles a Hassan y a Mariana lo que vamos a hacer.
El lanzamiento canary salió a producción a las 14:00 UTC.
A las 14:32, el segundo monitor de Hassan empezó a parpadear en rojo.
—Conexiones concurrentes alcanzando el límite máximo —dijo sin levantar la vista—. Estamos al 85% de capacidad con solo el 7% de los jugadores conectados.
Mariana ya estaba abriendo su terminal. —¿Cuál es el límite?
—Configuración predeterminada del balanceador de carga de hace seis meses. No está afinado para este evento.
Comenzó a teclear. —¿Podemos aumentarlo sin reiniciar?
Hassan observó cómo subían los números. —No de forma segura. Si tocamos el techo de conexiones, los jugadores comenzarán a perder paquetes. El juego se sentirá lento. Luego pensarán que es su internet y dejarán malas reseñas.
—Entonces reiniciamos —dijo Mariana.
—Eso causa una breve desconexión para todos los que estén conectados actualmente a ese nodo —explicó Hassan—. El grupo canary todavía es pequeño. Quizá dos mil jugadores como máximo en este momento.
—Hazlo.
Hassan ejecutó el comando. La gráfica se disparó brevemente cuando las conexiones se cayeron y se restablecieron, y luego se estabilizó en un número más bajo. Había aumentado el límite en un 40%.
—Nos compramos tiempo —dijo—. Pero esto no es sostenible. Necesitamos una configuración adecuada del balanceador de carga antes del sábado.
Mariana ya estaba revisando los registros de pagos. —Tenemos otro problema.
Hassan se volvió hacia su pantalla. Las transacciones de pago estaban subiendo, pero también la tasa de error. Aún no era catastrófico. Solo lo suficiente para llamar la atención.
—Tiempo de espera agotado en la pasarela de pagos —dijo Mariana—. La API externa tiene un límite de tasa que no tuvimos en cuenta. Los jugadores están intentando comprar potenciadores durante los momentos pico del evento y la pasarela los está rechazando.
—Añadimos caché el lunes —dijo Hassan—. Eso debería haber reducido la carga.
—Redujo la carga —coincidió Mariana—. Pero ahora nos estamos chocando contra los cuellos de botella de invalidación de caché en lugar de las consultas a la base de datos. El sistema no se rompió. Simplemente se rompió en otra parte.
Stefan apareció al final de la fila de escritorios sin que nadie lo notara llegar. Había estado vigilando las métricas durante diez minutos y no había dicho nada hasta ver cómo cambiaba la cara de Mariana al darse cuenta de los problemas de la caché.
—¿Qué esperabas? —preguntó Stefan en voz baja.
Mariana se giró hacia él, con los ojos brillando con esa energía peligrosa que le daba cuando estaba a punto de ser honesta de una forma que incomodaba a los ejecutivos. —Esperaba que el sistema de pagos funcionara porque le escribimos pruebas.
—Escribiste pruebas para la lógica de pagos —corrigió Stefan—. No escribiste pruebas para saber si la API externa podía manejar a 180.000 jugadores intentando comprar potenciadores simultáneamente durante un evento de fin de semana.
—Porque eso no está dentro del alcance —se defendió Mariana—. Eso es operaciones.
—Lo es ahora —sentenció Stefan—. La exactitud del código no es suficiente si tus suposiciones operativas son incorrectas. Puedes tener pruebas unitarias perfectas y aun así entregar algo que se rompa bajo carga real.
Hassan ya estaba tecleando comandos para agregar circuit breakers alrededor de las llamadas a la pasarela de pagos. —Necesitamos backoff exponencial en los reintentos. La configuración actual está martilleando la API cuando empieza a fallar, lo que empeora las cosas.
—Hecho —dijo Mariana—. Añadidas tres líneas de código que podrían salvarnos de un fallo en cascada.
Stefan la vio teclear. Estaba trabajando rápido pero sin pánico. Ahora había un ritmo en sus movimientos que no había visto antes de TDD. El tipo de confianza que viene de saber que tus pruebas detectarán regresiones mientras arreglas el problema inmediato.
—¿A cuántos jugadores afecta? —preguntó Stefan.
—Aproximadamente al 12% del grupo canary —respondió Hassan—. La tasa de errores está subiendo, pero aún no es catastrófica.
Mariana lo miró. —¿Qué pasa si no arreglamos esto antes del lanzamiento completo del sábado?
Hassan no respondió de inmediato. Miraba las gráficas y pensaba en lo que pasaría cuando ese 12% de error se aplicara a 180.000 jugadores en lugar de a dos mil.
—Tendremos jugadores enojados —dijo al fin—. Tendremos tickets de soporte. Podríamos perder ingresos para el evento. Pero no perderemos datos ni corromperemos el progreso del jugador.
—Esa es la diferencia entre un mal lanzamiento y uno catastrófico —intervino Stefan.
Mariana asintió una vez. —Entonces arreglaremos esto antes del sábado.
—Ya lo estamos haciendo —dijo Hassan, sin levantar la vista de su pantalla.
La prueba de carga debía realizarse a las 16:00.
Empezó a las 16:03 porque Hassan necesitó tres minutos más para configurar correctamente la monitorización. Ese retraso se convirtió en un desastre del que hablarían durante meses.
Habían construido la prueba sobre suposiciones que parecían razonables hasta que fallaron catastróficamente. Habían modelado el comportamiento del jugador basándose en los datos del trimestre anterior. Habían supuesto una escalada lineal de las solicitudes de pago con usuarios concurrentes. Habían supuesto que la configuración del balanceador de carga aguantaría a 3x de tráfico porque había aguantado a 2x en las pruebas.
La prueba comenzó con éxito. El sistema escaló como se esperaba hasta 50.000 conexiones concurrentes. Luego se topó con un muro que nadie había predicho.
—Pool de conexiones de base de datos agotado —anunció Hassan desde la esquina de la sala de conferencias donde había estado vigilando las métricas—. Estamos chocando contra el tamaño máximo del pool antes de llegar al límite del balanceador de carga.
Katja se volvió hacia él. —¿Cuál es el tamaño máximo del pool?
—500 conexiones —respondió Hassan—. Configurado hace seis meses cuando nuestro pico de usuarios concurrentes era de 40.000. No lo ajustamos para este evento porque pensamos que tendríamos tiempo de revisar la planificación de capacidad en el tercer trimestre.
Stefan miraba la gráfica que mostraba la CPU de la base de datos trepando hacia el 100% mientras las solicitudes de conexión se acumulaban. —¿A cuántos jugadores soportan realmente 500 conexiones?
—Depende de la complejidad de las consultas —explicó Hassan—. Con el sistema de recompensas y las actualizaciones de inventario de este evento, quizás a 8.000 usuarios concurrentes antes de que empecemos a ver agotamiento de tiempos de espera.
Mariana apareció en el marco de la puerta de la sala de conferencias con un portátil abierto y los ojos brillantes con esa energía peligrosa que le daba cuando estaba a punto de ser honesta de una manera que incomodaba a los ejecutivos. —Tenemos otro problema.
Acercó una silla y giró la pantalla hacia el grupo. La tasa de errores de la pasarela de pagos había subido del 12% durante el lanzamiento canary al 34% en las condiciones de la prueba de carga.
—La capa de caché se está invalidando con demasiada agresividad —indicó—. Cada vez que un jugador compra algo, invalidamos toda la caché del inventario de ese jugador. A gran escala, eso significa miles de fallos de caché por segundo. La base de datos está siendo golpeada dos veces: una por el agotamiento del pool de conexiones y otra por la estampida de cachés.
Stefan la observó. —¿Escribiste pruebas para este escenario?
Mariana negó con la cabeza. —Escribí pruebas para la lógica de pagos. No escribí pruebas para saber si nuestra estrategia de caché se sostendría bajo carga porque eso parecía trabajo de operaciones, no de desarrollo.
—Ese es el error —dijo Stefan en voz baja—. Seguimos separando la exactitud del código del realismo operativo. Pero son la misma cosa. Un sistema no es correcto si funciona con 10 usuarios y falla con 10.000.
Katja miraba a Hassan. —¿Qué necesitamos para arreglar esto antes del sábado?
Hassan ya estaba tecleando comandos en su terminal. —Necesitamos aumentar el tamaño del pool de conexiones. Necesitamos implementar el almacenamiento en caché de los resultados de las consultas a nivel de aplicación para que no estemos invalidando inventarios enteros por compras individuales. Y necesitamos añadir réplicas de lectura para manejar el aumento de la carga de las consultas.
—¿Cuánto tiempo? —preguntó Katja.
—Dos días, como mínimo —respondió Hassan—. Pero eso asumiendo que no rompamos nada más mientras hacemos estos cambios.
Mariana lo miró. —Podemos hacerlo escribiendo las pruebas primero. Yo escribiré las pruebas para la lógica de invalidación de la caché. Tú encárgate del pool de conexiones y de las réplicas de lectura.
Hassan asintió una vez. —De acuerdo.
Katja ya estaba mirando su teléfono. —Le voy a decir a Lukas que tenemos que retrasar el lanzamiento completo por dos días.
Stefan la vio teclear. —¿Será suficiente?
—No lo resolverá todo —admitió Katja—. Pero nos compra tiempo y reduce la exposición del jugador si algo aún se rompe.
Levantó la mirada hacia Stefan. —A esto te referías con el realismo operativo, ¿verdad? Podemos tener un código perfecto y aun así lanzar algo roto porque no probamos las cosas correctas.
Stefan asintió. —Puedes pasar todas las pruebas unitarias del mundo y seguir fallando si tus suposiciones sobre la escala son incorrectas.
Mariana ya estaba de vuelta en su escritorio tecleando pruebas. El tipo de trabajo que había empezado a hacer el lunes y que hacía a Stefan sonreír cuando pensaba que nadie lo miraba. Ya no se limitaba a arreglar problemas. Estaba escribiendo pruebas para evitar que volvieran a ocurrir.
El casi accidente ocurrió a las 19:58 del miércoles porque, por supuesto, tenía que suceder a las 19:58.
Hassan acababa de integrar el parche del pool de conexiones cuando el sistema de monitorización empezó a marcar patrones inusuales en las respuestas de la pasarela de pagos. No eran fallos todavía. Solo una latencia que aumentaba en formas que sugerían que algo estaba a punto de romperse.
—Estamos viendo que los tiempos de respuesta se duplican en las solicitudes de pago —dijo, abriendo el panel de métricas—. La pasarela todavía responde, pero a 800 ms en lugar de a 150 ms.
Mariana ya estaba revisando los registros. —¿Está saltando la limitación de tasa?
—No —respondió Hassan—. Es otra cosa. La pasarela está encolando las peticiones y procesándolas más lentamente de lo normal.
—¿Nos están estrangulando el ancho de banda? —preguntó Mariana.
—Todavía no —dijo Hassan—. Pero si los tiempos de respuesta suben otros 200 ms, empezaremos a ver tiempos de espera agotados en el lado del cliente. Los jugadores pensarán que el juego está roto y empezarán a dejar reseñas.
Stefan apareció en su fila de escritorios sin que nadie se diera cuenta de su llegada. Había estado trabajando desde su propia mesa, pero había visto subir las métricas durante diez minutos antes de acercarse.
—¿Cuál es la causa raíz? —preguntó.
Hassan se volvió hacia él. —El cuello de botella no somos nosotros. Es la pasarela. Pero la estamos desencadenando porque nuestra lógica de reintentos los está martilleando en el momento en que comienzan a ralentizarse.
Mariana ya estaba tecleando. —Así que necesitamos backoff exponencial en los reintentos con jitter.
—Exacto —confirmó Hassan—. La configuración actual hace el reintento inmediatamente al agotarse el tiempo de espera, lo que significa que si la pasarela está lenta, mandamos cinco peticiones en un segundo en lugar de una. Eso empeora el problema.
Stefan la observó teclear. Estaba trabajando rápido pero sin agitación. Ahora había un ritmo en sus movimientos que no había visto antes de TDD. La clase de seguridad que proviene de saber que tus pruebas atraparán regresiones mientras solucionas el problema inmediato.
—¿A cuántos jugadores les afecta ahora mismo? —preguntó Stefan.
—Alrededor del 5% de las sesiones activas —respondió Hassan—. Todavía no es catastrófico, pero va en aumento.
Mariana terminó de escribir e hizo push del commit. —Eso debería ayudar a reducir la carga sobre la pasarela durante los periodos de lentitud.
Hassan observó las métricas durante dos minutos. Los tiempos de respuesta empezaron a bajar hacia niveles normales. El martillo de los reintentos se había detenido.
—Nos ganamos tiempo —dijo—. Pero necesitamos hablar con el equipo de la pasarela de pagos sobre la planificación de capacidad para este evento.
Mariana lo miró. —No podemos hablar con ellos un miércoles por la noche.
—No —convino Hassan—. Pero deberíamos enviar un correo a primera hora del jueves por la mañana y solicitar una revisión de capacidad de emergencia.
Stefan los miraba a los dos con algo que podría haber sido orgullo si no estuviera demasiado cansado para sentirlo en condiciones. —Estáis haciendo el trabajo correcto —dijo en voz baja—. No solo arreglando problemas, sino evitando que vuelvan a ocurrir.
Mariana levantó la mirada hacia él. —Aunque deberíamos escribir pruebas para este escenario. Para no olvidarnos la próxima vez.
—Eso es exactamente lo que estaba pensando —asintió Stefan.
Hassan confirmó con un gesto. —Yo redactaré los casos de prueba. ¿Te encargas de implementarlo?
—Trato hecho —concedió Mariana.
Ambos volvieron a sus pantallas y reanudaron el trabajo. La oficina estaba en silencio, excepto por el tecleo y el zumbido de los servidores operando de fondo. Afuera, Berlín estaba oscuro y en gran parte inerte. Adentro, tres desarrolladores trabajaban en un problema que los mantendría despiertos hasta las 02:30 si lo permitían.
Para el viernes por la noche, la oficina volvía a sentirse diferente.
No transformada.
Eso habría sido demasiado fácil.
Pero diferente de la misma manera que se siente una habitación cuando alguien por fin abre la ventana correcta.
Katja había arrastrado a Stefan a la sala de conferencias a las 16:50 con la misma mirada que había tenido el lunes hacía dos semanas, cuando las métricas DORA aterrizaron por primera vez en su pantalla. Salvo que esta vez no era pánico. Era concentración con un rastro de satisfacción que aún no confiaba lo suficiente como para nombrar en voz alta.
Navigator llenaba la pantalla de la pared.
El panel del repositorio del backend mostraba cómo se veía una semana de cambio de comportamiento cuando se traducía en números. Los tamaños de los pull requests se habían mantenido por debajo de las cien líneas durante cuatro días consecutivos. Los comentarios de las revisiones eran más breves pero más específicos. La frecuencia de los commits había perdido su antiguo patrón de ráfagas y se había distribuido a lo largo del día laboral, como si la gente realmente estuviera integrando en lugar de acumular.
Pero la métrica más interesante era la que hizo sonreír a Katja al verla: cero incidentes en producción durante el lanzamiento del evento de verano, a pesar de haber empezado sin una paridad de staging adecuada y sin pruebas de carga.
—El canary funcionó —dijo Stefan antes de que ella pudiera preguntar.
—Sí —convino Katja—. Pero solo porque teníamos pruebas que detectaron los problemas de la pasarela de pagos el lunes y los problemas de invalidación de la caché el martes.
Hizo zoom en el gráfico del backend. La actividad de Mariana sobresalía en todos los aspectos correctos: más commits, diferencias más pequeñas, pruebas añadidas antes de los cambios de comportamiento. Un experimento revertido que había sido deshacedido en doce minutos porque la prueba fallida le dijo exactamente qué había malentendido. Fallo, contenido lo suficientemente pronto como para que resultara barato. Eso también era progreso, incluso si nadie lo ponía en una presentación de diapositivas.
—El lado de Unity todavía se ve igual —observó Katja—. Anton no ha tocado TDD.
—Probablemente no esta semana —coincidió Stefan—. Todavía está peleando con nosotros desde el interior de la conversación en lugar de desde afuera. En el lenguaje de Anton, eso es progreso.
Katja miró más allá de él, hacia la zona de QA. La Moleskine de Daniel volvía a estar cerrada, lo que se registraba como un fenómeno meteorológico después de meses de tomar notas constantemente. Estaba hablando con uno de sus probadores mientras señalaba una pantalla, y desde esta distancia Stefan no podía leer el código, pero podía interpretar su postura: curiosa, no a la defensiva.
—Esta mañana me preguntó si Navigator podía correlacionar la adición de pruebas con los defectos que se escapan a lo largo del tiempo —comentó Katja—. Y luego preguntó si QA debería empezar a escribir comprobaciones de aceptación ejecutables para las regresiones más caras en lugar de esperar a que el desarrollo les entregara tickets rotos en tres formatos distintos.
Stefan volvió a mirar la pantalla de la pared. —Ahí lo tienes —dijo.
—¿El qué?
—El momento en que la gente de procesos descubre que en realidad no quieren más puertas. Lo que quieren son mejores evidencias.
Katja se cruzó de brazos. —Estás muy complacido contigo mismo.
—Un poco.
—Qué asco.
Sonrió de todos modos, a pesar de que aún no confiaba en sí misma lo suficiente como para admitirlo en voz alta.
En la pantalla, la actividad de Hassan destacaba en todos los sentidos correctos: más commits en infraestructura, mejor documentación en los scripts de despliegue, pruebas añadidas para los escenarios de carga que habían fallado el martes. También había enviado un correo electrónico al equipo de la pasarela de pagos el jueves a las 08:15 de la mañana solicitando una revisión de capacidad de emergencia, y ellos le respondieron en dos horas con un aumento temporal del límite de tasa.
—Lee la nota de registro de Sofia —dijo Katja.
Hizo clic en la síntesis diaria del registro.
Sofia había escrito tres líneas el jueves por la noche:
Pensaba que TDD se trataba de demostrar que yo era lo suficientemente inteligente como para pensar con anticipación. No es eso. Se trata de hacer el problema lo bastante pequeño para que deje de fingir que entiendo más de lo que entiendo.
Stefan lo leyó dos veces. —Ese es todo el plan de estudios —dijo.
La boca de Katja se curvó. No en una sonrisa exactamente. En una aprobación de mejor estructura ósea.
—La de Mariana es más soez —añadió ella.
Abrió la nota siguiente.
Las pruebas no son una religión. Son declaraciones de testigos. El código miente. Las pruebas hacen que mienta menos.
Stefan se rio con tanta fuerza que Katja tuvo que esperar para seguir hablando. —No le falta razón.
—No. Rara vez se equivoca cuando está lo suficientemente enfadada. Katja echó un vistazo a la sala de backend de nuevo. —¿Y Anton?
Abrió su nota.
Era una sola frase.
Sigo odiando el sermón, pero más odio los requisitos invisibles.
Eso casi acaba con Stefan.
Katja dejó reposar el silencio después de eso. No de forma sentimental. Solo observante.
Fuera de la sala de conferencias, el viernes se iba relajando de la manera en que lo hacen las oficinas saludables. No derrumbándose. Sino apagándose. Sillas que retroceden. Música baja. Bolsos que aparecen. Hassan ya se había ido a las 17:03. El segundo jueves en dos semanas que salía a su hora, y ahora un viernes a juego. Nadie estaba en pánico. Nadie rondaba sobre el pipeline esperando un cuchillo sorpresa.
—¿Sabes qué cambió primero? —dijo Katja.
—Dime.
—No las métricas. La postura. —Hizo un gesto hacia el piso de desarrollo—. La gente parece menos acorralada. Mariana no se prepara para el golpe antes de cada merge. Sofia no se disculpa antes de hacer preguntas. Daniel sigue siendo Daniel, pero ahora tiene curiosidad. Incluso Anton está peleando con nosotros desde adentro de la conversación en lugar de desde afuera.
Stefan contempló la sala a través del cristal.
Ella tenía razón.
El cambio no era lo suficientemente dramático para los ejecutivos. Todavía no. Sin un gran antes y después. Sin una pose de héroe. Tan solo la transición, casi invisible, de un temor anticipado a una atención situacional. Los equipos que dejan de esperar a que el software les tienda emboscadas empiezan a pensar diferente. Incluso su manera de plantarse es diferente.
—¿Qué sigue? —preguntó Katja.
Esa era la verdadera pregunta. No si esta semana había funcionado. Sino si la siguiente crisis le permitiría seguir funcionando.
Stefan miró el calendario de Live Ops pegado junto a la pantalla. La planificación del tercer trimestre empieza el lunes. Lanzamiento de un evento mayor en agosto. Las mismas brechas en infraestructura por las que Daniel llevaba meses dando la tabarra. Sin un espejo de staging en condiciones. Con pruebas de carga que aún eran teóricas.
—A continuación —dijo—, la realidad verifica si el aprendizaje ocurrió a tiempo.
Katja siguió su mirada hasta el calendario.
Su cara cambió.
No a miedo exactamente.
Reconocimiento.
—El evento —dijo.
—Sí.
Se quedaron en silencio por un instante, los dos contemplando el mismo problema desde diferentes altitudes.
Luego Katja cerró el portátil.
—Bien —resolvió—. Al menos ahora, cuando se rompa, sabremos más rápido por qué.
—Ahí habla el alma de una CTO.
—Vete a la mierda —le espetó, abriendo ya la puerta.
Él la siguió de vuelta al piso de desarrollo.
Mariana levantó la cabeza inmediatamente. —¿Tenemos un veredicto? —preguntó.
Katja cogió su bolso del respaldo de la silla. —Sí —dijo—. Todos sois ligeramente menos caóticos que el lunes. No os pongáis sentimentales al respecto.
Sofia se rio.
Anton alzó una mano en una falsa bendición. —Id en paz, hijos míos de la prueba fallida.
—Sigues siendo un imbécil —replicó Mariana.
—Diseño de personaje coherente —contestó Anton.
Daniel, desde el otro lado del piso, llegó a sonreír.
Pequeño. Breve. Real.
Esa debió ser la cosa más extraña que alguien vio en toda la semana.
Navigator — Katja Müller — 12 de junio de 2026, 22:37
Semana de lanzamiento del evento de verano. El enfoque canary nos salvó de la catástrofe el lunes, cuando descubrimos bajo carga los límites de tasa de la pasarela de pagos y los cuellos de botella de invalidación de caché.
El comentario de Stefan sobre el realismo operativo caló más hondo que cualquier sermón que haya dado en años. Podemos tener pruebas unitarias perfectas y aun así despachar algo roto si nuestras asunciones sobre la escala son erróneas. Eso es lo que pasó el lunes: la lógica de pagos era a prueba de balas según cada test, pero la infraestructura no pudo gestionar patrones de tráfico reales.
Mariana adoptó el TDD inmediatamente tras descubrir esa brecha. Escribió pruebas para los escenarios de invalidación de caché la tarde del martes. Hassan implementó circuit breakers y backoff exponencial en los reintentos. Para la noche del miércoles, estuvimos a punto de tener un incidente que habría sido catastrófico de no ser por los sistemas de monitoreo que habían mejorado durante el fin de semana.
Anton sigue siendo escéptico sobre el TDD, pero admitió en su registro que odia más los requisitos invisibles que «el sermón». Daniel pregunta si QA debería redactar comprobaciones de aceptación ejecutables en vez de interpretar tickets vagos cuando desarrollo ha terminado su parte. Es posible que esté cayendo en la cuenta de que las pruebas automatizadas pueden sustituir una parte del teatro de aprobaciones que construyó para sentirse a salvo.
Señales del Navigator esta semana:
- Cero incidentes en producción durante el lanzamiento del evento de verano a pesar de haber empezado sin una paridad de staging adecuada o pruebas de carga.
- El tamaño de los pull requests en backend se mantuvo bajo las 100 líneas en toda la semana.
- Archivos de tests tocados en el 83% de los commits de backend desde el lunes.
- Comentarios de revisión de código más breves y más específicos.
- Actividad de commits distribuida a lo largo del día laboral en lugar de concentrada en el pánico del fin del sprint.
- Repositorio de Unity sin cambios hasta ahora. Escepticismo visible tanto en el código como en los registros.
La curva de adopción es irregular. Bien. El cambio verdadero es irregular.
La próxima semana toca la planificación del Q3. Todavía carecemos de un entorno de staging en condiciones que refleje el comportamiento de escalabilidad de producción. Las pruebas de carga siguen siendo teóricas. Daniel ha tenido razón en esto durante meses. Si el evento de agosto estalla por los aires, no será porque el TDD fallara. Será porque aún estamos aprendiendo una práctica mientras arrastramos la vieja deuda de infraestructura hacia un nuevo pico de tráfico.
Pero el equipo ahora reflexiona antes. En partes más pequeñas. Más claras. Eso no basta para salvarnos de todo. Quizá baste para mostrarnos con exactitud por dónde vendrá la próxima fractura.