Una de las pantallas de TourTracker tenía un botón inocente: Exportar a PDF. Funcionaba perfectamente con conjuntos de datos normales, pero el día que mi mujer (mi primera y mejor tester) probó a darle con 60.000 registros, la pestaña del navegador se quedó pensando hasta que Chrome la mató. Ahí se encendió la luz: algo había que hacer.
El reflejo del desarrollador
Cuando ves un proceso pesado que congela el navegador, el cerebro de programador entra en modo "optimizo lo que sea". Web Workers, virtual lists, renderizar el PDF en servidor, trocear en streaming, mover a un job en background con notificación por email... la lista de soluciones técnicas es larga, y todas son válidas. El problema es que ninguna se hace en una tarde.
Antes de tirarme a por la primera de la lista, lo puse encima de la mesa con Claude Code, esperando que me ayudara a elegir cuál era el camino más razonable.
La pregunta que cambió todo
Su respuesta no fue ninguna de esas. Fue otra pregunta:
"¿De verdad alguien va a leer un PDF de 60.000 filas? ¿Para qué se exporta esto a PDF?"
Me quedé en blanco. La realidad es que nadie iba a leer un PDF así. Nadie lo iba a imprimir, nadie iba a hacerle scroll de cabo a rabo. Si alguien quería trabajar con 60.000 filas, lo que necesitaba era una hoja de cálculo: filtrar, ordenar, cruzar, pegar en otro sitio. El PDF, por su propia naturaleza, está pensado para que un humano lo abra y lo lea. Cuando lo que tienes es un volcado masivo, el formato correcto siempre es CSV o XLSX, no PDF.
La conversación con mi mujer fue tan corta como concluyente: "¿Tú lo abrirías?". "Para nada, ni de coña.". Decisión tomada.
El fix: un cap, un mensaje, y toda la app arreglada de golpe
Aquí es donde la decisión arquitectónica anterior pagó el dividendo. Todas las pantallas de la aplicación que ofrecen exportación a PDF pasan por una única función exportToPdf. No hay lógica de exportación duplicada en cada vista. Eso significaba que con tocar un solo punto, toda la aplicación quedaba blindada a la vez.
El cambio fue mínimo: meter un tope de filas razonable y, cuando se supera, devolver un mensaje claro al usuario explicando que el conjunto es demasiado grande para un PDF y sugiriéndole que filtre, o que use la exportación a CSV o XLSX si lo que necesita es procesar los datos. Sin rediseños, sin Web Workers, sin reescribir nada. Una decisión de criterio, aplicada en el cuello de botella correcto.
Dos lecciones que me llevo
La primera es que la mejor optimización es, muchas veces, no hacer la cosa. Antes de invertir días en hacer que un proceso pesado vaya rápido, merece la pena parar treinta segundos y preguntarse si ese proceso debería existir tal como está planteado.
La segunda es que los guards se meten donde converge la lógica, no en cada pantalla. Si tu aplicación crece sin un punto único de paso para acciones comunes (exportar, imprimir, descargar, enviar), cada decisión que tomes la vas a tener que replicar N veces y mantenerla sincronizada. Tener un único exportToPdf que decide qué se puede y qué no es la diferencia entre un fix de cinco minutos y un fix de cinco días.
Y, como casi siempre, el aprendizaje no salió de leer un libro de arquitectura: salió de mi mujer probando la herramienta como una usuaria real y de una conversación que empezó con la pregunta correcta.


