Engineering

53 exchange feeds, 15 of them streaming

Jordan Ellis

Senior Product Marketing Manager, CoinBeacon

We were about to publish a post called “sub-second alerts across 60+ exchanges”. Neither number survived being checked, so here is the real shape of the pipeline instead — which is a better story than the one we nearly told.

There are two alert pipelines

Conflating them is exactly how a “sub-second” claim gets made. There is an event-driven path and a scheduled path, and they share only the delivery tail.

The event-driven path handles one alert type: a plain price alert, set once, that disarms after it fires. If you asked for repeated crossings instead, your alert carries an arm-and-cooldown state machine, and that belongs to the scheduler. So the fast path is real, and it is narrow.

What a price tick travels through

Each venue has its own adapter. Prices are conflated before they are published — a price identical to the last one is dropped, with a 25-second heartbeat so a quiet book still proves it is alive — and the streaming path is micro-batched into a latest-per-symbol buffer flushed every 250 milliseconds as a single write to a Redis stream.

A single arbitrator process is the only writer of prices. Streaming writes are accepted unconditionally; a REST price is rejected if a streamed price for that symbol arrived in the last fifteen seconds, which is what stops a 30-second poll from stamping over a live tick. Downstream of that write, changed prices go onto a second stream that only the alert evaluator reads.

The evaluator reads that stream in batches and does one cheap thing first: it asks Redis how many alerts are registered against each symbol in the batch. Symbols nobody is watching cost a single round trip and are discarded. Only the survivors are loaded and evaluated, and a trigger is claimed with a conditional update so two workers cannot fire the same alert twice.

End to end on that path, the exchange-tick-to-alert-stream leg measured 221, 255, 270, 550, 1092milliseconds across five consecutive samples. That is before evaluation, before the notification queue, and before your email provider or Telegram accepts the message. “About a second to Telegram for a one-shot price alert” is defensible. “Sub-second alerts” as a blanket claim is not.

The CoinBeacon price alert builder: a market picker set to BTC on Binance, quote-currency and notification-channel fields, and a live panel restating the alert in plain English, beside a left rail listing every alert type from price and momentum through RSI, MACD and funding rate.
The alert builder. The left rail is the full type list — and everything on it except the plain price alert is evaluated by the scheduler, not the fast path.

53 feeds, 15 streaming

The interesting number is not the total. It is the split. There are 53 exchanges configured, all of them enabled; 49 are carrying live price keys. Of those, fifteen have a registered websocket adapter, plus Kraken on an older streaming path — call it sixteen. Every other venue is polled: a whole-venue ticker endpoint every thirty seconds, or every ten for a dozen of them.

That distinction matters more to you than the headline count does. An alert on a streaming venue can fire about a second after the tick. An alert on a polled venue cannot beat the poll, no matter what the marketing says — worst case, your price moved twenty-nine seconds before we knew about it.

Where did “60+” come from? The closest thing was the validation enum for which platform an alert may name — fifty-nine entries, and six of its values have no price feed behind them at all. It was the wrong list to count.

Everything else runs on a clock

The scheduler carries twenty-six cron jobs. Percentage, periodic and funding-rate alerts run once a minute. The eleven indicator jobs each run once a minute too, hand-staggered across the seconds so they never collide, and they read stored candles — which is why they exist only on the venues we ingest candles for, and why they fire on candle close rather than on tick.

One detail is worth publishing because it surprised us. The price cron is written to fire every ten seconds, and when the workers run split by role it does not do ten-second work. The scheduler enqueues rather than evaluates, and that enqueue is deduplicated by a key with a sixty-second lifetime. Measured over about forty-eight minutes on a running stack: 289 cron fires produced 44 enqueues and 244 skips. The cron price path effectively runs about once a minute, not six times.

Delivery: four channels, one at a time

Every trigger claims one of your daily notification slots atomically — the gate and the count are a single statement, so a burst cannot overshoot the cap — then pushes a job onto a queue behind an idempotency key. The notification worker reserves jobs one at a time and processes exactly one at a time. No concurrency.

Four channels: email, Telegram, Discord, webhooks. Webhooks are https-only, refuse redirects and are guarded against pointing at internal addresses. Three attempts, five seconds apart. If a channel fails permanently, every alert you have on it is migrated to email and you get one message telling you so, rather than silently receiving nothing.

What we are not claiming

  • Not every feed is a stream. Sixteen of fifty-three. The rest are polled, and an alert cannot be faster than its feed.
  • Indicator alerts are candle-close events, not tick events. An RSI alert on the 1h fires after the hour closes. That is the correct behaviour for an indicator and it is not a latency bug, but it is not “instant” either.
  • The notification worker is deliberately serial. One job at a time is a throughput ceiling we have accepted, because ordering and idempotency were worth more than parallel sends at our volume. If that stops being true, it is the first thing that changes.
  • Daily notification caps are real and they apply per user. A noisy alert can exhaust its owner’s budget for the day. That is a design choice, not a fault, and it is why percentage alerts have a cooldown.

None of this makes the product worse than the version we nearly advertised. It makes it checkable. If you set a one-shot price alert on a streaming venue, you should get it in about a second — and if you set an RSI alert on the 4h, you should expect it when the 4h closes, because that is when it becomes true.


Jordan EllisSenior Product Marketing Manager, CoinBeacon

Jordan Ellis is a Senior Product Marketing Manager at CoinBeacon, covering the charting, alerting and market-data work that ships on the platform. They write the release notes here, and check every figure in them against the running app before it is published.


The figures in these posts are read from the running app. When it changes, I edit the post, and the date at the top changes with it.

Set one and see

The price alert form is open without an account. You configure it, and signing up is what actually arms it.

Email is included free. Telegram, Discord and webhooks are added in settings.

Open the alert builder