Handling Dynamics 365 API throttling during a show week data load
Dataverse enforces service protection limits per user rather than per organisation: 6,000 requests in a 300 second sliding window per web server, 20 minutes of combined execution time, and 52 concurrent requests. A single integration account running badge scan writes during doors open is therefore the first thing to hit the ceiling.
Doors open at nine. By twenty past, the scanning app is showing a queue indicator that nobody has seen in testing, and the integration writing badge scans into the CRM is returning 429s. The registration desk is fine, because scanning is buffered locally. The problem lands two hours later, when the exhibitor lead dashboards are still showing yesterday's numbers and somebody senior asks why.
Dynamics 365 API throttling has a specific shape, and the shape explains why this happens at 09:20 on the first morning and never in a test. The limits are enforced per user over a five minute sliding window, and a single integration account funnelling every scan write is one user.
Two meters, and only one of them is about speed
Microsoft runs two separate systems and they are easy to confuse.
Service protection limits are about bursts. Microsoft (2026) documents three of them, enforced per user per web server: a cumulative "6,000 within the five-minute sliding window" for the number of requests, "20 minutes (1,200 seconds) within the five-minute sliding window" for combined execution time, and "52 or higher" for concurrent requests. Exceeding any of them returns a 429, and the error text is unambiguous: "Number of requests exceeded the limit of 6000 over time window of 300 seconds."
Entitlement limits are about volume over a day, and they are a licensing construct. Microsoft (2026) allocates 40,000 Power Platform requests per 24 hours for each paid Dynamics 365 Enterprise or Professional licence and 6,000 for Team Member, while application users, non-interactive users, administrative users and the system user draw on a pooled tenant allowance of "500,000 base requests + 5,000 requests accrued per USL" up to a documented maximum of ten million.
The two meters fail at different times for different reasons and the fixes are different. Service protection stops your burst. Entitlement stops your day. During show week you will meet the first one.
Why is a single integration account the bottleneck?
Because the limit is scoped to the authenticated user, and every architecture diagram anyone draws puts one service account in the middle.
Microsoft is explicit that the system evaluates these limits for each user, that each authenticated user has an independent limit, and that the same limits apply to application users as to everybody else. So an organisation with 300 licensed staff has 300 independent service protection budgets and uses precisely one of them for the integration that matters.
There is a second wrinkle that makes capacity planning genuinely awkward. Each web server in the environment enforces the limits independently, most environments have more than one, and the number depends on factors including how many licences you bought. Trial environments get a single web server. So the effective ceiling for your integration account is 6,000 requests per 300 seconds multiplied by an unknown small integer, which means the honest planning position is to design against 6,000 and treat anything above it as luck.
Splitting the load across two or three application users multiplies the budget cleanly and costs you a clean audit trail, since the writes now arrive under whichever service identity happened to pick them up. That is a real trade rather than a free win, and it is worth deciding deliberately.
What does doors open look like in requests per minute?
Measure your own peak, but here is the arithmetic on a plausible one.
A show admits 9,000 attendees between 09:00 and 09:45. That averages 200 scans a minute, which sounds harmless. The busiest five minutes are nothing like the average: suppose 2,600 of those scans land between 09:12 and 09:17, which is 520 a minute.
Now count the writes. A typical scan handler creates a scan record, updates a last-seen field on the contact, and writes a session attendance row. Three operations per scan. Two thousand six hundred scans is 7,800 requests inside a 300 second window, against a ceiling of 6,000 per user per web server. That is 130 per cent of the limit, so the integration starts receiving 429s partway through the busiest five minutes of the show and keeps receiving them until the window slides.
The daily picture is comfortable by comparison. Nine thousand scans at three operations each is 27,000 requests, which is 5.4 per cent of the 500,000 base pooled allowance for non-licensed identities. Nothing about the day is a problem. Five minutes of it is.
That gap between the daily average and the peak window is the whole lesson. Anyone sizing this work from a daily total will conclude there is nothing to do.
Batching fixes one limit and leaves the other alone
Bundle the operations and the request count collapses. A batch can carry up to 1,000 operations, so those 7,800 writes at 100 operations per batch become 78 requests inside the window, comfortably under 6,000.
Two things stop that being the end of the story.
The first is execution time. Microsoft's guidance is to "Avoid large batches", to start at a batch size of 10 and increase concurrency rather than size, and the reason is the second service protection limit: larger batches increase total execution time per request, so a design that escapes the request count ceiling can walk into the 1,200 second combined execution ceiling instead. If each 100 operation batch takes 6 seconds, 78 batches consume 468 seconds of the 1,200 available, which leaves headroom. At 1,000 operations per batch and 55 seconds each, the same work consumes 440 seconds, so there is no gain and considerably less flexibility when something fails.
The second is that batching does nothing for entitlement. Microsoft states directly that batch operations are not a valid strategy to bypass entitlement limits, that the two limit systems are evaluated separately, and that entitlement limits accrue on the underlying operations whether or not they were batched. So the 27,000 operations stay 27,000 operations in licensing terms however you package them.
The clean design, then, is small batches with a bounded worker pool. Keep concurrency well inside 52, keep batch size modest, and let the number of workers rather than the size of the payload be the thing you tune.
What Retry-After is telling you
When you are throttled, the 429 arrives with a Retry-After header carrying a number of seconds, and Microsoft is clear that the duration depends on how demanding the preceding five minutes were and that continuing to send demanding requests extends it.
That last part changes the correct behaviour. A client that retries aggressively after a 429 makes its own next wait longer, so the naive fast retry is actively counterproductive here in a way it is not on every API. Wait the stated duration. Then resume at a lower rate rather than at the rate that caused the problem.
Microsoft also exposes two response headers, x-ms-ratelimit-burst-remaining-xrm-requests and x-ms-ratelimit-time-remaining-xrm-requests, with an instruction attached that is worth quoting because people ignore it: "Don't depend on these values to control how many requests you send. They're intended for debugging purposes." Log them, chart them after the show, and do not build a governor on them.
The general question of how to shape a retry policy that holds up under load, across every vendor in the stack, belongs with a backoff strategy for the busiest registration day. Salesforce meters the same kind of work as a 24 hour org-wide allowance instead, which produces entirely different arithmetic.
What to settle before show week
Four decisions, all cheap in September and expensive on the Tuesday of the show.
Decide how scans are buffered when the CRM refuses them, and for how long. A local queue that holds four hours of scans turns a throttling incident into a delay. No queue turns it into lost data.
Decide the write granularity. Three operations per scan is a choice, and it can often be one: write the scan row during the show and compute the last-seen field and the session attendance rollup afterwards. That change alone would have taken the example above from 7,800 requests to 2,600, which fits.
Decide who owns the service account and whether it is shared with anything else. Anything else on that identity is competing for the same 6,000.
And decide what is allowed to change during the show, because a plug-in deployed on Monday that adds two operations to every contact update will change your peak arithmetic without anybody connecting the two events. That is the argument for freezing every integration for the duration.
Where this stops
Designing against published limits gets you through doors open. Two things sit outside what the arithmetic can promise.
The first is that plug-ins and custom workflow activities do not count toward the request limit, and their execution time does get added to the request that triggered them. So an environment carrying heavy customisation can hit the combined execution time ceiling on a request volume that looks modest, and the cause will be invisible from the integration side. If your Dataverse environment has years of accumulated plug-in logic on the contact entity, ask what fires on create and update before you size anything, and expect the answer to be longer than you hoped.
The second is that the number of web servers is not something you can see or control, and Microsoft says plainly that these limits can change and vary between environments. Any capacity plan built on a specific multiple of 6,000 is built on a number nobody published. Design for the single web server case and treat the extra capacity as margin.
Start this week by measuring your own peak minute. Take last year's scan log, bucket it into five minute windows, find the busiest one, and multiply by the number of Dataverse operations your handler performs per scan. If that product is anywhere near 6,000, you have a design decision to make before the next show rather than a monitoring dashboard to build. The rest of what integrations owe each other sits with this cluster.
Questions people ask about dynamics 365 api throttling
- What are the Dataverse service protection limits?
- Three limits apply per user per web server. The cumulative number of requests is capped at 6,000 within a five minute sliding window, combined execution time at 20 minutes within the same window, and concurrent requests at 52 or higher. Exceeding any of them returns HTTP 429 with a Retry-After header.
- Does batching avoid Dynamics 365 throttling?
- Batching helps with one limit and not the other. Bundling operations into fewer requests keeps you under the request count ceiling, but Microsoft states that entitlement limits accrue on the underlying operations whether or not they are batched. Large batches also push you toward the combined execution time limit instead.
- How many API requests does a Dynamics 365 licence include per day?
- Microsoft allocates 40,000 requests per 24 hours for each paid Dynamics 365 Enterprise or Professional licence, and 6,000 for Team Member. Application users, non-interactive users and system users draw instead on a pooled tenant allowance starting at 500,000 base requests plus 5,000 accrued per user licence.