Skip to content
Holits

Blockchain Infrastructure

CEX Tracker

A multi-exchange monitoring service that watches nine centralized crypto exchanges for new listings and announcements, and pushes real-time alerts to Telegram, Discord and a REST API.

By Holits

The problem

New listings move price, and traders who hear about one first have an edge that lasts minutes, not days. The information exists the moment an exchange publishes it — but nine exchanges means nine different publishing mechanisms, response shapes, rate limits and, on three of them, active anti-scraping defences that block anything that isn't a real browser.

The approach

CEX Tracker polls Binance, OKX, MEXC, Bybit, Bitget, Coinbase, BingX, Bitfinex and Deribit for their tradable pairs and announcement feeds, diffs the result against what it already knows, and treats a genuinely new listing, a delisting or an exchange expanding to a new market as three distinct events — each with its own alert. Alerts reach subscribers through a Telegram bot, a Discord bot, and a REST API with tiered, API-key-scoped rate limits.

An LLM extraction layer reads raw announcement text and pulls out the ticker symbol and a sentiment label, running against a self-hosted OpenAI-compatible endpoint rather than a third-party API, so extraction cost doesn't scale with alert volume.

Puppeteer only where an API genuinely doesn't work

Six of the nine exchanges expose trading-pair and announcement data through a usable API and get polled directly, every 15 seconds. Three — MEXC, BingX and Bitfinex — sit behind Cloudflare protections that block direct HTTP requests regardless of headers or retries. For those three, and only those three, a separate Puppeteer microservice runs a stealth-plugin headless Chrome instance, polled on a slower 5-minute interval with Redis caching in front of it to keep container load down. The two-tier cadence is a direct trade: fast and cheap where an API allows it, slow and expensive only where nothing else works.

Scaling the aggregation layer with the dataset

The aggregation cycle is architected so its cost tracks what actually changed, not the size of the dataset it's watching. Existing pairs and base assets are batch-loaded in bulk per exchange rather than queried per pair, and the result is filtered down to only the pairs that changed before any further processing runs — which keeps cycle time proportional to the delta each poll produces even as the tracked pair count grows past 13,000. Notification fan-out follows the same principle on the delivery side, streaming subscribers via cursor instead of loading the full recipient set into memory per send.

What it looks like in practice

  • Telegram and Discord bots, sharing a rate limiter and the same subscription-tier checks, so a free-tier user gets the same gating regardless of which channel they use.
  • A REST API with SHA-256-hashed, bearer-token API keys. A missing key and a wrong key return an identical 401 — a deliberate choice to avoid leaking which failure mode a caller hit.
  • Tiered subscriptions (free / basic / pro) via Stripe, gating bot alerts, arbitrage and paper-trading simulations, and API access.
  • An optional event bus. A RabbitMQ topic exchange is available for downstream consumers; if it's unreachable the service logs a warning and keeps running rather than going down over a queue nobody is currently reading.

Design decisions worth noting

  • Retry, don't drop. Announcement processing runs a state machine — pending, processing, processed, failed, expired — instead of a single pass/fail attempt, so a transient extraction failure gets retried instead of silently losing an actionable announcement.
  • Cold-start protection against false delistings. The very first aggregation cycle after a restart is excluded from delisting alerts, because a freshly started database looks, for one cycle, like everything just disappeared.
  • Operator access is explicit, not inherited. Cross-server admin access is granted through an env-var allowlist rather than derived from who owns a Discord server — a deliberate separation between "runs a community" and "has operator access to the platform."

Case study

See this in production: A tiered polling architecture for tracking nine exchanges in real time.

Availability

Private. Built and operated in-house; not distributed under an open licence.