[object Object]

← back to Nationalrealestate

Perf: 5-min in-process cache on /api/markets (1.8s scan -> ms on warm hits)

511984e7a6a7942a89d28100b78d164c8c4e965a · 2026-07-21 15:26:17 -0700 · Steve Abrams

Files touched

Diff

commit 511984e7a6a7942a89d28100b78d164c8c4e965a
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Tue Jul 21 15:26:17 2026 -0700

    Perf: 5-min in-process cache on /api/markets (1.8s scan -> ms on warm hits)
---
 src/server/index.ts | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/src/server/index.ts b/src/server/index.ts
index c3b90d8..bcbf907 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -118,11 +118,16 @@ const MARKETS_METRICS = [
   'months_of_supply', 'sale_to_list', 'median_hh_income', 'rent_yield', 'affordability',
 ];
 
-// ranking dashboard: one row per region with latest score + latest key metrics
+// ranking dashboard: one row per region with latest score + latest key metrics.
+// The latest-per-metric scan covers 1.2M rows (~1.8s) — cache per type; data changes monthly.
+const marketsCache = new Map<string, { at: number; body: any }>();
+const MARKETS_TTL_MS = 5 * 60_000;
 app.get('/api/markets', async (req, res) => {
   try {
     const type = String(req.query.type || 'county');
     if (type !== 'county' && type !== 'metro') return res.status(400).json({ error: 'type must be county|metro' });
+    const hit = marketsCache.get(type);
+    if (hit && Date.now() - hit.at < MARKETS_TTL_MS) return res.json(hit.body);
     const metricsQ = query<{ region_id: number; metric: string; value: string }>(
       `SELECT DISTINCT ON (ms.region_id, ms.metric) ms.region_id, ms.metric, ms.value::text AS value
          FROM metric_series ms
@@ -173,7 +178,9 @@ app.get('/api/markets', async (req, res) => {
         affordability: m.affordability ?? null,
       };
     });
-    res.json({ type, count: rows.length, rows });
+    const body = { type, count: rows.length, rows };
+    marketsCache.set(type, { at: Date.now(), body });
+    res.json(body);
   } catch (e: any) {
     res.status(500).json({ error: String(e.message || e) });
   }

← db8222e Market detail: Climate Risk (FEMA NRI) + Rental Market (HUD  ·  back to Nationalrealestate  ·  auto-save: 2026-07-21T15:38:16 (1 files) — src/jobs/broker_r fabf9ec →