Surfaced reviewing #387, which points the landing hero at GET /api/v1/leaderboard?period=contest. That makes the highest-traffic anonymous surface in the product issue an uncached rebuild against the 512MB free-tier instance that also serves /app and the protocol surfaces.
Nothing on the path caches the response:
api/routers/leaderboard.py:30 sets no Cache-Control and no ETag.
dashboard/frontend/vercel.json forces Cache-Control: no-store on /(api|paper|backtest|runs|config|admin|ticker|health|compare)(/.*)?, so the Vercel edge cannot absorb any of it either.
- The caches that do exist in
domain/leaderboard/service.py (_cached_run_index, the skip cache) select which run to draw; they do not memoise the built response.
Per request that means all 12 configured entries get a _find_cached_run lookup plus a db.get_equity_curve, then align_equity_curves over the lot. Measured against a local backend on the committed seed DB: 12 entries x 162 points.
The contest window is fixed and historical, so this is the single most cacheable thing the backend produces. A short public, max-age=... on period=contest plus dropping no-store for that one path would remove the load.
Two things to keep in mind for whoever picks this up:
Surfaced reviewing #387, which points the landing hero at
GET /api/v1/leaderboard?period=contest. That makes the highest-traffic anonymous surface in the product issue an uncached rebuild against the 512MB free-tier instance that also serves/appand the protocol surfaces.Nothing on the path caches the response:
api/routers/leaderboard.py:30sets noCache-Controland noETag.dashboard/frontend/vercel.jsonforcesCache-Control: no-storeon/(api|paper|backtest|runs|config|admin|ticker|health|compare)(/.*)?, so the Vercel edge cannot absorb any of it either.domain/leaderboard/service.py(_cached_run_index, the skip cache) select which run to draw; they do not memoise the built response.Per request that means all 12 configured entries get a
_find_cached_runlookup plus adb.get_equity_curve, thenalign_equity_curvesover the lot. Measured against a local backend on the committed seed DB: 12 entries x 162 points.The contest window is fixed and historical, so this is the single most cacheable thing the backend produces. A short
public, max-age=...onperiod=contestplus droppingno-storefor that one path would remove the load.Two things to keep in mind for whoever picks this up:
period=dailyreachesmaybe_schedule_daily_leaderboard_refresh(), andperiod=liveis the Season 0 preview. Onlycontestis safely cacheable.