dbet · cache flow

cache hit
cache miss
external API
Claude model
↵ done
↓ next layer
GET /api/picks/today (SSE)
localStorage · full day · per-device · keyed by date
HITRender picks — no server call↵ done
MISSContinue to server
picks.json · disk · today's entry with sports:['auto']
HITStream cached text → client stores in localStorage↵ done
MISSCheck if already generating
autoPicksGenerating flag · in-memory
BUSYReturn generating:true → client retries in 3s↵ done
FREESet flag → fetch schedule for all active sports
fixturedownload.com · tier 1 · NBA/NHL/MLB/NFL · midnight ET / 6h MLB
GAMESUse fixture schedule — full season JSON, filtered to today. Continue to odds pipeline.
MISSNo games today or fetch failed → try ESPN
ESPN schedule · tier 2 fallback · all leagues incl. NCAAB/NCAAF
NO GAMESSkip odds fetch → go directly to Claude
GAMESContinue to odds pipeline
oddsCache · in-memory · 4h
HITUse cached odds → pass to Claude↵ done
MISSCheck disk cache
odds.json · disk · 4h · keyed by sport:date
HITUse disk odds → pass to Claude↵ done
MISSTry The Odds API
The Odds API · tier 1
OKSave to disk + memory → pass to Claude↵ done
FAILTry Tank01
Tank01 / RapidAPI · tier 2
OKSave to disk + memory → pass to Claude↵ done
FAILAI estimate fallback
AI estimate · tier 3 fallback · odds only
Claude generates estimated odds when no source available
Claude Opus · cross-sport analysis
📝 prompt assembled — date · all active sports · schedule (fixturedownload → ESPN) · odds (from whichever tier resolved). Claude selects up to 5 best-value bets across all sports. Medium & High confidence only.
Stream tokens to client → archive in picks.json as sports:['auto'] → clear historyCache
Archive guard: skips write if all pick keys already recorded for today
GET /api/scores
ESPN scoreboard · real-time · all active sports
OKReturns games per sport with score/status. Client filters strip to pick games only by team name match.↵ done
Client polling · 2min interval · only while a game is LIVE
Score strip auto-refreshes every 2 min when any pick game is in progress. Polling stops when all games are final.
GET /api/history
historyCache · in-memory · past days only, never today
HITServe response↵ done
MISSToday's date or cold cache — continue
Read picks.json + outcomes.json
Deduplicate picks by normalized key — strips odds, spreads, clarifications. Same game = same key across multiple runs.
Outcome resolution · 10min TTL for today · permanent for past days
ALL RESOLVEDServe + cache in historyCache↵ done
PENDINGCall Claude Haiku → save outcomes.json (with __checkedAt__ timestamp) → serve. historyCache only set when today has picks and no past-day picks are pending.
Cache TTL Summary
Layer TTL Notes
localStorage full day Per-device, keyed by date only. Picks don't change mid-day; score strip refreshes independently.
picks.json all day Disk. Auto-picks keyed as sports:['auto'] per date. Archive guard skips write if all pick keys already seen. Writing invalidates historyCache.
autoPicksGenerating in-flight In-memory flag. Prevents duplicate Claude calls if two users hit the cold-start at the same time.
fixtureSeasonCache midnight ET / 6h In-memory, full season per league. MLB 6h for rainouts; NBA/NHL/NFL expire at midnight ET.
scheduleCache 4h In-memory ESPN fallback, keyed by date+sports
oddsCache 4h In-memory
odds.json 4h Disk, keyed by sport:date
historyCache session In-memory. Only set when today has picks and no past-day picks are pending. Cleared whenever new picks are archived.
outcomes.json 10min / permanent Disk. Today's picks re-checked every 10 min via __checkedAt__ timestamp. Past days cached indefinitely.