What it does
Per-user throttling that protects the shared platform from clients making extraordinary demands. Exceed a limit and the Web API returns HTTP 429 with a Retry-After header; the SDK for .NET returns an OrganizationServiceFault with a Retry-After TimeSpan in its ErrorDetails.
Key facts
- Three facets are enforced, per user, per web server. Two use a five-minute (300 second) sliding window: 6,000 requests, and 20 minutes (1,200,000 ms) of combined execution time. The third, concurrent requests, is 52 or higher and returns an error immediately rather than on a window.
- Microsoft states plainly that these are defaults, that they can change, and that they vary between environments. Don't hard-code them.
- Each web server enforces independently. Most environments have several; trial environments get one. The number depends on factors Microsoft manages, one of which is how many user licences you've bought.
- Error codes are
-2147015902/0x80072322for request count,-2147015903/0x80072321for execution time, and-2147015898/0x80072326for concurrency. - Operations originating inside plug-ins and custom workflow activities don't count, because the sandbox doesn't use the public endpoints. Their compute time does accrue to the triggering request.
- These are separate from entitlement limits. Batching doesn't dodge entitlement limits — those accrue per CRUD operation whether batched or not.
- Dataverse search uses a different API (
api/search) with its own rules, throttled at one request per second per user. - Two response headers,
x-ms-ratelimit-burst-remaining-xrm-requestsandx-ms-ratelimit-time-remaining-xrm-requests, expose remaining headroom. Microsoft says these are for debugging and shouldn't be used to control your send rate. - The limits apply identically to application users. There's no special treatment for service principals.
When to use / skip
There's nothing to switch on — this is a constraint to design around. Every integration that writes more than a trickle needs a retry strategy, and every ETL tool needs to be configured with one. The design question is whether you're building a nightly bulk job that will spend its life fighting these limits, or a continuous near-real-time flow that never approaches them. Microsoft's own recommendation is the latter: move away from large periodic jobs, because the whole point of the limits is to smooth out exactly that shape of load.
Configuration decisions
- Retry policy: honour
Retry-Afterrather than inventing a backoff. Exponential backoff is a fallback for when the header is absent. - Degree of parallelism. Set
ParallelOptions.MaxDegreeOfParallelismexplicitly rather than accepting the default, which is derived from the cores on your machine and has nothing to do with the server. - Batch size, if any. Microsoft's guidance is that most scenarios are fastest with single requests and high parallelism; if you batch, start around 10 and increase.
- Whether the load can be spread across more than one application user, which multiplies the per-user budget — and whether that's an acceptable audit trade-off.
- What the client application does when throttled: a portal should disable the UI and say the server is busy, not surface the error text.
Gotchas
- Because the limits are evaluated over a window, you can exceed the request count and execution time before throttling kicks in, then get a bill for it. Concurrency is the exception and errors immediately.
- Keep pushing while throttled and the
Retry-Afterduration extends. Aggressive retry makes the outage longer, not shorter. - Batching to dodge the request count pushes you straight into the execution time limit, which is exactly what that facet exists to counter. It's not a loophole.
- Removing the affinity cookie moves you between web servers and resets the ratelimit headers, so anything reading those values for control logic gets nonsense.
- Portals are the classic surprise. Anonymous traffic funnels through one service principal, so the whole site's load lands on a single user's budget.
- Clients written before 2018 predate these limits entirely and often have no 429 handling at all. Assume any inherited integration is in this category until proven otherwise.
Consultant notes
- Ask the ETL vendor directly whether their product honours
Retry-After, and get the answer in writing. "It has retry" is not the same answer. - The right architecture conversation is nightly-batch versus continuous-sync, and it's much easier to have before the integration is built. Frame the limits as the reason, not as an obstacle.
- Don't let anyone design against 6,000 requests as a fixed budget. It's a per-server default in a document that says it can change.
- If a client's data migration is going to take three days at a sustainable rate, say so during planning. Discovering it during the migration weekend is how cutovers slip.
Worth another look before any large data migration, and whenever a client changes ETL tooling.