---
title: "API Engineering for Crypto Venues"
book: "Networks, Hardware and Trading Infrastructure"
subject: quant
language: en
chapter: 20
exercises: 8
source: https://one-course.com/books/quant/14/en/chapter/20-api-engineering-for-crypto-venues
---

# Chapter 20 — API Engineering for Crypto Venues

A large crypto venue lets one WebSocket connection carry at most 1 024 streams, accepts at most 300 new connections per address every five minutes, disconnects any connection after 24 hours, and expects an answer to its ping within a minute. A firm that follows 400 symbols with depth and trades on each has 800 streams to place, a book to rebuild whenever a message is lost, and a single budget of request weight for the snapshots that rebuild it and the orders that trade. When one connection loses a message and the firm resynchronises every symbol on it from full-depth snapshots, the budget runs out after 24 of them, and the last of the 80 symbols is stale for three minutes.

Chapters 16 to 19 were about where the venue is and how packets reach it. This chapter is about the interface itself: how streams are spread over connections and addresses, how gaps are detected and repaired, how one rate budget is shared, how an [order-entry path](#def-nw-api-engineering-for-crypto-venues-path) is chosen, and which timestamps to trust. It uses Book 3’s order-book builder and rate-limit governor and Book 13’s WebSocket client, and the venues’ documentation, dated.

## 20.1 Websocket sharding

**Definition 20.1 (Connection sharding).**

*Connection sharding* is the assignment of a subscription set’s streams to several connections, and of the connections to several source addresses, so that no connection or address exceeds a venue’s limits and a failure or a slow consumer affects only part of the set.

**As of September 2026 — WebSocket limits, from venue documentation.**

- Binance spot streams: at most 1 024 streams per connection; 300 connections per attempt every 5 minutes per IP; 5 incoming messages per second per connection, beyond which the connection is closed (and repeatedly disconnected IPs may be banned); connections valid 24 hours; a ping every 20 seconds, answered by a pong within a minute; depth events carry an event time `E` , trades a trade time `T` . A full-depth snapshot (up to 5 000 levels) costs request weight 250; 1 000 levels cost 50; the weight limit is 6 000 a minute.
- OKX: 3 connection requests per second per IP; 480 subscribe, unsubscribe or login requests per connection per hour; a connection without data for 30 seconds is closed.

The venue’s cap is a maximum, not a target. One connection could carry all 800 streams, but it would carry them in order: a burst on one symbol delays every other symbol’s messages behind it (chapter 1’s [head-of-line blocking](https://one-course.com/books/quant/14/en/chapter/1-networking-for-trading#def-nw-networking-for-trading-hol) at the application level), one disconnection drops every book, and the 24-hour reset takes the whole feed down at once. The chapter’s firm caps a connection at 160 streams (80 symbols), which needs five connections; reconnecting all five at once is far within 300 per address per five minutes, so one address suffices.

**Proposition 20.2 (How many connections and addresses).**

For $S$ streams, a cap of $c$ streams per connection (the venue’s or lower) and a venue limit of $L$ new connections per address per window $W$, a design that must be able to reconnect everything within $w \le W$ needs $\lceil S/c \rceil$ connections and $\lceil \lceil S/c \rceil / (L\,w/W)
\rceil$ addresses, if the limit is spread evenly over the window.

**Proof.** Each connection carries at most $c$ streams. Reconnecting $n$ connections in $w$ uses $n$ connection attempts; an address allows $L w/W$ of them in $w$ on the even-spreading reading of the limit. ∎

```python
def plan_shards(n_streams, limits, max_streams_per_conn=None, reconnect_window_s=None):
    """Connections to carry the streams at the venue's cap or the firm's lower one; addresses
    so that reconnecting them all within reconnect_window_s respects the per-address limit."""
    cap = min(limits.streams_per_conn, max_streams_per_conn or limits.streams_per_conn)
    conns = math.ceil(n_streams / cap)
    window = reconnect_window_s or limits.window_s
    per_addr = limits.conns_per_window * min(1.0, window / limits.window_s)
    addresses = max(1, math.ceil(conns / per_addr))
    return {"connections": conns, "addresses": addresses, "streams_per_conn": cap}
```

***Listing 20.1.** The shard planner: connections at the venue’s or the firm’s cap, and addresses for a reconnection within a given window. code/firm/cryptofeed/firm_cryptofeed.py*

![The chapter’s shard plan, schematically: 800 streams over five connections of 160, from one address. The venue would allow one connection of 800; the firm’s cap limits head-of-line blocking and the damage of one disconnection.](https://one-course.com/images/onecourse/chapters/quant-14/nw-api-engineering-for-crypto-venues/fig-ba5c86e580b8.svg)

***Figure 20.1.** The chapter’s shard plan, schematically: 800 streams over five connections of 160, from one address. The venue would allow one connection of 800; the firm’s cap limits [head-of-line blocking](https://one-course.com/books/quant/14/en/chapter/1-networking-for-trading#def-nw-networking-for-trading-hol) and the damage of one disconnection.*

## 20.2 Snapshots, deltas and sequence gaps at scale

**Definition 20.3 (Per-symbol resynchronisation).**

*Per-symbol resynchronisation* repairs a book after a sequence gap by fetching a snapshot for the symbols whose own update sequence shows the gap, rather than for every symbol carried by the connection on which messages were lost.

The venue’s procedure is Book 3’s: buffer the deltas, fetch a snapshot, drop the deltas older than it, apply the rest, and if a delta’s first update number is beyond the book’s last plus one, discard the book and start again. Book 3’s `firm.wsbook` implements it; fed a stream that loses one event, it answers “applied”, “applied”, then “gap”. What a gap costs is decided by how many books the firm throws away and how many snapshots its weight budget can pay for.

**Proposition 20.4 (What a gap costs).**

If each snapshot costs $w$ of a budget of $B$ per window $T$ shared by nothing else, and $m$ books must be rebuilt, the last one returns after about $\lceil m\,w/B \rceil - 1$ whole windows plus a round trip; with [per-symbol resynchronisation](#def-nw-api-engineering-for-crypto-venues-resync) $m$ is the number of symbols that lost messages, with per-connection resynchronisation it is every symbol on the connection.

**Proof.** The governor admits $\lfloor B/w \rfloor$ snapshots per window; the remaining ones wait for the following windows. ∎

```python
def resync_staleness(symbols_hit, snapshot_weight, governor_rules, rtt_ms=100.0):
    """One snapshot per hit symbol, admitted by the governor's weight (one a millisecond at most);
    a symbol is stale until its snapshot returns. The last return and the stale symbol-seconds."""
    gov = frl.Governor([frl.Rule(r.kind, r.interval_ms, r.limit) for r in governor_rules])
    t, done = 0, []
    for _ in range(symbols_hit):
        while True:
            ok, wait = gov.try_send(t, snapshot_weight, False)
            if ok:
                break
            t += wait
        done.append(t + rtt_ms)
        t += 1
    return {"done_ms": max(done) if done else 0.0, "symbol_seconds": sum(done) / 1000.0}
```

***Listing 20.2.** Recovery under the weight governor: each snapshot waits for the budget, and a book is stale until its snapshot returns. code/firm/cryptofeed/firm_cryptofeed.py*

| Snapshot depth | Weight | Per symbol (5 books) | Per connection (80 books) | Last book back |
| --- | --- | --- | --- | --- |
|  |  | (stale symbol-s) | (stale symbol-s) | per connection (s) |
| 5 000 levels | 250 | 0.5 | 5 769 | 180.1 |
| 1 000 levels | 50 | 0.5 | 11.2 | 0.2 |

***Table 20.1.** Simulation: five messages lost on one connection of 80 symbols (they touch five symbols), repaired per symbol or per connection, with snapshots at two depths under the 6 000-weight-a-minute governor of Book 3 and a $100\,\mathrm{m}\mathrm{s}$ round trip; staleness in symbol-seconds. Data: `nw_api.resync_rows()`.*

![Simulation: stale symbol-seconds after five messages are lost on one connection, by recovery design and snapshot depth (). Per-connection recovery with full-depth snapshots costs four orders of magnitude more. Data: fig_api.py.](https://one-course.com/images/onecourse/chapters/quant-14/nw-api-engineering-for-crypto-venues/fig-9e6fca68ae1a.svg)

***Figure 20.2.** Simulation: stale symbol-seconds after five messages are lost on one connection, by recovery design and snapshot depth ([Table 20.1](#tab-nw-api-engineering-for-crypto-venues-resync)). Per-connection recovery with full-depth snapshots costs four orders of magnitude more. Data: `fig_api.py`.*

The table is the case for doing the harder thing. Per-symbol recovery needs sequence numbers per symbol (the venue’s `U` and `u`) and a book per symbol that can be discarded alone; in exchange five lost messages cost five snapshots. Per-connection recovery is simpler and, with full depth, catastrophic: 80 snapshots of weight 250 need three and a half minutes of a 6 000-weight budget, during which the firm has no weight left to send orders. Snapshots of 1 000 levels make even the careless design survivable, which is a second lesson: ask for the depth the strategy needs.

## 20.3 Rate-limit governors across keys and addresses

A venue’s limits are per address, per account, per key, and several strategies share them. The firm needs one governor per limit that everyone passes through (Book 3’s `firm.ratelimit`), and a rule for sharing it. The chapter’s allocator gives each strategy up to its demand in proportion to a priority weight and spreads what the satisfied ones leave: with 6 000 a minute, a risk process that needs 500 gets all of it, and market making and arbitrage, asking 4 000 and 3 000 with weights 3 and 2, get 3 300 and 2 200. Snapshots for recovery must come out of the same budget, which is why recovery design is a rate-budget question.

![One 6 000-weight minute shared by three strategies with priority weights 3, 2 and 1: the risk process’s 500 is met in full, the others share the rest in proportion. Data: fig_api.py, nw_api.budget().](https://one-course.com/images/onecourse/chapters/quant-14/nw-api-engineering-for-crypto-venues/fig-7da2b8b86ce6.svg)

***Figure 20.3.** One 6 000-weight minute shared by three strategies with priority weights 3, 2 and 1: the risk process’s 500 is met in full, the others share the rest in proportion. Data: `fig_api.py`, `nw_api.budget()`.*

## 20.4 Choosing among order-entry paths

**Definition 20.5 (Order-entry path).**

An *order-entry path* is one of the interfaces through which a venue accepts orders (REST requests, orders over a WebSocket session, a FIX session, a venue-specific binary protocol), each with its own connection model, rate limits, latency and failure behaviour.

The large venue of this chapter documents several (a REST interface, a WebSocket API, a FIX API, and market-data streams in a binary encoding), and chapter 18’s [private endpoints](https://one-course.com/books/quant/14/en/chapter/18-private-connectivity-to-crypto-venues#def-nw-private-connectivity-to-crypto-venues-endpoint) add routes to them. The choice follows the strategy: a persistent session removes the handshake from each order; REST’s statelessness helps recovery; FIX brings session-level sequence numbers and resend requests. Whatever the path, it draws on the same governor, and a firm that sends orders on two paths must know whether the venue counts them against one limit or two.

## 20.5 Redundant connections and which timestamps to trust

**Definition 20.6 (Venue clock skew).**

*Venue clock skew* is the difference between the clock that stamps a venue’s messages (its event and transaction times) and the firm’s own synchronised clock, which varies over time; it is estimated, never given.

Every message carries the venue’s event time; the firm stamps its arrival. The difference is the one-way delay plus the venue’s clock error, and the two cannot be separated from one side alone. Its minimum over a window, however, is the smallest delay plus the error: if the smallest delay is stable, tracking the minimum tracks the venue’s clock (chapter 4’s minimum-delay filter, applied to someone else’s clock).

```python
def skew(event_ms, recv_ms, window):
    """Minimum one-way delay minus the venue's clock offset: min(receive - event) per window."""
    e, r = np.asarray(event_ms, float), np.asarray(recv_ms, float)
    d = r - e
    starts = range(0, len(d) - window + 1, window)
    return [(float(r[i + window - 1]), float(d[i:i + window].min())) for i in starts]
```

***Listing 20.3.** The venue-clock estimator: the minimum of receive time minus event time over each window. code/firm/cryptofeed/firm_cryptofeed.py*

![Simulation: a venue clock running 3 to 5\, m s ahead of the firm’s over an hour, messages at ten a second with a minimum one-way delay of 0.8\, m s and exponential jitter; the one-minute minimum tracks the truth within 15\, µ s. Data: fig_api.py, nw_api.skew_series().](https://one-course.com/images/onecourse/chapters/quant-14/nw-api-engineering-for-crypto-venues/fig-934c04dcc271.svg)

***Figure 20.4.** Simulation: a venue clock running 3 to $5\,\mathrm{m}\mathrm{s}$ ahead of the firm’s over an hour, messages at ten a second with a minimum one-way delay of $0.8\,\mathrm{m}\mathrm{s}$ and exponential jitter; the one-minute minimum tracks the truth within $15\,\text{µ}\mathrm{s}$. Data: `fig_api.py`, `nw_api.skew_series()`.*

Redundant connections make the question sharper: two connections to the same stream deliver the same event twice, at two arrival times, and the firm keeps the first (chapter 19’s racing, for data). The venue’s event time orders events across symbols and connections; the firm’s arrival time says when it could act. A strategy that uses the event time to measure its own latency must first subtract the estimated skew, or it will measure the venue’s clock.

**Method 20.7 (Running a crypto venue’s interfaces).**

1. Record the venue’s limits (streams, connections, messages, weights, lifetimes) with their dates, and re-read them on every change notice.
2. Shard below the caps, spread reconnections over time and addresses, and stagger the 24-hour resets.
3. Detect gaps per symbol and resynchronise per symbol, with snapshots no deeper than the strategy needs.
4. Put every request, snapshot and order through one governor per limit, and allocate it by priority.
5. Estimate each venue’s clock skew continuously and timestamp everything on arrival with a synchronised clock.

## 20.6 Tutorial: four hundred symbols

**Goal.** Plan shards, compare recovery designs under the weight governor, share a budget and estimate a venue’s clock. **End state:** Figures [20.2](#fig-nw-api-engineering-for-crypto-venues-stale), [20.3](#fig-nw-api-engineering-for-crypto-venues-budget) and [20.4](#fig-nw-api-engineering-for-crypto-venues-skew) and [Table 20.1](#tab-nw-api-engineering-for-crypto-venues-resync).

1. **Shards.** `firm_cryptofeed.plan_shards` ( [Listing 20.1](#lst-nw-api-engineering-for-crypto-venues-shards) ) with the dated `LIMITS` ; `nw_api.plan()` .
2. **Gaps.** `nw_api.gap_demo()` feeds Book 3’s `firm.wsbook` a stream with a lost event; `resync_staleness` ( [Listing 20.2](#lst-nw-api-engineering-for-crypto-venues-resync) ) prices the recovery under Book 3’s governor.
3. **Budget.** `allocate` shares one minute of weight.
4. **Clock.** `skew` ( [Listing 20.3](#lst-nw-api-engineering-for-crypto-venues-skew) ) on `skew_series()` .

**What to change next.** Feed the recovery model Book 13’s `firm.wsclient` decoded fixtures; give the governor the order traffic as well and watch the recovery starve it.

## 20.7 Build: the crypto feed manager

**Purpose.** The interface layer to crypto venues: shards, recovery, shared budgets and venue clocks; the input of the crypto rows of chapter 29’s plan.

**Interface.** `firm_cryptofeed`: `Limits`, `LIMITS`, `plan_shards`, `resync_staleness`, `allocate`, `skew`; Book 3’s `firm.ratelimit` and `firm.wsbook` wrapped, not edited.

**Rules.** Limits are dated rows with sources; every request goes through a governor; recovery is per symbol wherever the venue’s sequence numbers allow; the venue’s clock is estimated, not assumed.

**Acceptance tests.** `code/firm/cryptofeed/tests/`: shard counts at the caps, recovery waiting for the next window, water-filling, and the skew estimator by hand.

**Stretch.** A live shard manager that rebalances streams by message rate; recovery by incremental snapshots where a venue offers them.

Sources and further reading

- Binance spot API documentation (WebSocket streams, local order book procedure, order-book weights); OKX API v5 documentation (WebSocket limits).
- RFC 6455, The WebSocket Protocol; One Quant Book 3’s `firm.wsbook` and `firm.ratelimit` , One Quant Book 13’s `firm.wsclient` .

## 20.8 Exercises

**Exercise 20.1 ★.**

How many full-depth snapshots of weight 250 fit in a 6 000-weight minute?

**Solution of Exercise 20.1.**

$6\,000/250 = 24$, and nothing else in that minute.

**Exercise 20.2 ★.**

Why cap a connection at 160 streams when the venue allows 1 024?

**Solution of Exercise 20.2.**

To limit what one connection’s problems cost: [head-of-line blocking](https://one-course.com/books/quant/14/en/chapter/1-networking-for-trading#def-nw-networking-for-trading-hol) behind a busy symbol, the books lost when it drops, the snapshots needed to recover, and the load of the 24-hour reset. Five connections of 160 share the risk and the work.

**Exercise 20.3 ★.**

What must a client do when it receives a WebSocket ping, and what happens at this chapter’s venue if it does not?

**Solution of Exercise 20.3.**

Answer with a pong carrying the ping’s payload, as soon as practical (RFC 6455). The venue pings every 20 seconds and disconnects a connection that has not answered within a minute.

**Exercise 20.4 ★★.**

Using [Proposition 20.2](#prop-nw-api-engineering-for-crypto-venues-shards), how many addresses does a firm need to reconnect 40 connections within 10 seconds at 300 connections per 5 minutes per address?

**Solution of Exercise 20.4.**

In 10 seconds one address may open $300 \times 10/300 = 10$ connections on the even-spreading reading, so 40 connections need 4 addresses.

**Exercise 20.5 ★★.**

Why does the minimum of receive time minus event time track the venue’s clock, and when does it fail?

**Solution of Exercise 20.5.**

Receive minus event is the one-way delay minus the venue’s [clock offset](https://one-course.com/books/quant/14/en/chapter/4-time-synchronisation#def-nw-time-synchronisation-offset); the delay has a floor that some messages reach in every window, so the minimum is the floor minus the offset, and its changes are the offset’s. It fails when the delay’s floor moves (a route change, congestion lasting the whole window) or when the venue stamps events at different points for different streams.

**Exercise 20.6 ★★.**

A strategy measures its tick-to-order latency as its order time minus the venue’s event time. What is wrong?

**Solution of Exercise 20.6.**

It mixes two clocks: the difference includes the venue’s [clock offset](https://one-course.com/books/quant/14/en/chapter/4-time-synchronisation#def-nw-time-synchronisation-offset) (milliseconds in the chapter’s simulation) and the one-way delay to the firm. Measure tick-to-order on the firm’s own clock from the arrival timestamp, and use the venue’s time only after subtracting the estimated skew.

**Exercise 20.7 ★★★.**

*Coding.* With `firm.cryptofeed`, find the largest snapshot weight at which a per-connection recovery of 80 symbols finishes within the first minute.

**Solution of Exercise 20.7.**

75: $80 \times 75 = 6\,000$, the whole minute’s budget; at 76 the last snapshot waits for the next minute.

**Exercise 20.8 ★★★.**

*Find the flaw.* “We subscribe to everything on one connection; the venue allows it, and fewer connections are more reliable.”

**Solution of Exercise 20.8.**

One connection is one failure domain: a disconnection or the 24-hour reset drops every book, a busy symbol delays all others, and a per-connection recovery needs a snapshot for every symbol, which the weight budget cannot pay for quickly. More connections, each below the cap, are more reliable.

## 20.9 Problem: Four Hundred Symbols, Five Connections

**Problem 20.1.**

Weekend problem — shards and recovery

A firm follows 400 symbols on a venue with the limits of [Box 20.1](#dat-nw-api-engineering-for-crypto-venues-limits), with a depth and a trade stream each, at most 160 streams per connection, and one 6 000-weight minute for snapshots and orders.

**Part I — Shards.**

1. How many streams, connections and addresses does it need?
2. How many would it need at the venue’s own cap?
3. How many addresses to reconnect everything within 10 seconds?
4. What does the 24-hour limit mean for the design?

**Part II — A gap.**

5. Five messages are lost on one connection. How many symbols need a snapshot per symbol, and per connection?
6. With full-depth snapshots, how long until the last book is back per connection, and how many stale symbol-seconds?
7. And with 1 000-level snapshots?
8. What can the firm not do while a per-connection recovery runs?

**Part III — Budget and clocks.**

9. How does the allocator share 6 000 between market making (4 000, weight 3), arbitrage (3 000, weight 2) and risk (500, weight 1)?
10. Where do recovery snapshots fit in that allocation?
11. How well does the one-minute minimum estimate the venue’s clock in the simulation?
12. Why estimate it at all?

**Part IV — The verdict.**

13. State the *named result* : the minimum connections and addresses for the subscription set under the venue’s limits, and the book staleness a gap costs with per-symbol against per-connection resynchronisation.
14. Which design choice matters most?
15. What would change at a venue without per-symbol sequence numbers?
16. How should the shards be spread over the day’s 24-hour resets?
17. What does a second connection to the same streams buy?
18. What does Book 3’s governor add that a simple counter would not?
19. Where does this go in chapter 29’s plan?
20. In one sentence: what does a lost message cost?

**Solution of Problem 20.1.**

**Part I.**

1. 800 streams, 5 connections of 160, 1 address.
2. One connection.
3. Still one: five reconnections in 10 seconds are well within the per-address limit.
4. Every connection must be replaced at least daily: stagger the resets and reconnect before the venue does, with a new connection subscribed before the old one closes.

**Part II.**

1. Five (the lost messages touch five symbols) per symbol; all 80 of the connection per connection.
2. $180.1\,\mathrm{s}$ , and 5 769 stale symbol-seconds.
3. $0.2\,\mathrm{s}$ and 11.2 symbol-seconds: 80 snapshots of weight 50 fit in one minute.
4. Send any request that needs weight, orders included, until the recovery’s snapshots have used their windows.

**Part III.**

1. Risk 500 (all it asks), market making 3 300, arbitrage 2 200.
2. As a reserved share, or through the risk class: recovery must not be starved by trading, nor starve it.
3. Within $15\,\text{µ}\mathrm{s}$ of the truth, from $-2.23\,\mathrm{m}\mathrm{s}$ at the start to $-4.20\,\mathrm{m}\mathrm{s}$ at the end.
4. To measure latency to and from the venue on one time base, and to notice when the venue’s clock, and so its timestamps, move.

**Part IV.**

1. *Named result* : 800 streams need five connections of 160 and one address under the venue’s limits; five lost messages cost 0.5 stale symbol-seconds with per-symbol recovery, and 5 769 symbol-seconds (the last book back after three minutes) with per-connection recovery from full-depth snapshots.
2. Per-symbol recovery; then the snapshot depth.
3. The firm could not tell which symbols missed messages and would have to rebuild every book on the connection: smaller shards and shallower snapshots would then be the only defences.
4. Evenly: a few connections at a time, each renewed before the venue closes it.
5. A second copy of every event: a missed message on one is usually present on the other, so the book needs no snapshot; the first copy wins.
6. Fixed windows aligned like the venue’s, several rules at once (weight, orders per interval, per day), and the pause on 429 and 418 answers.
7. In the crypto rows: shards, addresses, governors per limit, recovery design and snapshot depth, and the clock-skew monitoring.
8. Either a few tenths of a second of one book, or minutes of every book on a connection and of the firm’s whole rate budget.

## 20.10 Interview questions

**Interview question 20.1 ★ developer.**

How do you keep a local order book correct from a snapshot and a stream of deltas?

**Solution of Interview question 20.1.**

Buffer the deltas, fetch a snapshot, drop the deltas at or before the snapshot’s update id, apply the rest in order; if a delta’s first update id is beyond the book’s last plus one, discard the book and start again; verify with the venue’s checksum where it offers one.

*What the interviewer is looking for: Sequence numbers; the gap rule; snapshot and buffer ordering; checksums.*

**Interview question 20.2 ★★ developer.**

You need 2 000 streams from a venue. How do you design the connections?

**Solution of Interview question 20.2.**

Below the venue’s per-connection cap (a few hundred streams each), a dozen connections spread over two or more addresses, symbols balanced by message rate, reconnections staggered, per-symbol recovery, and a spare connection ready.

*What the interviewer is looking for: Caps and limits; failure domains; staggering; recovery design.*

**Interview question 20.3 ★★ developer.**

Three strategies share one API key’s rate limit. How do you stop one of them from starving the others?

**Solution of Interview question 20.3.**

Route every request through one governor per venue limit and give each strategy a share by priority (water-filling), with a reserved share for risk and recovery; refuse or queue what exceeds a share rather than letting the venue answer 429.

*What the interviewer is looking for: Central governor; allocation; reserves; no reliance on the venue’s errors.*

**Interview question 20.4 ★★ developer, researcher.**

How would you estimate a venue’s clock error from its market data?

**Solution of Interview question 20.4.**

Stamp arrivals with a synchronised clock and track the minimum of arrival minus the venue’s event time over windows: its level is the minimum delay minus the venue’s offset, and its changes are the offset’s. Cross-check against round trips measured with the venue’s own time endpoint.

*What the interviewer is looking for: Minimum-delay filter; separating delay from offset; verification.*

**Interview question 20.5 ★★ developer.**

REST, WebSocket or FIX for order entry: how do you choose?

**Solution of Interview question 20.5.**

By latency, recovery and limits: a persistent WebSocket or FIX session avoids per-request handshakes and gives sequence numbers (FIX) or push acknowledgements; REST is simple and stateless but slower; check whether the venue counts all paths against one limit and which offers [private endpoints](https://one-course.com/books/quant/14/en/chapter/18-private-connectivity-to-crypto-venues#def-nw-private-connectivity-to-crypto-venues-endpoint).

*What the interviewer is looking for: Session against request; recovery semantics; shared limits.*

**Interview question 20.6 ★★★ developer.**

Your feed handler loses messages every day at the same time. What do you look at?

**Solution of Interview question 20.6.**

The 24-hour reset or a scheduled venue event (connections all opened together, reset together); the machine’s own schedule (a cron job, garbage collection, a backup); message rates at that time (an index rebalance, a funding time); and the limits (5 incoming messages a second, reconnection limits) hit by a burst of re-subscriptions.

*What the interviewer is looking for: Periodic causes; staggering; limits; measure before guessing.*
