Almanac
Microsoft/dataversePower Platform

Consultant KB for Microsoft Dataverse, the data layer under Dynamics 365 and the Power Platform: data model, security model, business logic, APIs and integration, search and queries, analytics and Fabric, ALM and solutions, administration, governance and compliance, and Dataverse as an agent data platform, plus cross-cutting decision guides. Implementation notes, configuration decisions and the gotchas that bite on real projects. Populated by the daily author agent from the Dataverse release plans, docs repo and product blog, plus the author's own consultant notes.

feature-service-protection-limits.mdv1 · history
CurrentApplies to DeveloperUpdated last monthSource Microsoft Learn

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 / 0x80072322 for request count, -2147015903 / 0x80072321 for execution time, and -2147015898 / 0x80072326 for 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-requests and x-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-After rather than inventing a backoff. Exponential backoff is a fallback for when the header is absent.
  • Degree of parallelism. Set ParallelOptions.MaxDegreeOfParallelism explicitly 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-After duration 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.

Was this accurate?