TL;DR
The per-user request ceiling everyone quotes for Dynamics 365 is still published, and Microsoft's own banner says the limits behind it are disabled on all environments with the option to enable them removed. Here is what the service protection API limits page says today, which limit type actually returns a throttling response, the priority control you can set, and why an exemption moves the meter rather than removing it.
Which Dynamics 365 service protection limits are actually enforced?
The resource-based ones, on the finance and operations endpoints — and a different answer on the Dataverse side, which section five covers. The per-user ceiling that keeps turning up in integration design reviews is still published on Microsoft's page, and Microsoft's own banner at the top of that same page says the limits behind it are disabled.
Everything below is the page text behind that.
The banner, in full, because the summary is where this goes wrong
The Important box that opens Service protection API limits, quoted rather than paraphrased:
Finance and operations apps environments version 10.0.19 and later enable resource-based service protection API limits. Resource-based API limits continue to protect the finance and operations service from unexpected spikes in usage that threaten the availability and performance of the service. User-based service protection API limits, as described in this article, were previously announced as mandatory in all finance and operations apps environments in version 10.0.33 as an additional layer of service protection. As of March 31, 2023, user-based service protection API limits are no longer being implemented in finance and operations apps environments. The limits are currently optional and can be enabled or disabled by using the User-based service protection API limits feature in Feature management. In version 10.0.35, the API limits are disabled by default but can still be optionally enabled for environments. In version 10.0.36, the limits are disabled on all environments, and the option to enable the limits is removed.
Read the last sentence twice. Not disabled by default — disabled on all environments, with the enable option removed. Resource-based limits [GA] since 10.0.19; user-based limits [DEPR], and that label is ours, drawn from the banner rather than from Microsoft's vocabulary, because Microsoft does not use the word "deprecated" on that page.
The numbers everyone quotes, and where their status lives
The page still publishes the user-based table, introduced as "the default user-based service protection API limits that apply per user, per application ID, per web server".
- Number of requests — 6,000 within the five-minute sliding window
- Execution time — 20 minutes (1,200 seconds) within the five-minute sliding window
- Number of concurrent requests — 52
The error strings are published too, which is why the figures travel: "Number of requests exceeded the limit of 6000 over the time window of 300 seconds."
So the numbers are real, the mechanism description is real, and the status sits in the box above them. Both the limits page and the Throttling prioritization page still describe the two types working together.
The Throttling prioritization page opens with "Resource-based limits for service protection APIs work together with the user-based limits for service protection APIs as protective settings".
The limits page carries the same point inside its resource-based section — "Resource-based service protection API limits work together with user-based limits as protective settings that help prevent the over-utilization of resources".
Those sections describe the architecture; the Important box describes what is switched on. Quoting the table without the banner is the tell.
What actually returns a throttling response
On the finance and operations endpoints, the resource-based limits. Microsoft describes them by what they measure rather than by a number: they "enforce thresholds based on environment resource utilization", throttling "when the aggregate consumption of web server resources reaches levels that threaten service performance and availability".
The thresholds themselves are "based on percentage utilization of resources such as memory and CPU on the environment web servers".
The response is HTTP 429, with a message specific to this limit:
This request could not be processed at this time due to system experiencing high resource utilization.
That is Microsoft's string as published. Its own reading of the error is what an architect needs:
This error doesn't necessarily indicate that any single user or integration is causing the issue. Instead, it indicates that the cumulative utilization of web server resources across all service integrations has exceeded a threshold that threatens the performance and availability of the service.
Your optimizer can be throttled because of somebody else's nightly job. No per-user budget expresses that.
Retry operations supplies the recovery contract: the 429 "response header includes a Retry-After interval that indicates the number of seconds that the user must wait", that interval "depends on the nature of the operations that the preceding five-minute period contains", and, the part most retry code misses, "Retry requests don't receive higher priority than new requests."
One scoping fact: the limits "are available only for the finance and operations apps online service, including production and sandbox environments. They aren't available for on-premises or development environments."
On the limits page itself the user-based limits get a table of figures and the resource-based thresholds get prose. There is no published threshold number for them on that page, which is why you tune against Retry-After rather than against a budget. The published numbers for this path size the pattern, not the request.
The one control you can actually set
Priorities. Throttling prioritization [GA], marked Platform update 37 on the page, covers "priority-based throttling for Open Data Protocol (OData) and custom service-based integrations".
It carries a Note that decides whether it is worth your time: "Throttling priority mapping doesn't apply to user-based service protection API limits. The priority mapping is specific to resource-based service protection API limits."
- Where it lives — "In finance and operations apps, go to System administration > Setup > Throttling priority mapping." The prose on the same page calls it the "Throttling Priority Mapping page"; both casings are Microsoft's
- Who can do it — "You must be assigned the System administrator or Integration priority manager role to complete the setup" — those two Security Roles, named exactly
- What you key on — "In the Authentication type field, select User or Microsoft Entra application based on your integration scenario"
- The application case — "in the Client ID field, select the application that you registered in the Microsoft Entra application"
- The levels — "Three priority levels are available: Low, Medium, and High. Each priority level assigns different throttling thresholds for the selected application or user"
So it is relative, not a quota: "Setting appropriate priorities ensures that low-priority integrations throttle before high-priority integrations." And it keys on the registration: "If you set the priority mapping for an application, you apply the priority mapping to any API request from the selected Microsoft Entra application ID."
The exemption trap: you moved the meter, you did not remove it
Microsoft lists nine services "currently exempt" — Document Routing Agent, the Warehouse Management mobile app, Retail Server API, Office Integration, Data Import/Export Framework (DIXF), Recurring integrations, Data Integrator, the finance and operations apps Connector, and Power Platform virtual tables.
Keep the "currently": the page adds that "the documentation is updated when exemptions are removed for these services." DIXF is the exemption a bulk load meets, where the constraint is batch capacity, not a request budget.
Now read the virtual-tables carve-out in full, because the second half is the half that gets dropped:
The exemption for virtual tables applies only when the Microsoft Power Platform integration with Finance and Operations apps is enabled. The service protection API limits apply to virtual tables if the integration isn't enabled for the Finance and Operations apps environment. When the integration is enabled, the exemption applies only to the Finance and Operations apps API endpoints that the virtual entity plugin invokes. The Finance and Operations apps service doesn't throttle the request. However, because the request is made through the Microsoft Dataverse API, Service protection API limits might still apply to the request.
"Might still apply" is Microsoft's hedge and it stays. The request is not unmetered; it is on a different meter — whose headline figures look almost identical, which is what makes this expensive to discover late.
- Status of the user-based limits — Finance and Operations: "disabled on all environments" in 10.0.36, and "the option to enable the limits is removed" · Dataverse: Live: "Dataverse has enforced Service Protection API limits since 2018"
- Scope of the request count — Finance and Operations: "per user, per application ID, per web server" · Dataverse: "per web server", evaluated "for each user"
- Concurrent requests — Finance and Operations: 52 · Dataverse: "52 or higher" — "might be higher than 52 in some cases"
- Batch ceiling — Finance and Operations: "batch size is limited to 5,000 operations" · Dataverse: "up to 1,000 operations"
Two more on the Dataverse side change the arithmetic. Plug-in traffic is carved out — "Service protection limits don't apply to data operations that originate from plug-ins and custom workflow activities" — though "the extra computation time that these operations contribute is added to the initial request that triggered them".
And a second, independent meter exists: "Service protection API limits and entitlement limits are evaluated separately."
So the per-user ceiling you stopped designing against on the Finance and Operations side is the one Dataverse has enforced since 2018 — which is why Microsoft says its limits might still apply to a request that crossed over.
How we register integrations, and why (T2 — ours)
Our design position, not Microsoft's recommendation.
We give every integration flow its own Microsoft Entra app registration — order intake, the nightly history pull and the write-back each get their own.
It costs minutes in Entra and buys the only lever the Throttling prioritization page publishes: priority mapping keys on the client ID, so flows sharing a registration and a service account cannot be prioritised apart — the only other key Microsoft publishes is the user ID. One registration for everything settles the High/Medium/Low question before anyone has asked it.
Note where that argument comes from. The limits page describes a throttling key combining user and application client ID — but that description sits inside the user-based section, so it is not the support for this.
The support is the priority-mapping page: a mapping applies "to any API request from the selected Microsoft Entra application ID", which is resource-based and current.
Where we draw the line
We do not size a write path against the per-user request ceiling; the banner says why. We do not treat an exemption as an absence of limits, because the Dataverse page publishes its own. And we do not let an Optimizer's bulk read and its decision write-back share a client ID — that is the flow you most want to protect sharing a priority with the one you least mind losing.
Dynamics stays the system of record. The optimization is the system of intelligence, and it queues behind the ERP's own users by priority mapping. We don't touch your ERP core — we surround it with intelligence.
What to do this week
- Check your environment version against the banner on Service protection API limits. On 10.0.36 or later, delete the per-user request ceiling from your design document.
- Open System administration > Setup > Throttling priority mapping and count the rows. An empty page means every integration shares one priority.
- Count your Microsoft Entra app registrations against your integration flows. If the first number is smaller, per-flow prioritisation is not yet open to you.
- Read your 429 handler. If it sleeps a fixed number of seconds instead of reading
Retry-After, it is guessing at an interval Microsoft says varies.
About Cognilium Cognilium is the AI optimization layer for Dynamics 365 — complementary apps that optimize the pricing, inventory, warehouse and planning decisions your ERP manages but can't optimize. Built on Power Platform, Dataverse and Azure. https://cognilium.ai · https://www.linkedin.com/company/37180269/
Open Throttling priority mapping and count the rows. If it is empty, book a fifteen-minute call and we will walk your integration flows and their priorities with you, live — no deck. https://cognilium.ai
Sources
- Service protection API limits (finance and operations apps)
- Throttling prioritization
- Retry operations
- Maximize API throughput
- Service protection API limits (Microsoft Dataverse)
Sources
Share this article
Muhammad Mudassir
Founder & CEO, Cognilium AI
Muhammad Mudassir
Founder & CEO, Cognilium AI
Mudassir Marwat's argument is that ERP systems record decisions they never optimise.
