Skip to content

Architecture Overview ​

Pulsar follows a client-server architecture with real-time data streaming via WebSockets and REST APIs for historical data.

System Diagram ​

┌─────────────────────────────────────────────────────────────┐
│                        Data Sources                          │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐    │
│  │  Alpaca   │  │ Binance  │  │ doviz.com│  │ Finnhub  │    │
│  │  (SIP)   │  │  (REST)  │  │   (WS)   │  │  (REST)  │    │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘  └────┬─────┘    │
│       │              │              │              │          │
└───────┼──────────────┼──────────────┼──────────────┼─────────┘
        │              │              │              │
┌───────▼──────────────▼──────────────▼──────────────▼─────────┐
│                    Backend (FastAPI)                           │
│                                                               │
│  ┌─────────────────────────────────────────────────────┐     │
│  │              Provider Registry                       │     │
│  │  ┌──────────┐  ┌──────────┐  ┌──────────┐          │     │
│  │  │ Alpaca   │  │  Crypto  │  │  Doviz   │          │     │
│  │  │ Provider │  │ Provider │  │ Provider │          │     │
│  │  └────┬─────┘  └────┬─────┘  └────┬─────┘          │     │
│  └───────┼──────────────┼──────────────┼────────────────┘     │
│          │              │              │                       │
│  ┌───────▼──────────────▼──────────────▼────────────────┐     │
│  │                Redis Pub/Sub                          │     │
│  │  quotes:stock    quotes:crypto    quotes:doviz        │     │
│  └───────┬──────────────┬──────────────┬────────────────┘     │
│          │              │              │                       │
│  ┌───────▼──────────────▼──────────────▼────────────────┐     │
│  │           WebSocket Connection Managers                │     │
│  │  /ws/quotes      /ws/crypto      /ws/doviz            │     │
│  └───────┬──────────────┬──────────────┬────────────────┘     │
│          │              │              │                       │
│  ┌───────┴──────────────┴──────────────┴────────────────┐     │
│  │              REST API Endpoints                        │     │
│  │  /market  /crypto  /doviz  /financials  /portfolio     │     │
│  └──────────────────────┬───────────────────────────────┘     │
└─────────────────────────┼─────────────────────────────────────┘
                          │
              ┌───────────▼───────────┐
              │   Frontend (Next.js)   │
              │                        │
              │  ┌──────────────────┐  │
              │  │  Zustand Stores  │  │
              │  │  market / doviz  │  │
              │  │  crypto / fin    │  │
              │  └────────┬─────────┘  │
              │           │            │
              │  ┌────────▼─────────┐  │
              │  │    React Pages   │  │
              │  │  Dashboard       │  │
              │  │  Stocks          │  │
              │  │  Currencies      │  │
              │  │  Crypto          │  │
              │  │  Terminal        │  │
              │  │  Portfolio       │  │
              │  └──────────────────┘  │
              └────────────────────────┘

Key Design Decisions ​

Provider Abstraction ​

All data sources implement the MarketDataProvider abstract base class with start(), stop(), name, and pubsub_channel. This allows adding new data sources (exchanges, brokers) without modifying existing code.

Redis as Message Bus ​

Providers publish normalized data to Redis Pub/Sub channels. WebSocket managers subscribe to these channels and forward to connected clients. This decouples data ingestion from delivery and allows horizontal scaling.

Throttled Delivery ​

Both providers and WebSocket managers batch updates at 300ms intervals. This prevents client saturation during high-frequency trading periods while maintaining near-real-time feel.

Worker Cache Pattern ​

A background worker periodically fetches and caches snapshot data in Redis (TTL: 15 minutes). REST endpoints read from this cache first, falling back to direct API calls when cache is empty. This ensures data availability during provider reconnections.

Frontend State Architecture ​

Zustand stores hold all market data globally. Pages subscribe to relevant slices. WebSocket managers update stores directly, triggering React re-renders only for changed data.

Released under the MIT License.