/api/bookings registra P95 = 4,100 ms y P99 = 8,700 ms (×13.7 el SLA).
La introducción de pdfmake en v2.4.0 y la consulta N+1 en el filtro avanzado son los responsables primarios.
Se estiman 504 timeouts en cascada bajo carga de >40 VUs concurrentes.
| Query | Tiempo | Calls/req | Estado |
|---|---|---|---|
| SELECT * FROM bookings WHERE... | 340ms | 1 | slow |
| SELECT * FROM users WHERE id=? | 85ms ×22 | 22 | N+1 |
| SELECT * FROM spaces WHERE id=? | 42ms ×22 | 22 | N+1 |
| SELECT * FROM organizations WHERE... | 12ms | 1 | ok |
users.workspace_id e spaces.booking_date sin índice. Seq Scan en tabla de 180k filas.
Tiempo total DB por request: ~2,230ms
| Objeto | Tamaño | Retentores |
|---|---|---|
| EventEmitter listeners | 820 MB | 54,200 |
| Closure (bookingCache) | 340 MB | 12,800 |
| Buffer (pdf generation) | 280 MB | — |
| String (moment locales) | 148 MB | — |
bookingCache. pdfmake crea Buffers que no se liberan si la generación de PDF se interrumpe.
SELECT bookings.*, users.name, spaces.name FROM bookings JOIN users ... JOIN spaces .... Añadir índices en users.workspace_id y spaces.booking_date.import pdfmake from 'pdfmake' a dynamic import() dentro del handler exportPDF(). Solo se carga cuando el usuario solicita exportar. Reducción inmediata de 586 KB del bundle inicial.content: ['./src/**/*.{ts,tsx}'] en tailwind.config.ts reduce a ~8–12 KB en producción.emitter.removeAllListeners('update') al destruir instancias de BookingCache. Resolver el Buffer leak en pdfmake con try/finally { doc.end(); } para garantizar cleanup.date-fns (ya instalado como devDependency): solo se incluyen las funciones importadas. import { format } from 'date-fns' ≈ 2 KB.| Métrica | Antes | Después | Delta |
|---|---|---|---|
| P95 latencia | 4,100ms | 42ms | -99% |
| P99 latencia | 8,700ms | 180ms | -98% |
| RPS @ 40 VUs | 38 | 310 | +716% |
| Error rate | 8.4% | 0% | -100% |
| Bundle inicial | 1,846 KB | 412 KB | -78% |
| RSS Node.js | 3.8 GB ↑ | ~1.4 GB | estable |