A trade copier can sit far under its rate limit all day and still fail every time it matters. Limits are budgeted as averages. Copier demand is an impulse: near zero between master trades, then a wall of requests inside a fraction of a second, sized by follower count. Same unit, different shape, which is why throttling arrives during the fast move and not during the quiet hour you tested in.

Key takeaway

API rate limits throttle trade automation at the worst moment because copier demand is a burst, not an average: one master trade multiplies into (calls per order) x (legs) x (follower count) requests inside a fraction of a second. Rejection is not spread evenly either, so a copier that dispatches its follower list sequentially in a fixed order strands the same tail accounts on every burst. The fixes are streaming instead of polling, rotated iteration order, spending scarce allowance on order submission before state queries, and exponential backoff with jitter on retries.

Why does an average limit fail a bursty client?

Because the limit is a rate and the demand is an impulse. Mean request rate is meaningless for a client that idles and then asks for everything at once. Only the peak matters, and it scales linearly with follower count.

Published allowances are specific and usually scoped to the connection rather than the account. cTrader's Open API documentation states you can perform a maximum of 50 requests per second per connection for any non-historical data requests, and a maximum of 5 per second for historical data requests. The historical bucket is ten times tighter, so a copier pulling bars or trade history over the connection it trades on spends from a much smaller purse than it thinks.

Scope matters more than the number: a per connection allowance is shared by every account authorized on that connection, so adding followers adds demand without adding budget. The same vendor documents that each connection can support an unlimited number of accounts of a certain type, and recommends creating at most two connections, one for demo and one for live. Both are true, and read together they are the tension this article is about: unlimited accounts, fixed request budget.

Treat any published figure as a snapshot, not a contract, since providers change limits and some evaluate them dynamically. Every example below uses an illustrative allowance of 30 requests per second, which no named broker publishes, chosen to keep the arithmetic exact. The per order call counts are a modelling assumption too: 3 when the copier submits, confirms and polls state, 2 when fills arrive over a stream. Count what your own setup spends on one order, then multiply.

What does a throttled client actually see?

Usually an explicit rejection, sometimes nothing at all. The status code is 429, defined in RFC 6585, which says it "indicates that the user has sent too many requests in a given amount of time." The same section says the response SHOULD include details explaining the condition and MAY include a Retry-After header. MAY, not MUST, so no client can assume it will be told how long to wait.

Section 7.2 of that document goes further: servers are not required to use the 429 status code at all, and when limiting resource usage "it may be more appropriate to just drop connections, or take other steps." A silent connection drop is legitimate throttling and is indistinguishable from network loss, so a copier that measures throttling by counting 429s under-reports it. Four more behaviours shape the client:

  • Rejections are not cached. RFC 6585 states that responses with the 429 status code MUST NOT be stored by a cache, so every retry gets a fresh verdict from the origin rather than a replayed rejection.
  • Rejected attempts can still cost budget. Some APIs count every request that arrives against the quota, including the ones they refuse; others charge only for what they serve. That one sentence in the documentation decides whether a retry loop is roughly free or whether it burns the next window's allowance on calls already refused. Find that sentence before you write the loop, and assume the stricter reading if it is absent.
  • Throttling can escalate rather than reject. Exchange level messaging controls sit above the broker's limiter, and a venue specification can define more than one tier: refuse the excess messages at one threshold, drop the session at a worse one. Thresholds and consequences are venue specific and change over time, so read the current messaging specification for the venue you route to. Rejection is the polite tier.
  • A block can masquerade as a freeze. MQL5 documents WebRequest() as synchronous, stating that it breaks program execution and waits for the response from the requested server. A throttled call from a MetaTrader expert advisor parks the calling thread until timeout and stalls unrelated logic sharing it.

Fixed window, sliding window, or token bucket?

Providers rarely document which algorithm they use, and standard response headers seldom reveal it, so you identify it from the failure pattern. Identical copier code passes on one broker and fails on another with the same published number.

AlgorithmMechanismWhat a fan-out burst feels likeHow you recognize it
Fixed windowCounter resets on a calendar boundaryA burst straddling the boundary briefly delivers double the rate, then hits a wallFailures cluster late in each window, and some bursts pass that should not have
Sliding windowCount evaluated continuously over the trailing N secondsSmooth, no free burst, cut off at request 31 of 30The rejection point is identical on every burst, with no boundary luck
Token bucketCapacity C, refilling at R per secondIdle time banks tokens, so the first burst passes and later ones do notFirst trade clean, second clean, third catastrophic
Leaky bucket or queueRequests queue and drain at a fixed rateNothing is rejected. Everything is lateNo errors at all, but fills land at prices the master never saw

Work the boundary burst exactly. Against a 30 per second fixed window counter, a client sends 30 requests at t = 0.980s (window [0, 1)) and 30 more at t = 1.020s (window [1, 2)): 60 requests in a 40 millisecond span, twice the nominal limit, then a wall for the remaining 980 milliseconds. The same client against a sliding window is cut off at request 31.

The token bucket fools people because it does not fail on the first trade. Model capacity 60, refill 30 tokens per second, a 36 call fan-out per master trade, and a full bucket after a quiet spell.

  • Trade 1 at t = 0.0s: 36 served, 60 - 36 = 24 tokens left.
  • Trade 2 at t = 0.5s: refill adds 0.5 x 30 = 15, giving 39; 36 served, 3 left.
  • Trade 3 at t = 1.0s: refill adds 15, giving 18; 18 of 36 served, 18 rejected, which at 3 calls per account is 6 entire accounts, half the book, receiving nothing.
  • Trade 4 at t = 1.5s: bucket holds 15; 15 served, 21 rejected, which is 7 accounts unserved.

Keep firing every 0.5 seconds and demand is 36 / 0.5 = 72 calls per second against a 30 per second refill, so 42 per second are permanently rejected. Clean, clean, then collapse, which is exactly the sequence a scalper produces.

The fan-out arithmetic that breaks the budget

One master trade is never one request. Assume an order costs 3 API calls: submit, confirm, then query the resulting position state. The master fires once and it fans out to 12 follower accounts, so demand is 3 x 12 = 36 calls inside a fraction of a second. Against the illustrative 30 per second allowance, 30 are served and 6 rejected, which is 6 / 36 = 16.67 percent of the burst.

That percentage hides the damage. The dispatch loop walks the follower list one account at a time at 3 calls each, so the first 10 accounts consume exactly 10 x 3 = 30 calls and close the gate on the nose. Accounts 11 and 12 receive zero of their 3 calls each: 2 accounts x 3 calls = 6, matching the 6 rejections exactly. The outcome is not "the book is 16.67 percent degraded." It is "2 of 12 accounts got nothing at all," and those two are flat while ten are in the trade.

36 CALLS, ONE GATE, TWO ACCOUNTS LEFT OUT FILL 12 branches x 3 calls dispatch loop one connection LIMIT 30/s accounts 1 to 10 30 calls served all in the trade 10 x 3 = 30, gate closes exactly here accounts 11 and 12 6 calls refused flat, holding nothing
The dispatch loop walks accounts in order at 3 calls each, so the first ten consume the entire 30-per-second allowance exactly and the last two receive none of their calls. The book is not uniformly 16.67% degraded; two named accounts are flat while ten are in the trade.

Trace the path. One master fill enters the copier's dispatch loop, fans into 12 per account branches, each branch emits submit, confirm and poll in sequence, and all 36 calls funnel back through one authenticated connection into the broker's limiter. The limiter is the merge point: it admits calls 1 through 30 and refuses 31 through 36, so the two branches at the tail of the loop never reach the exchange.

Bracket orders blow the budget fastest. A bracketed entry is three submissions: entry, stop, target. At 2 calls each (submit and confirm, fills arriving on a stream), one master bracket across 12 accounts costs 12 x 3 x 2 = 72 calls, or 2.4 seconds of a 30 per second allowance for one entry with zero polling. Add a state poll per leg and it becomes 12 x 3 x 3 = 108 calls, or 3.6 seconds. A scalper entering every 5 seconds averages 108 / 5 = 21.6 calls per second, comfortably inside the budget, and still fails, because the demand arrives as a 3.6 second wall rather than as 21.6 evenly spaced calls.

Why the same accounts fail every time

Rejection under a rate limit is not random. It hits whichever requests are processed last. If your copier iterates followers in a stable order, by account ID, signup date, or database row order, the same tail accounts are refused on every burst, permanently.

Quantify it over 6 consecutive master trades. With fixed ordering, accounts 11 and 12 fail 6 of 6 bursts, a 100 percent failure rate, while accounts 1 through 10 fail 0 of 6. Total failed account orders: 2 x 6 = 12. Now rotate the starting index by 2 accounts each burst. A 12 account list cycles completely in 12 / 2 = 6 bursts, so every account lands in the rejected tail exactly once, failing 1 of 6, or 16.67 percent. Total failed account orders: 2 per burst x 6 bursts = 12, identical to the fixed order case.

Rotation does not create capacity. It redistributes failure.

Randomizing order feels like a solution and is not. Only the distribution changes: a permanent 100 percent failure for two named customers becomes an occasional one in six miss for everyone. Fully random ordering gives the same expected miss rate of 2 / 12 = 16.67 percent, but the chance an account misses two bursts in a row is (1/6) x (1/6) = 1/36 = 2.78 percent, so it reintroduces clusters that rotation removes. The diagnostic value is the real prize: if two followers are chronically out of sync and the rest are perfect, check your iteration order before hunting for a broker bug.

How a retry turns a throttle into an outage

A naive client retries every rejected call immediately, adding load to an endpoint that just said it had none to spare. Trace the backlog with a 36 call fan-out every second against a 30 per second ceiling: second 1 offers 36, serves 30, carries 6. Second 2 offers 42, carries 12. Second 3 offers 48, carries 18. Second 4 offers 54, carries 24. The backlog grows by exactly 36 - 30 = 6 calls per second, so after 10 seconds it is 60 outstanding calls, which at 3 calls per account is 20 account orders of stale work on a 12 account book.

The honest caveat: a single isolated burst does not storm. Offer 36, serve 30, retry 6 in the next second, all 6 succeed, done. A storm needs sustained demand above the ceiling, or multiple clients synchronizing on the same retry instant.

OBEYING RETRY-AFTER EXACTLY BUILDS THE STORM 8 processes, 6 rejected calls each, all told "Retry-After: 1" proc 1 proc 2 proc 3 proc 4 proc 5 proc 6 proc 7 proc 8 t = 0 t = 1s, all eight wake together t = 2s 48 offered into a 30/s gate, 18 refused again, rhythm repeats
Every client obeys the documented delay perfectly and that is precisely the problem: identical waits mean identical wake times, so eight processes offer 8 x 6 = 48 calls into a 30-per-second gate at the same instant and 18 are refused again. Randomised jitter on top of the backoff is what breaks the lockstep.

Synchronization is the mechanism to picture. Eight copier processes share one broker allowance, each holding 6 rejected calls. Each receives Retry-After: 1 and obeys it precisely. All eight wake inside the same millisecond and offer 8 x 6 = 48 calls at a 30 per second gate, so 18 are rejected again and all eight lock into the same recurring rhythm. Honoring Retry-After exactly, with no randomization, is what builds that lockstep. The fix changes one edge: instead of every client's arrow landing on the same instant, each lands at a random point inside its own window.

Apply exponential backoff with full jitter to those 48 calls. Spread over a 1 second window they are still 48 per second and still fail. Over 2 seconds they are 24 per second, under the ceiling. Over 4 seconds they are 12 per second, comfortably clear. That is the division of labour described by AWS in its analysis of exponential backoff and jitter: capped backoff alone still leaves "clusters of calls" and merely introduces "times when no client is competing," while jitter spreads the spikes. Backoff lowers the arrival rate below the ceiling; jitter stops every client arriving at once. In that analysis, with 100 contending clients, Full Jitter (a uniform random sleep between zero and the capped exponential backoff) cut the call count by more than half.

Then bound it, because trading is not a batch job. With a 100 ms base and factor 2, the schedule is 100, 200, 400, 800, 1600, 3200 ms, a cumulative 6300 ms across six attempts; under Full Jitter the expected total is half that, 3150 ms. Either is an eternity to leave a follower holding a position the master has closed. So split the policy by call type: state queries get the full curve, order submission gets a hard deadline. Under a 2 second deadline with Full Jitter, expected waits of 50 + 100 + 200 + 400 + 800 = 1550 ms fit five attempts inside the budget, after which the copier must escalate, alerting the trader or flattening the divergent account. Unbounded backoff on an order is a decision to do nothing, dressed up as patience.

What actually buys back allowance?

Removing calls, in a specific order of effectiveness. Count how many accounts fit in a 30 per second allowance under three designs:

  • Baseline, 3 calls per account (submit, confirm, poll state): 3n <= 30, so n = 10 accounts.
  • Batch the state query into one call covering the whole book: 2n + 1 <= 30, so n = 14 accounts, using 2 x 14 + 1 = 29 calls. A 40 percent increase for one API change.
  • Eliminate the state query with a push subscription for fills: 2n <= 30, so n = 15 accounts, a 50 percent increase over baseline.

Streaming beats batching for an exact reason: the batched call still costs one request, the stream costs zero. Batching pays only when it replaces more than one call (12 polls become 1, saving 11), but a subscription replaces all 12 with nothing. That is the strongest practical argument for a push transport over repeated polling, covered in our breakdown of WebSocket, FIX and REST in a trade copier.

Priority budgeting is the next lever, and most copiers get it wrong by accident. Submissions and confirmations are irreversible and time critical; state queries, equity refreshes and historical pulls are recoverable and deferrable. Out of 30 calls per second with 12 followers, reserve 12 x 2 = 24 for submissions, leaving 6 for state, so a full reconciliation sweep of 12 accounts takes 12 / 6 = 2 seconds. That lag is the honest price of never dropping an order: a stale equity reading is recoverable, an unplaced exit is not. Many implementations do the opposite purely because the state poll sits in the same synchronous loop as the submit.

Caching is third, and it carries a real cost. A cached position model is a belief, not a fact: if the broker rejects an order, a margin call liquidates, or a firm risk rule flattens the account, the cache keeps asserting a position that no longer exists. Cache for reads, reconcile on a fixed cadence, and force a full reconcile after any throttling event, precisely because throttling is when the cache is most likely to have missed something. For where these rejections sit in the wider chain, see our end to end copy trading latency budget.

The funded account cost of a missed exit

A throttled copier can leave follower accounts holding a position the master has already closed. That is not a cosmetic delay. It is an unmonitored position held by a machine that believes it already exited, invisible because the interface reports the master's flat state.

A throttled exit is a real drawdown event

Rejected close requests consume trailing drawdown headroom on evaluation and funded accounts exactly like a losing trade, except no trading decision produced the loss. Confirm your firm's exact drawdown figure and how it is calculated, since both vary by firm and by program.

Price it with the stable CME multipliers: the E-mini S&P 500 (ES) is 50 US dollars per index point and the Micro E-mini (MES) is 5 US dollars per index point. The master exits one ES long, accounts 11 and 12 miss the exit, and the market retraces 12 points before backoff lands the close. Per account the divergence is 12 x 50 = 600 US dollars per contract, so across the two stranded accounts it is 1200 US dollars. On micros the same retrace costs 12 x 5 = 60 US dollars per contract, or 120 across both. A request queue produced that loss, and it lands against the same drawdown headroom a losing trade would. On a funded account this also runs into what your firm permits, which we cover in our guide to algo and automated trading rules at prop firms.

When no copier setting fixes it

When calls per order x legs per trade x follower count exceeds the per connection allowance at your trade frequency, no retry policy, backoff curve or caching layer fixes it. The arithmetic does not close. A high frequency, bracket heavy scalper fanned across dozens of accounts on a single REST connection needs an architectural answer: more connections, a batch or FIX path, a streaming feed to remove polling, or fewer accounts per connection. Accepting a slower cadence on non urgent updates is the cheapest of those, and for many books it is enough.

Architecture is also the fair thing to ask a copier vendor about, without accusation. A vendor can truthfully advertise unlimited accounts while the underlying broker truthfully publishes a fixed per connection budget, as cTrader's documentation does on both counts. Reconciling those two facts is the vendor's design problem. Ask directly: how many API calls does one order cost, are accounts spread across connections or stacked on one, is the follower list iterated in a rotated order, and what happens to an account whose submission is rejected.

Rate limits are also blast radius control, not just an obstacle. A copier bug that fires in a loop is capped by the same ceiling that throttles a legitimate burst, and the session drop tier in venue messaging specifications exists because an unconstrained client can damage infrastructure everyone else trades on. The goal is not to defeat the limit. It is to spend a scarce budget on the calls that cannot be undone.

Frequently asked questions

What does a 429 error mean on a broker or platform API?

A 429 means the server refused the request because too many were sent in a given period, which RFC 6585 defines as the rate limiting status code. The response SHOULD explain the condition and MAY carry a Retry-After header telling you how long to wait, but that header is optional, so a client cannot be built on the assumption it will arrive. Some servers skip 429 entirely and drop the connection instead, which is indistinguishable from network loss.

Why does my automation only get throttled during fast markets?

Because rate limits are averages and automation demand is a burst. A copier sends almost nothing between master trades, then emits (calls per order) x (legs) x (follower count) requests inside a fraction of a second, so its peak can be many times its average. The only moments that generate load are the only moments that matter, which is why a system sitting far under its limit all day still fails at the open.

Are API rate limits applied per account or per connection?

Most published limits are per connection, not per account, so adding follower accounts adds demand without adding budget. cTrader's Open API documentation states a maximum of 50 requests per second per connection for non-historical data requests, and separately says one connection can support an unlimited number of accounts of a given type. Confirm the scope with your own provider, since limits and their scoping change.

Why do the same follower accounts always miss the fill?

Because rejection under a rate limit hits whichever requests are processed last, not a random selection. A copier that iterates its follower list in a stable order (account ID, signup date, database row order) always spends the allowance on the same early accounts and always exhausts it before reaching the same tail accounts. If two of your accounts are chronically out of sync and the rest are perfect, check the iteration order before hunting for a broker specific bug.

Does randomizing or rotating account order fix throttling?

No, rotation redistributes failure without creating capacity. Over a full rotation cycle the total number of rejected calls is identical to a fixed order, but the misses spread evenly across the book instead of concentrating on two named accounts. Rotation is still worth doing, because a 100 percent failure rate for two customers is far worse than an occasional miss for everyone, but it does not buy back a single request.

What is exponential backoff with jitter and why do I need both parts?

Exponential backoff waits progressively longer between retries, and jitter randomizes each wait so many clients do not retry in lockstep. They solve different halves of the problem: backoff lowers the arrival rate below the ceiling, while jitter stops every throttled client arriving in the same instant. AWS reported that capped backoff alone still produces clusters of calls, and that Full Jitter cut the call count by more than half with 100 contending clients.

Do rejected requests still count against my rate limit?

It depends entirely on the provider, and the answer decides your correct retry policy. Some APIs count every request that arrives, including the ones they refuse, so an aggressive retry loop spends the next window's allowance on calls that were already rejected; others charge only for requests they actually serve. Find the sentence in your provider's rate limit documentation that says which rule applies before you write the loop, and if the documentation is silent, assume the stricter reading.

How do I find out which rate limiting algorithm my broker uses?

You usually cannot read it from the documentation or the response headers, so infer it from the failure pattern. A fixed window lets an occasional double sized burst through near a boundary then walls off; a sliding window cuts you off at the same request number every time with no boundary luck; a token bucket passes the first burst cleanly and collapses on the third; a queueing limiter rejects nothing and delivers everything late.

How many accounts can I safely run behind one API connection?

Divide the per connection allowance by the number of calls your copier spends per order per account. At an illustrative 30 requests per second and 3 calls per account (submit, confirm, poll state), only 10 accounts fit in a single second of allowance; batching the state query into one call raises that to 14, and replacing polling with a push subscription raises it to 15. Do this arithmetic with your provider's real published limit and your own measured call count.

Can API throttling actually cost money on a funded account?

Yes, because a throttled copier can leave follower accounts holding a position the master has already closed. Using the stable CME multipliers, a 12 point adverse move on one ES contract is 12 x 50 = 600 US dollars per stranded account, and the same move on a Micro E-mini is 12 x 5 = 60 US dollars. That loss consumes real trailing drawdown headroom even though no trading decision produced it, so verify your firm's exact drawdown figure and how it is calculated.