
Product
LighterPulse
Analytics hub for Lighter.xyz: dashboards, a block explorer, exchange stats and cross-venue funding comparison.
- Next.js
- TypeScript
- Tailwind CSS

Background service for Lighter.xyz that computes total open interest across every perpetuals market. A worker takes a WebSocket snapshot every 15 minutes, normalises it to the two-sided figure Lighter shows in its own app and stores it in Upstash Redis; a stateless Express API serves it to dashboards with a single read.
Lighter OI Aggregator answers a question every Lighter dashboard needs: how much open interest is there across the whole exchange right now? Lighter's market-stats stream reports open interest market by market, so an exchange-wide figure means summing every market, and keeping a socket open in every client just to add those numbers up is wasteful.
The service splits the problem into two small processes. A worker connects on a schedule, reads one complete snapshot of every market, computes the total and disconnects. A stateless HTTP API reads the stored figure from Redis, so clients get the number with one request and no streaming code.
Instead of holding a long-lived WebSocket, the worker opens a fresh connection each cycle, subscribes to market_stats/all and waits for the subscription snapshot. It accepts both payload shapes the channel can send (a map of market id to stats, or a single market object), keeps the latest open interest per market id, saves the doubled total once and closes the socket. A 60-second timeout guarantees a stalled connection can never block the next cycle.
Upstash Redis holds a single key, total_open_interest_usd, which is the only state the worker and the API share, so the two never depend on each other's memory or process. The Express server is stateless: one route reads the key and returns { total_open_interest_usd }, with failures mapped to a 500 response. One npm script starts both processes together.
The market stats stream reports open interest for one side of each market, so a plain sum comes out at half the number traders see in Lighter's app. The service doubles the total once, at write time, so every consumer reads the same figure and none of them has to know about the quirk.
Total open interest moves slowly compared with prices, so a permanent socket would add reconnection logic and memory for no real benefit. Reading one snapshot per cycle keeps the worker simple and cheap, and because each cycle sums whatever markets exist at that moment, listings and delistings are handled automatically.
A network stall during the snapshot could leave the worker waiting indefinitely. Every cycle resolves on close, on error or after a 60-second timeout, whichever comes first, so a bad connection costs at most one refresh.
The same channel can deliver a map of markets or a single market object depending on the message. The parser normalises both into one record keyed by market id before summing, so a market that appears in more than one message is never counted twice.
Analytics dashboards, trading tools and bots that need Lighter's total open interest as a single number, without running their own WebSocket client or aggregation logic.

Product
Analytics hub for Lighter.xyz: dashboards, a block explorer, exchange stats and cross-venue funding comparison.

Backend service
Streaming pipeline that ingests Lighter liquidations, dedupes replayed batches and serves a rolling 24h total.