All research
9 min readVenue RiskMarket MakingMonitoringLive Trading

The outage that closes the cheap exit: asymmetric halts and the 39 silent minutes

A prediction-market position leaves two ways — merged at +2.6 c/share or resolved at −17.9. Cancel-only mode shuts the cheap door and leaves settlement running, so the venue transfers the cost of its outage onto whoever holds inventory. Both read endpoints returned 200 throughout. Cancels died 38 minutes before places did, and for 39 minutes before any error appeared the venue accepted every order and matched none.

What this is about

Polymarket is a prediction market. You buy shares in a yes-or-no question — will the highest temperature in Tokyo be 24°C on 22 September? — and at settlement each share pays exactly $1.00 or exactly $0.00. Nothing in between. Questions cover weather, sports, elections and crypto prices, and most resolve within days.

I run an automated market maker on it. The bot quotes both sides of a market and earns the spread: buy one YES and one NO on the same market and the pair redeems for exactly $1.00 whatever happens, so the profit is locked the moment the second leg fills. Polymarket also pays a maker rebate for providing liquidity. The risk is the leftover — shares whose other half never filled, which go to settlement alone and pay 1.00 or 0.00.

Everything below comes from six weeks of live quoting with real money: 701 settled markets, $19,889 of deployed capital, one account, one venue.

Venue outages are usually written up as downtime: minutes lost, volume forgone, an apology on a status page. For a market maker holding inventory, that framing misses the part that costs money.

On 19 September 2026 Polymarket entered cancel-only mode for about two hours — orders could be withdrawn but not placed. The bot had been running 117 hours and held 186 markets. Nothing broke on our side.

This piece is about what a halt does to a book you cannot stop holding, and about why the obvious way to monitor for one does not work.

The asymmetry

A position leaves this book exactly two ways, and they are not close in cost:

Exit pathPer shareRequires
Merged into a complete set+2.6cplacing an order
Resolved at settlement−17.9cnothing

Measured over 396 resolved markets.

A halt that stops order entry while settlement proceeds does not pause the strategy — it forces every position maturing in the window through the expensive exit. The venue transfers the entire cost of its outage onto whoever is holding open inventory.

Quantified on this book: merge income runs +1.524 $/h against a structural shortfall of −0.158 $/h. The engine carries about 90% of its own liability. Switch it off and the bleed rate goes to roughly −1.68 $/h — ten times worse — because resolutions keep maturing on their own clock and nothing is being earned against them.

The 39 minutes nobody could see

The obvious monitor is a liveness probe. It does not work, and this incident is why: GET clob.polymarket.com/ok returned 200 and GET clob.polymarket.com/markets returned 200, throughout.

Both read endpoints were healthy the whole time. Reads are not writes. A probe that asks whether the venue is up answers a question nobody has; the question is whether this account can place an order, and the only honest way to know is to have tried.

Worse, the failure was not even synchronous with the errors. Reconstructing the window from the bot's own tape:

TimeEvent
20:54venue status page opens “Investigating”
21:00last fill
21:01CANCEL refusals begin (757 of them, through 21:55)
21:39PLACE refusals begin (“503 trading is disabled”)
22:53last refusal
22:56first fill

Cancels died 38 minutes before places did — so for that stretch the bot could not withdraw stale quotes but could still add to them, which is precisely the state adverse selection feeds on.

And earning stopped at 21:00:28, 39 minutes before the first explicit error. The venue accepted orders and matched none. No error-based detector can see that window, because there were no errors in it.

Detecting what produces no errors

The fix was a second detector that watches for the absence of fills rather than the presence of failures — with the threshold relative to the run's own rate, because “no fills for 20 minutes” is an outage at 40 fills an hour and an ordinary Tuesday at three.

Run alone it is useless. Over one session it flagged eight droughts, seven of which were the overnight book being slow:

WindowLengthEvidence
00:35 → 01:0630 minsilence only
01:13 → 01:3421 minsilence only
… five more …
21:00 → 22:56116 mincorroborated by 823 refusals

Seven false alarms against one real find is a signal an operator correctly learns to ignore. Marking a drought only when observed refusals overlap it collapses eight rows to one — and that one starts at 21:00:28, 39 minutes earlier than the refusal record alone would say.

That is the whole technique: silence is evidence, but only in the presence of a second witness.

The number that reframes the risk

Polymarket's status page reports uptime per service. The aggregate for Predictions is 99.71%; the web app is 99.99%.

The Predictions Trading API — the CLOB, the thing a maker actually trades through — is 99.16% over 90 days.

That is about 18 hours in 90 days, roughly 6 hours a month, and it is the number that matters. The aggregate flatters it by an order of magnitude in the wrong direction.

At 1.524 $/h of forgone merge income that is roughly $9 a month for this book — small. But the rate, not the total, is the point: an outage hour costs about ten times the hourly structural shortfall, and it arrives concentrated rather than spread.

Where the real damage went

Here is the part that upends the intuitive reading. When the session was later restarted, its first 18 hours looked terrible. Almost none of it was the new session:

Settled in the new session's first 18.7 hoursMarketsP&L
Opened by the PREVIOUS run26−$51.43
Opened by this run4−$10.85
Total30−$62.28

83% of the resolution damage belonged to a book built under a different configuration, settling now because that is when its markets ended.

This is the trap in reading session P&L at all. A session's window contains whatever happens to be maturing, not what that session did. Restart at the wrong moment and you inherit the previous configuration's bill while its income has already been banked elsewhere — which is exactly how a change gets blamed for something it never touched.

What this establishes, and what it does not

Does: that read-endpoint liveness probes cannot detect a write halt; that a venue can stop matching before it starts refusing; that drought detection needs corroboration to be usable; that cancel and place capabilities fail separately and the distinction matters.

Does not: anything about Polymarket's reliability relative to other venues — this is one account's view of one incident plus a published uptime figure. Nor does it price the outage properly: the forgone-income figure assumes the session would have earned at its average rate, and outages may well correlate with exactly the volatile conditions where that assumption is worst.

One limitation worth stating plainly. An outage's end cannot be observed from failures alone — the absence of a refusal is also what a stopped process looks like. The only honest end marker is positive evidence that trading worked again, which here is the first fill: 22:53:23 last refusal, 22:56:00 first fill, recovery bracketed to under three minutes without inferring anything.