Overview
On a market with Maker Protection, any order action that could take liquidity — that is, any order not marked post-only — is held for the market’s configured window before it reaches the matching engine. Post-only placements and all cancellations are never held.
The delay sits in the order gateway in front of the matching engine, not in the engine itself. Every client path passes through it, so the behaviour is the same whichever protocol you use. Because the hold happens before the request is sequenced into the engine, a held order takes its queue position at release, not at receipt.
The only way to avoid the delay is to submit the order as post-only. A limit order without post-only is held regardless of whether it would in fact have rested — the classification is by order type, not by outcome.
Which markets have it
ReadmakerProtectionMillis from the instruments endpoints. It is the authoritative, live source — the market list changes as the rollout progresses.
GET /instruments and GET /trading/instruments, and is omitted entirely when the market has no Maker Protection configured. Treat “absent” and “zero” as the same thing: no delay.
The ten most liquid linear perpetual markets are excluded at every phase, so that active taker flow in the majors is not slowed. Every perpetual listed after 24 September 2026 has Maker Protection applied from launch. Additions to the list are announced on status.kraken.com ahead of each maintenance window.
Phase 1 markets — 24 September 2026
Phase 1 markets — 24 September 2026
These 59 markets are covered at launch. This list is a point-in-time record; query
makerProtectionMillis for the current set.PF_2ZUSD · PF_ALCHUSD · PF_ANTHROPICXUSD · PF_ASTERUSD · PF_ASTRUSD · PF_ATOMUSD · PF_BELUSD · PF_BRENTOILUSD · PF_CHFUSD · PF_CKBUSD · PF_CTSIUSD · PF_CYBERUSD · PF_DEEPUSD · PF_DEGENUSD · PF_DYMUSD · PF_ENJUSD · PF_GALAUSD · PF_GRIFFAINUSD · PF_HMSTRUSD · PF_ICPUSD · PF_IDUSD · PF_INTCUSD · PF_IOSTUSD · PF_LCAPUSD · PF_LDOUSD · PF_LRCUSD · PF_METISUSD · PF_MINAUSD · PF_MTLUSD · PF_MUUSD · PF_NATGASUSD · PF_NBISUSD · PF_NEIROUSD · PF_OPENAIXUSD · PF_OPUSD · PF_PENGUUSD · PF_PROMPTUSD · PF_SAMSUNGUSD · PF_SKHYUSD · PF_SNDKUSD · PF_SOONUSD · PF_SOXLUSD · PF_SOXSUSD · PF_TUSD · PF_US100USD · PF_VELOUSD · PF_VIRTUALUSD · PF_WIFUSD · PF_WTIOILUSD · PF_XAGUSD · PF_XAUUSD · PF_XCNUSD · PF_XCUUSD · PF_YFIUSD · PF_ZILUSD · PI_ETHUSD · PI_LTCUSD · PI_XBTUSD · PI_XRPUSDWhat is and isn’t delayed
An edit is classified against the order your account placed, not against what your order-status feed has caught up on. An edit sent immediately after a placement is therefore held on the same terms as one sent to a long-resting order, even though the target may not be visible to you yet. Only an edit naming an identifier your account has not placed — and that no resting non-post-only order answers to — is exempt.
Order lifecycle
Four properties are worth designing around:- Most of your order’s validation happens at release, not at submission. The request is held untouched and only reaches the matching engine when the window expires, so margin, price collars and market status are all evaluated at that later moment. See What can happen while an order is held. The exceptions are the account-wide limits you could otherwise move during the window — your open-order count, the contract’s maximum position, and your client order IDs — which are decided when the hold opens. See Account limits are decided when the hold opens.
- The full window is always served. The hold is decided from market conditions at submission. If the liquidity that made your order aggressive disappears during the window, the order still waits out the delay before entering the book. Held orders are not re-evaluated.
- The queue is FIFO. With a fixed delay, holds are released in the order they were accepted. A later order cannot overtake an earlier one inside the queue.
- The contract is “at least N ms”. Orders you submit are released by a timer and land very close to the configured window. Orders fired by a trigger are different: they wait in the matching engine and are released by the next event it processes, so on a quiet market a stop or take-profit can be held noticeably longer than the configured window. Never assume the delay is exact, and never infer it by measuring latency — read
makerProtectionMillis, which can be changed at any time.
What can happen while an order is held
A held order is not yet in the book, and it is not guaranteed to get there. The window is an interval in which your order can be rejected by events that have nothing to do with your own trading:
The practical consequence: an order that returns a rejection roughly one window after you sent it has usually not been rejected on its own merits. Read the returned status rather than assuming the placement itself was malformed.
Account limits are decided when the hold opens
A held order is committed but not yet matched, so any account-wide setting you can change during the window would otherwise decide the fate of every order you have in flight — not just the one it names. Three of them are therefore settled when the hold opens rather than at release, and one is refused outright while you hold anything.The maximum-position reservation covers only the shapes whose size is known at submission: a plain placement, and an order group’s parent when it is one. An initial-margin market order sizes itself from available margin at release, and an amend’s realised quantity depends on fills during the window, so neither reserves anything.
How many orders you can have held at once
You may have at most 250 requests held at once. A request past that cap is refused rather than forwarded, and reports as though you had hit your order limit:
Three properties to design around:
- It bounds simultaneity, not rate. A hold releases after at most 100 ms and hands its slot straight to the next request, so a steady stream of aggressors well inside the cap is never refused. What the cap prevents is a standing ladder of many live holds at once.
- The budget is per member, not per account. A subaccount charges its master’s budget, so the cap cannot be side-stepped by spraying the same ladder from many subaccounts — and one strategy sitting at the cap can refuse another’s aggressor on the same member.
- Every held shape counts, including an order group whose parent is held, and a held amend.
Self-trade prevention
A liquidity-taking order released from a hold always cancels the resting order of your own it would match, overriding the self-trade strategy configured on your account (GET / PUT /self-trade-strategy). It applies across the whole account tree — the maker may belong to your account, your master, a sibling or a sub-account.
This closes an evasion the hold would otherwise leave open: post-only orders are never held, so an account could drop one in front of its own held taker and have the default REJECT_TAKER strategy kill the release, recalling committed aggression for the price of one extra message.
Behaviour by protocol
There is noheld order state anywhere in the public API. Maker Protection surfaces as extra latency on aggressive placements, not as a new state to model.
- REST
- WebSocket
- FIX
The connection is simply held for the duration of the delay, and the response carries the final outcome —
placed, filled, cancelled or a rejection — exactly as it would without Maker Protection.Set your client-side request timeout comfortably above the market’s makerProtectionMillis. A timeout tighter than the window will abandon requests that are about to succeed. The window can never exceed 100 ms, so a single timeout budget covers every market.Cancelling a held order
You can cancel an order while it is held. Cancels are never delayed, so a cancel sent immediately after a placement can overtake it inside the window. A cancel cannot recall committed aggression. Cancelling inside the window does not withdraw the order: it removes the order’s right to rest, not its obligation to trade. The held request is rewritten to immediate-or-cancel and released at its original expiry, where it takes whatever liquidity it can and the remainder is discarded instead of joining the book. Address the cancel by order ID or by client order ID. For a held placement the client order ID is your only option — the engine has not assigned an order ID yet. A held amend is different: the order it targets is already resting, so it has an order ID you can use. What a cancel does inside the window depends on the shape of the request being held:
After release, timing is ordinary:
Edits cannot claim a held order. Only a cancel can — a single cancel, or your own cancel-all. When both a held placement and a held amend of the same order exist, amends are claimed first, and every matching amend is claimed, not just the first.
How a converted placement is reported
A conversion is not a new state and not a new status code. The cancel and the order are answered separately:
So a cancelled hold produces two responses: the cancel’s, and the order’s own — the latter about one window later. An
iocWouldNotExecute on an order you submitted as a plain limit order is the signature of this path.
How a withdrawn hold is reported
The claims that do withdraw an order — a cancel of a held post-only order, and an admin cancel-all — never reach the matching engine, so they are reported locally:
There is no dedicated “cancelled while held” value in the public enums. Distinguish this case by the cancel you sent, not by the code.
Cancelling while an edit is held
Amending a resting order so that it would cross the book is claimable too, and the outcome is the one instruction that reads least like a cancel. While the amend is held, the original order is still live in the book, unchanged, at its old price — the amendment has not reached the matching engine, so the order can still trade on its old terms during the window. A cancel of that order inside the window is absorbed: it is answered by the gateway and never forwarded, so the engine does not cancel the target. At release, the amendment is rewritten to reprice that same order to the price you committed to and to give up its right to rest. Same order ID, same client order ID, same order group. Both of your instructions therefore take effect — the amend crosses, and what it would have left behind does not sit on the book: A converted amend has exactly two outcomes. Either it trades and leaves nothing resting, or the order is gone:orderForEditNotFound is not the expected outcome of cancelling during a held amend. If you see it, the order had genuinely already left the book — it is not the signature of this race.REJECTED_AFTER_EXECUTION, so the fills that are already booked are visible rather than hidden behind an error.
Two amends of the same order can be held at once. A cancel claims both, because converting only one would let the other release as a plain edit and re-rest the order the cancel has just been acknowledged for.
Order groups cannot be cancelled while held
An order group whose new parent order would take liquidity is held, but it is not a claimable hold. A cancel addressed to the parent order ID during the window finds nothing, returnsORDER_NOT_FOUND, and the group still goes live when the window expires. You cannot stop the group inside the window; cancel it after it is live.
Reusing a client order ID inside the window
A hold reserves its client order ID for the length of the window, so that a committed aggressor cannot be recalled by racing another order onto the same identifier. Two cases follow, and they are answered differently:
The reservation lasts exactly as long as the hold and is dropped when the order is released. Held amends do not reserve an ID — the order they target is already resting at the matching engine, which remains the authority for that identifier.
If you cancel an order and immediately replace it reusing the same client order ID, both can be in flight within one window. While that is true, the replacement is addressable by order ID only — a cancel by client order ID still resolves to the first order.
Either wait out the window before reusing an identifier, or address in-flight cancels by order ID.
Cancel-all while orders are held
Your owncancelallorders claims every held placement and held amend in scope, on exactly the same terms as a single cancel: placements are converted to immediate-or-cancel, and amends are converted in place.
Because a held amend’s target is already resting at the engine, a sweep that claims one also carves that order out of the sweep: it is deliberately left in the book, and the converted amend removes it when it releases. So a cancelallorders on a Maker Protection market can return having left an order resting, by design.
Known gap. A held amend whose target is swept loses that target, so its aggression cannot be preserved: the amend is answered as a rejection rather than converted. Reconcile from the amend’s own response rather than assuming the sweep result covers it.
- A carved-out bracket parent keeps its group’s triggers. They are not cancelled with the rest of the sweep, so the position the amend fills is not left without its take-profit and stop-loss.
- An order spared by one sweep stays spared. Once an amend has been converted, the order it targets is left alone by later cancel-alls too, until that amend releases and removes it.
Batch orders
A batch is not held as a single unit. The window starts at the first liquidity-taking instruction in the batch:- Instructions before the first aggressor are forwarded immediately.
- The first aggressor and everything after it wait out the window together.
- Cancels are forwarded immediately wherever they appear. A cancel placed after the order it targets claims that order’s hold within the same batch — converting it, exactly as a separate cancel would. A cancel placed before it cannot claim anything: at that point the placement does not exist yet, so the cancel resolves against whatever order you already had under that identifier.
Reference
Testing
Maker Protection has been enabled on the Phase 1 markets in the client UAT environment since 27 August 2026, at the same 20 ms window and the same 250-hold cap production launches with. Test your order handling there before the production date. Contact your account manager for UAT access. Worth exercising specifically, since each one has a non-obvious outcome:- Cancel during a hold. Confirm you handle the order still filling after a successful cancel, and that you do not retry the placement.
- Cancel during a held amend. Confirm you handle a successful cancel followed by the amend’s own fills or reject, rather than expecting
orderForEditNotFound. - Your own resting order in the way. Confirm you tolerate a maker of yours being cancelled with
CANCELLED_BY_SELF_TRADEeven withREJECT_TAKERset. - The concurrent-hold cap. If you run a high-rate strategy, confirm you handle
tooManyOrderson a placement — and that you retry it rather than treating it as a permanent limit. - Client order ID reuse inside a window. Confirm you handle
clientOrderIdAlreadyExistarriving immediately on submission rather than at release. - Batch instruction ordering, and client-side timeouts above the market’s
makerProtectionMillis.