Skip to main content
Maker Protection is a short, fixed delay applied to liquidity-taking order actions on selected Derivatives markets. It gives resting maker orders time to react to new information before an incoming aggressor can trade against them.

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

Read makerProtectionMillis from the instruments endpoints. It is the authoritative, live source — the market list changes as the rollout progresses.
The field is present on both 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 15 September 2026 has Maker Protection applied from launch. Additions to the list are announced on status.kraken.com ahead of each maintenance window.
These 57 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_IOSTUSD · PF_LCAPUSD · PF_LDOUSD · PF_LRCUSD · PF_METISUSD · PF_MINAUSD · PF_MTLUSD · 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_XRPUSD

What 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:
  • Your order is validated at release, not at submission. The request is held untouched and only reaches the matching engine when the window expires, so margin, position limits, price collars and market status are all evaluated at that later moment. See What can happen while an order is held.
  • 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.

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.
On the edit path this changes which of your two orders dies. A self-matching edit already destroyed the order being amended rather than refusing the edit; with the hold, the maker is cancelled and the amended order trades. If you rely on REJECT_TAKER to protect resting quotes on a Maker Protection market, that protection does not hold against your own released aggressors.

Behaviour by protocol

There is no held order state anywhere in the public API. Maker Protection surfaces as extra latency on aggressive placements, not as a new state to model.
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.
If you send processBefore on an aggressive order, its deadline must allow for the hold. The deadline is evaluated after the delay, so a processBefore shorter than makerProtectionMillis rejects every time with wouldProcessAfterSpecifiedTime.

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.
This is the easiest thing to get wrong. cancel on an aggressive held order means “do not leave anything resting”, not “forget I sent this”. If the market has moved in your favour during the window, a cancelled hold still fills. Release time never moves, so a cancel cannot be used to buy a free look at the market.
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.
On the v4 API, a converted amend that part-fills and is then refused because the remainder may not rest reports 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, returns ORDER_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.
Known limitation — OCO siblings do not see held legs. A group member whose activated order is held inside the engine is invisible to sibling cancellation and reduction, which walk booked orders and registered triggers only. If an opposing sibling fills during the hold window, the held leg is not removed, and both legs of the group can go live. Reconcile group state from fills after any sibling fill on a Maker Protection market rather than assuming one leg cancelled the other. A fix is in progress.

Reusing a client order ID inside the window

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, not the replacement.
  • If the first order is somehow still live when the replacement is released, the engine rejects the replacement with clientOrderIdAlreadyExist.
Either wait out the window before reusing an identifier, or address in-flight cancels by order ID.
If you need “get me out entirely, with nothing left resting and nothing new trading”, there is no request that does it inside the window. Wait out the window — it is capped at 100 ms — and then cancel. Anything you send during the hold can only change whether the order rests.

Cancel-all while orders are held

Your own cancelallorders 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. Two consequences worth designing around:
  • 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.
Claimed holds are reported through their own placement or edit responses and are not listed in the cancel-all response.

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.
The order you write your instructions in therefore decides which of them wait. If you want a passive instruction to reach the book without delay, put it ahead of any aggressive instruction in the batch. Self-trade resolution is decided per member, from that member’s own delay rather than from its position in the batch. A post-only member, or one on a market without Maker Protection, that waits behind an aggressor in the same batch keeps the self-trade strategy your account configured.

Reference

Testing

Maker Protection has been enabled on the Phase 1 markets in the client UAT environment since 27 August 2026. 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_TRADE even with REJECT_TAKER set.
  • Batch instruction ordering, and client-side timeouts above the market’s makerProtectionMillis.
The UAT environment and production run the same build at launch, so behaviour verified there is the behaviour you get on 15 September.