Skip to main content
What we measured, how, and what we have not measured yet. Every number on this page is MEASURED in the run named with it, with its sample size and the machine it was measured from. A number we have not measured does not appear in a table.

Run of 2026-10-21

  • When: 2026-10-21, 00:26 to 01:04 UTC (38 minutes).
  • From: one virtual server in Vilnius, Lithuania (the location its address geolocates to), over IPv4. This machine is far from our servers: its median TCP connect to our API took 198 ms.
  • Key: one free-plan key with market:read. Our API was paced at 40 requests a minute (the free plan allows 60), each venue at no more than one request every 2 seconds, one stream connection at a time.
  • Markets: 12 legs on 8 markets, chosen at the start of the run: 4 Kalshi and 4 Polymarket legs from /opportunities (markets listed on both), and 4 Limitless legs from the top of /markets/search.
  • Load on the measuring machine: shared with other work, sampled about once a minute (38 readings): a 1-minute load average of 1.3 to 9.8 on 4 CPUs and 61% to 71% CPU steal in every reading, so this run has no unloaded comparison. Under the same load, a TCP connect to Kalshi’s nearby edge took 7.5 ms at the median (n = 20), which bounds the network-stack delay this machine adds to a request at a few milliseconds; delays in our client’s own code are not bounded by it, and they can widen the tails.

Method

  1. Each request is timed with a monotonic clock from the moment it is sent: time to first byte (TTFB) when the response headers arrive, total when the last body byte arrives.
  2. A request is cold when a new TCP and TLS connection was made for it (observed, not assumed) and warm when it reused one. At least every fifth request per route was made on a fresh connection (more when a server had closed the idle connection).
  3. Routes are sampled round-robin over the whole window, so each route sees the same network conditions.
  4. Our book against the venue’s: right after each of our order-book answers, the venue’s own public book for the same market is read, and the best YES bid and ask are compared. A match is both within 0.05 cents.
  5. The network floor is the TCP connect time to each host, 20 connects per host before the window.
  6. Percentiles are linear-interpolated between the closest ranks. The metrics were written down before the run started, and every raw sample is kept with the run.

Network floor

TCP connect time from the measuring machine (n = 20 per host). The venues answer from content-delivery edges near this machine; our hosts do not. To judge what our servers add, compare our numbers with the floor to our hosts, not with the venues’ figures.

REST latency

Warm requests, total time in ms, including the error answers a route gave (see Reliability). A cold request (new connection) to the order book took 791 ms (Kalshi, n = 48), 797 ms (Polymarket, n = 24) and 791 ms (Limitless, n = 30) at the median: about 500 ms of TCP and TLS handshakes on top. What it means:
  • /key and search answer in about one network round trip (200 ms against a 198 ms median connect): from this machine, distance is nearly all of their time.
  • Order books and trades take about 95 ms more than that, on every venue, which is the time to read and check the book or tape on our side.
  • /events spends about 400 ms more before its first byte and 200 ms more on its body.
  • Keep connections open (HTTP keep-alive) and reuse one client: a new connection costs about 500 ms here.

Freshness as served

The age fields our answers carry, read from every answer during the run. An order book’s age is the time since its last change, not since we last checked it. The next section shows that the old books were unchanged on the venue too. On Polymarket, one market’s newest trade was 244 s old at the median, and three were 27 to 49 hours old. On those three, the newest trade time we served was within 3 s of the newest trade in Polymarket’s own public trade history: the markets had not traded for that long.

Our book against the venue’s

Our order book, then the venue’s public book for the same market straight after it, compared on the best YES bid and ask. Read this table with three limits:
  • Pairs are our 200 answers only. The order-book requests we answered 503 are not in it (see Reliability).
  • The top of book moved on 1 of the 9 compared legs (a Polymarket market, 7 different tops over 30 pairs); on the other 8 it did not change during the run, which is easier to match.
  • “The same market” means the market our answer names in venue_market_id.

A second window on busier markets

2026-10-21, 01:38 to 01:51 UTC, same machine and pacing, 9 legs on 3 markets listed on all three venues and among Polymarket’s busiest by 24-hour volume: the Thunder against Spurs game and two US midterm balance-of-power markets. The books changed during this window (our median age_ms per leg was 0.2 s to 41 s), but the best bid and ask prices did not change on any of the 7 compared legs; the comparison covers prices, not sizes. The other 2 Limitless legs answered 503 throughout and are not in the table.

Coverage

One walk of GET /public/v1/events (32 pages) found 3122 active events. 3007 of the 3122 events (96%) are listed on two or more venues: 2578 on two, 313 on three and 116 on all four. Reading the details of 40 of those events gave 128 active markets, all 128 listed on two or more venues (Kalshi 124, Polymarket 121, Limitless 15, predict.fun 10).

Stream

One connection, 600 s, 36 channels (book, price and trades for each of the 12 legs). The three Limitless legs whose books had not changed within the 1 h bound answered a status of upstream_unavailable instead of data, and one Limitless leg’s book and price frames began 250 s after subscribing. Both clocks in the last row are ours, so it measures our stream’s own delay after a change is stamped, not the venue’s time to us.

Reliability

The 282 answers of 503 came from 6 of the 12 legs, for two reasons. The book had not changed for longer than the venue’s freshness bound (Limitless 1 h, Kalshi 20 min), so the API refused it rather than serve it without a fresh timestamp; the venue showed the same unchanged top of book.
  • 90 from 3 of the 4 Limitless order books (all 30 requests each). Limitless showed the same two-sided top of book on all 58 of our reads per market.
  • 12 from 2 Kalshi order books (8 and 4 answers). Their served age_ms reached 1159 s and 1166 s against the 1200 s bound; the venue’s top did not change, and our book matched it on the reads before and after.
  • This run did not record the 503 messages; the second window, which does, gave the same reason on all 36 of its Limitless book refusals: “the book is 4228 s old, older than the limitless bound of 3600 s” (and similar, up to 9293 s).
The other 180 answers came from 6 trade tapes (2 Kalshi and 4 Limitless markets, all 30 requests each), answered with no trade tape (the second window, which records messages, shows “no live tape for this leg”): the market had had no trade since our tape began. Checked against the venues’ public trade history afterwards, the 2 Kalshi markets’ newest trades were 8 and 10 days before the run, 2 of the Limitless markets’ 66 and 227 days before, and the other 2 Limitless markets list no trades. There was no 429, no 500 and no failed connection. In the second window, 91 of 475 answers were 503: 54 “no live tape for this leg” (3 Limitless tapes), 36 for 2 Limitless books past the 3600 s bound, and 1 “no live book” for a Kalshi book whose other 17 answers were served.

Earlier run (2026-10-20, without a key)

A run made the evening before (21:10 to 21:37 UTC, same machine, no key) measured only routes that need no key. Warm GET /public/v1/stream/protocol took 201 ms at the median (n = 147). A stream handshake without a key was refused with 401 unauthorized in the error envelope every time (n = 5).

Caveats

  • One vantage point, far from our servers. A client close to them sees lower numbers; we have not measured that yet.
  • The measuring machine was under load (see above), which widens the tails a little.
  • A small sample of markets (12 legs, then 9 more) and one stream session.
  • The free plan only. No load test was run: this page measures one client at a time, not capacity.
  • Trading is not live, so order-placement latency is not measured.

Reproduce a figure yourself

Time any route with curl from your own machine; run it a few times so the connection is reused:
Every order book and list answer carries its own freshness (age_ms, universe_age_s, age_s), so you can measure the data’s age as served from your own requests: see Freshness.