Optimising latency
Most of an order's round trip is consensus; code wins by streaming reads, cutting serial round trips, using the fast order class and never stalling orders.
The API server hop, mempool and HyperBFT commit are protocol, and no code removes them. Per the docs, they add up to about 380 ms end to end for a cancel or ALO order. Your code controls the rest: round trips per decision, their distance, the ordering class, and whether bookkeeping stalls an order.
Say you hedge from Ireland while the API servers run in Tokyo, on AWS. One such hedge measured 350 to 500 ms: about 110 ms of transit plus four sequential round trips. Cutting round trips and moving to Tokyo are the levers.
Sequencing is far less noisy than latency: send times varying under 10 ms produce predictable ordering on the L1. So measure where your transactions land relative to others, not only reply time.
Stream reads, then run your own node
Section titled “Stream reads, then run your own node”Polling REST is the slowest view of the book and spends IP weight that order placement needs (rate limits): subscribe over WebSocket.
Past that, the docs’ read path is your own non-validating node (running a node):
- Peer with a reliable node such as the foundation non-validator.
--disable-output-file-bufferingwrites outputs as soon as blocks execute.- Hardware at least as in the numbers; more cores execute blocks faster.
- Build the book locally from node outputs, faster and more granular than the API. The docs’ example order book server is not actively maintained: fork it or write your own, and handle ALO priority fees.
--batch-by-blockwaits for block end before writing: simpler to consume, but turning it off and inferring boundaries is faster.split_client_blocks: truestreams transactions 70 to 150 ms sooner, before inclusion in client blocks and before execution, so results must be predicted (reasonable for simple actions such as orders). Predictions must handle actions that later fail.
Beyond that, read priority is bought (priority fees).
Send fewer round trips, in the fast class
Section titled “Send fewer round trips, in the fast class”Count serialised round trips. Prepare everything an order needs (metadata, precision rules, leverage) before the signal, and never put an /info call in the order path. The order path depends only on cached state, the nonce source and the signer: a read that stalls it costs more than any network tuning saves (rate limits).
Keep connections warm and small writes immediate. One WebSocket carries reads and signed actions. On TCP sockets you control, set TCP_NODELAY so a small order is sent at once, not held to coalesce.
Land in the fast class. Cancels and ALO orders sent at time t almost always execute before IOC and GTC orders sent at the same time, across several blocks; within each consensus bundle, ALO orders and cancels execute first. The docs recommend:
- Cancels with the fast flag
f: true; its only cost, and its only effect today, is that it cannot cancel trigger orders. The docs say a future upgrade will prioritise only fast cancels in the mempool, so set it now. - Batches every 0.1 s from one task per process, ALO in batches of their own: ALO-only batches are prioritised.
- Order priority for IOC orders that must arrive sooner.
One API wallet per process keeps nonces apart
Section titled “One API wallet per process keeps nonces apart”Nonces are tracked per signer, the account key or the signing API wallet (nonces and API wallets). Several processes signing with one key and the millisecond clock collide: two orders in one millisecond share a nonce, and one is rejected.
The docs’ fix: one API wallet per trading process, and in each process one counter every batch draws from, fast-forwarded to the current millisecond when behind. It tolerates out-of-order arrival within 2 seconds.
// One instance per signing key, shared by every task in the process.export class NonceSource { private last = 0;
next(): number { const now = Date.now(); this.last = now > this.last ? now : this.last + 1; return this.last; }}One API wallet signing for several sub-accounts shares one nonce set across them: give each sub-account its own.
Failing safely on shutdown and crash
Section titled “Failing safely on shutdown and crash”A quoting process that exits leaves ALO orders resting and filling while nothing hedges. Cancel everything on shutdown and keep scheduleCancel armed for crashes: at least 5 s ahead, re-armed on a heartbeat, at most 10 firings per day (orders).
For an order in flight, the docs call noop more effective than cancel: signed with the pending order’s nonce, it marks that nonce used so the order cannot land. After a WebSocket drop, reconcile in-flight posts by cloid (WebSocket). A stale expiresAfter rejection costs 5 times the usual address budget, so a short expiry as a latency guard has a price.
The numbers
Section titled “The numbers”| Item | Value |
|---|---|
| End to end, cancel or ALO order | about 380 ms |
| Commit | usually 2 blocks |
| Send-time variation for predictable ordering | under 10 ms |
split_client_blocks gain |
70 to 150 ms |
| Node hardware | 32 logical cores, 128 GB RAM, 500 MB/s disk |
| Suggested batch cadence | every 0.1 s, ALO batched separately |
| IOC order priority | about 45 ms per bp, linear to 8 bps |
| Gossip priority | about 25 ms per slot |
| Tokyo and Ireland hedge (measured) | 350 to 500 ms |
| Gossip peer RTT (measured, TCP connect on ports 4001 and 4002) | about 70 ms (APAC) to 252 ms (eastern Europe) |
| Nonce window | 2 days before to 1 day after block time |
| Nonces kept per signer | 100 |
For the trading decision this page serves, see Latency, priority and infrastructure. For the full nonce rules, see Nonces, expiry and API wallets.