| # | Commit | P50 (ms) | Δ Mejor | Status | Descripción del cambio |
|---|---|---|---|---|---|
| 20 | a8f3d12 | 281ms | +34ms | DISCARD | order_by optimization — sin efecto neto |
| 21 | c2e91b4 | 307ms | +60ms | DISCARD | column subset select — overhead de mapeo superior al ahorro |
| 22 | f7a06c8 | 247ms ✓ META | −20ms | KEEP | Redis result cache TTL=60s · primera vez bajo 300ms |
| 23 | 3b1d7e2 | 259ms | +12ms | DISCARD | TTL reducido a 30s — más cache misses, peor |
| 24 | 9d4f021 | 275ms | +28ms | DISCARD | cache warming en startup — latencia inicial aumenta |
| 25 | e5c83a9 | 224ms | −23ms | KEEP | query plan hint FORCE INDEX · Postgres optimizer corregido |
| 26 | 2af19d3 | 235ms | +11ms | DISCARD | EXPLAIN ANALYZE auto-hint — inestable entre runs |
| 27 | b8e74c1 | 248ms | +24ms | DISCARD | partial index tenant_id — ya cubierto por composite |
| 28 | — | N/A | — | CRASH | Cython compile error: compilador no disponible en entorno test |
| 29 | 0c62f85 | 214ms ★ BEST | −10ms | KEEP | response_model simplificado + exclude_unset=True a nivel global |
| 30 | 7e3b190 | 224ms | +10ms | DISCARD | exclude_unset per-endpoint — redundante, ya global |
| 31 | 4d91c27 | 228ms | +14ms | DISCARD | GZip middleware — overhead CPU > ahorro transferencia |
| 32 | 1f78a64 | 231ms | +17ms | DISCARD | middleware ordering auth-before-log — sin impacto medible |
| 33 | 6c24e08 | 219ms | +5ms | DISCARD | HTTP Keep-Alive header forzado — conexiones ya persistentes |
| 34 | d3b0f17 | ⏳ running | — | PENDING | prefetch_related para FK de usuarios — evaluando ahora |
42 from fastapi import APIRouter, Depends, Query 43 from typing import Optional 44- from pydantic import BaseModel, Field, validator, root_validator 44+ from pydantic import BaseModel 45 78- class SummaryResponse(BaseModel): 79- tenant_id: str = Field(..., description="Tenant identifier") 80- report_date: str = Field(..., description="ISO8601 date") 81- metrics: dict = Field(default_factory=dict) 82- metadata: Optional[dict] = Field(None) 83- _computed_at: str = Field(default="") 78+ class SummaryResponse(BaseModel): 79+ tenant_id: str 80+ report_date: str 81+ metrics: dict = {} 82+ metadata: Optional[dict] = None 83+ model_config = {"populate_by_name": True} 84 115- return JSONResponse(content=response.dict(exclude_unset=False, by_alias=True)) 115+ return response.model_dump(exclude_unset=True)