Read-optimized equity market dashboard for exploring stock data clearly and responsibly.
- Read-heavy API optimized for low-latency dashboards and watchlists.
- Explicit cache-aside strategy with volatility-aware TTLs and versioned keys.
- Write path separated into a worker to keep the API responsive under ingest load.
- Data model and indexes aligned to access patterns (time-series + movers).
- Start the data services and API.
docker compose up --build
- The first boot auto-applies migrations. To re-run, reset the volume:
docker compose down -v && docker compose up --build
- Start the frontend.
cd frontend && npm install && npm run dev
Frontend calls http://localhost:3000 by default.
flowchart LR
API[Stock API] --> Worker[Ingestion Worker]
Worker --> PG[(PostgreSQL)]
APIService[Fastify API] --> PG
APIService --> Redis[(Redis Cache)]
UI[React + Vite] --> APIService
price_pointssupports time-series reads by(symbol, ts DESC).daily_snapshotssupports dashboard sorting bychange_pctand per-symbol latest.market_briefsexists for future LLM/RAG summaries without coupling to core reads.
- Cache-aside per endpoint with a short NX lock to prevent stampedes.
- Versioned keys:
market:version:YYYY-MM-DDbumped after each ingest. - Tiered TTLs by market state:
- Overview: 60s open / 6h closed
- Watchlist: 20s open / 1h closed
- History: 6h (immutable-ish)
- Worker runs on a fixed interval and uses a provider interface.
- Provider returns normalized OHLCV snapshots and intraday points.
- Upserts
symbols+daily_snapshots, appendsprice_points.
- Lightweight request timing log per route (duration in ms).
- Designed to be p50/p95 ready without external APM.
GET /healthGET /api/dashboard/overviewGET /api/watchlist?symbols=AAPL,MSFTGET /api/stocks/:symbol/history?range=7d|30d|90d
- Worker stubs a provider behind an interface so real APIs can be swapped in.
- Cache keys are versioned by trading date and bumped after ingest.