Power Automate 429 Throttling at Scale: When to Redesign Instead of Adding Retries
A technical guide for teams whose recurring, business critical flows fail with 429 or 401 errors or miss their deadline: which limit you are hitting, the levers in order, resumable worker patterns and when the work belongs in code.
When a Power Automate flow hits 429 Too Many Requests and must finish before a deadline, more retries and longer delays are the wrong answer: they make the run longer, not smaller. Reduce the work in this order. First, fewer API calls per record: select fewer columns, expand related rows and stop per item Get a row calls. Second, batching. Third, change tracking, so each run processes only what changed. Fourth, controlled concurrency. If the volume still outgrows one flow, split it into an initiator and resumable workers over a job table, or move the heavy step to Azure Functions with a queue or a scheduled job against the Dataverse Web API. Stabilise the most critical process first.
Why are retries and delays the wrong fix for 429 errors under a deadline?
A 429 is the platform telling a caller to slow down. The Dataverse connector and most Microsoft connectors already retry throttled calls and honour the Retry-After interval, so wrapping actions in extra retry loops or Delay actions does not create capacity. It spends the same budget more slowly and pushes the finish time past the moment finance, payroll or the warehouse needs the output. Retries and pagination also count as actions against the flow's Power Platform request allowance, so a retry storm consumes the budget it is waiting for.
Microsoft also documents that a cloud flow which is consistently throttled can be turned off after a sustained period, so a weekly process that limps through on retries is one busy month away from not running at all. Check the current Power Automate limits page for the exact rule. Correct retry handling still matters, and for a one-off migration it is most of the answer, which is why our Dataverse bulk import strategy treats throttling as flow control. A recurring process with a deadline needs the opposite emphasis: make each run do less work.
Which limits is a throttled flow actually hitting?
"429" covers several different ceilings, and the fix depends on which one you hit. Read the raw output of the failed action before changing anything. Our Power Automate support guide walks through the payloads symptom by symptom, so the table below only names the limits and what each one means for design. The values Microsoft publishes change, so confirm current figures in the Dataverse API limits, Power Automate limits and connector reference documentation.
| Limit | Counted against | How it shows up | What it means for design |
|---|---|---|---|
| Dataverse service protection limits | Each user or application identity, per web server, over a sliding window of a few minutes: number of requests, combined execution time and concurrent requests. | HTTP 429 with a Retry-After header and a Dataverse error code in the body that names which of the three was exceeded. | Too many small calls, calls that are individually expensive and too many calls at once are three different problems. Every flow sharing one connection identity shares one budget. |
| Power Platform request limits | Background flows use the owner of the flow, or the flow itself when it has a Process licence, over a 24 hour sliding window, plus a shorter window limit. | Flow actions slow down rather than fail. Runs take much longer than they used to without an obvious error. | Every action counts, including Compose, variables, conditions, retries and pagination. Fewer actions per record matter as much as fewer Dataverse calls. |
| Connector throttling | The connection, for a number of calls per time window defined per connector. | HTTP 429, often with a plain "Rate limit is exceeded" message and no Dataverse error code. | Many flows on one connection concentrate load. Split connections by workload and read the throttling limits on the connector reference page. |
| Target service throttling, such as SharePoint Online | The service behind the connector, based on how expensive the requests are. | HTTP 429 or 503 from the service, and on large lists, threshold errors that are not 429 at all. | Unindexed filters on large lists make every call expensive. The fix is the query shape, not the retry policy. |
How do you cut the number of API calls each record costs?
Start here, because it is the cheapest change and it helps against every limit in the table. Open the run history of a slow run, count the actions executed per record processed, and write the number down. Most flows we review do several times more work per record than the process needs, and the reduction rarely changes what the flow does. Then reduce how many requests reach the target at all.
- Select only the columns you use on List rows and on the trigger. Wide rows cost execution time on the server and payload size in the flow.
- Filter on the server. Move conditions from Condition actions inside the loop into the Filter rows query, so rows that will be skipped are never fetched.
- Expand related rows in the same query instead of calling Get a row for the parent or lookup of every item. A Get a row inside an Apply to each is one of the most common multipliers we find.
- Build lookup tables once. Fetch reference data such as product codes or owners once per run, then look values up in memory with Filter array or Select rather than querying per record.
- Compose in memory. Shape the payload with Select and Compose and write once, instead of updating the same row several times as values are worked out. Those actions still count as Power Platform requests, but they do not touch the Dataverse or connector limits.
- Skip no-op writes. Compare the incoming values with what is already stored and update only when something changed. Updates that change nothing still run plugins, flows and auditing.
- Turn pagination on deliberately, with a threshold you chose, and check for an item count that equals the threshold. Silent truncation is covered in the support guide linked above.
How does batching reduce throttling in Power Automate?
Batching sends several operations in one request, which cuts round trips and helps against request count and connector call limits. It does not cut the work: Microsoft documents that Dataverse execution time limits still apply to the combined operations, and that batching does not reduce the request entitlement counted against a licence. Treat it as a way to spend the budget efficiently, not as a way around it.
What is available from a flow depends on the connector and changes over time, so check the current connector reference before you design around a specific action. The options we use are below.
| Option | Where it runs | Use it for | Watch for |
|---|---|---|---|
| Changeset request in the Dataverse connector | Inside the flow | A small group of related creates and updates that must succeed or fail together. | It is a transaction, so one failure rolls back the group. Keep the group small and meaningful. |
| Dataverse Web API $batch | An HTTP request from a flow, a custom connector or code | Many independent operations in one round trip. | Execution time for the whole batch still counts. Larger batches move you from request limits to execution time limits. |
| ExecuteMultiple | Code using the Dataverse SDK | Grouping requests from a .NET job to reduce network overhead. | The server still processes the requests one after another, so the gain is round trips, not throughput. |
| CreateMultiple, UpdateMultiple, UpsertMultiple | Code, or a Dataverse custom API a flow calls | High volume writes to one table, where the bulk messages are designed for throughput. | Not every connector version exposes them directly. Plugins registered on single create or update still need checking. See the bulk import guide for the mechanics. |
| SharePoint REST $batch | Send an HTTP request to SharePoint | Many item updates on one list. | Build the multipart body carefully and log per operation results, because a batch can partly succeed. |
How do you process only the records that changed since the last run?
A weekly flow that reprocesses the whole table every time will outgrow any limit eventually, because its cost grows with the size of the table rather than with the amount of change. Process deltas instead, and the cost follows the business activity.
Dataverse change tracking is the first choice where the table supports it. Enable Track changes on the table, request changes with the Web API change tracking preference, store the delta token the response returns, and on the next run ask only for rows created, updated or deleted since that token. Deleted rows arrive too, which a modified date filter cannot give you. Tokens expire if they are not used for long enough, so plan a full reconciliation as the fallback.
Where change tracking is not available, use a watermark: store the modifiedon value of the last processed row in a configuration table, query rows modified after it, overlap the window slightly to cover clock and commit ordering, and make the write idempotent with an alternate key so the overlap cannot create duplicates. Automated flows triggered on change should use trigger conditions and filtering columns so they fire only for the columns that matter.
How much concurrency should a throttled flow use?
Less than people expect, and set on purpose. Concurrency helps when calls are quick and the identity has budget left. It hurts when many parallel branches write through one identity, because they reach the concurrent request limit or the execution time limit sooner and every branch then waits. The flow that fails is often not the flow that spent the budget.
- Apply to each runs sequentially unless you enable concurrency, and the documented maximum degree of parallelism is limited. Raise it in small steps and measure the throttled action count, not only the duration.
- Trigger concurrency control limits how many runs of a flow execute at once and queues the rest. Microsoft documents that once it is turned on it cannot be turned off without removing and re-adding the trigger, so decide before production.
- Keep writes that depend on order sequential. Parallel updates to the same rows cause conflicts that look like random failures.
- Count the identities, not the flows. Five flows on one service connection share one Dataverse budget. Give the heavy batch its own identity so it cannot starve the flows and users that run during the day, which is the subject of our guide to protecting interactive users from Dataverse API limits.
- Separate high volume work from approvals and notifications onto different connections, so a slow batch does not delay a person waiting for an approval.
How do you fix 429 Too Many Requests on a large SharePoint list?
A large SharePoint list is usually throttled because each call is expensive, not because there are too many calls. Filtering on columns that are not indexed forces the service to scan the list, and once a list passes the list view threshold, queries that are not backed by an index can fail with a threshold error instead of a 429. Retrying an expensive query does not make it cheaper.
- Index the columns the flow filters and sorts on, in list settings, before the list grows. Adding an index to a very large list can itself be restricted, so do it early.
- Put the filter in the Get items Filter Query on an indexed column, use Top Count and pagination deliberately, and limit the columns returned with a view or a select in the HTTP request.
- Stop calling Get item per item inside a loop when Get items already returned the fields you need.
- Process only what changed. Filter on the Modified column with an index, or use the change based actions for lists and libraries, rather than reading the whole list on every run.
- Group updates with SharePoint REST $batch through Send an HTTP request to SharePoint, and spread heavy flows across connections owned by different service identities where that fits your governance.
- If the list is effectively a database with hundreds of thousands of rows and relational queries, it probably belongs in Dataverse or SQL, and that is a design decision rather than a tuning task.
How do initiator and worker flows make a long-running process resumable?
A single flow that loops over every record keeps all of its progress in the run. If it is cancelled, times out, is throttled into the ground or is turned off, nobody can say which records were done, and the only safe option is to start again. Move the state out of the run and into a job table in Dataverse, and the process can stop and resume at any point.
The initiator flow runs on the schedule. It works out what needs doing, preferably from change tracking, and writes one row per unit of work to the job table with a status of Pending, a batch identifier and a business key. It does no processing itself. Worker flows, triggered on a schedule or by the initiator, claim a small number of Pending rows, process them, and set each to Done or Failed with the error recorded. Because every row carries its own status, a restart picks up where the last worker stopped.
Claiming needs care, or two workers will process the same row. Read the row with its ETag, then update the status to Claimed with an If-Match condition on that ETag through the Dataverse Web API. If another worker got there first, the ETag no longer matches, the update fails with a precondition error, and the worker moves on. Not every connector action exposes If-Match, so use an HTTP request, a custom connector or a small custom API for the claim. Add a claimed-at time so a sweep can release rows claimed by a worker that died, and make the final write idempotent with an alternate key so a replay cannot duplicate a record.
Keep individual runs short. Microsoft documents a maximum run duration, and Do until loops carry their own count and timeout defaults, but the practical reason is recovery: a worker that handles a bounded slice and ends is easy to restart, alert on and scale. Put a kill switch row in a configuration table that every worker reads at the start, so the process can be paused without turning flows off or losing queued work. The same pattern for integrations, with an outbox and backoff, is set out in our point-to-point integration rationalisation guide.
| Job table column | Purpose |
|---|---|
| Status (Pending, Claimed, Done, Failed, Parked) | Tells any worker what is left and lets the run resume after a restart. |
| Business key and batch identifier | Ties the work item to the source record and to one scheduled run, for idempotent writes and reporting. |
| Claimed by and claimed at | Shows which worker holds the row and lets a sweep release stale claims. |
| Attempt count and last error | Stops a poison record from being retried forever; after a set number of attempts it is parked for a person. |
| Completed at | Proves the deadline was met and feeds the reconciliation count at the end of the run. |
When does the work belong in Azure Functions or a scheduled Web API job instead of a flow?
Power Automate is a good orchestrator and a poor bulk processor. Once the redesign above still leaves a process near the limits, keep the flow for what it does well, the schedule, the approvals, the notifications and the business visible status, and move the heavy step into code. The flow then starts the job and reports the outcome.
Is Power Automate still the right platform at that point? Usually yes, for the orchestration. We recommend the right solution - whether that's Microsoft Dynamics 365, Power Platform, or a custom-built CRM. Some businesses need the Microsoft ecosystem. Others need full control without licensing. We deliver both. Where the processing sits entirely outside the Microsoft estate and licensing is the obstacle rather than the design, a custom-built CRM or back office application on React, Node.js, PostgreSQL or .NET is the alternative we build.
| Signal | Stay in Power Automate | Move the heavy step to code |
|---|---|---|
| Volume per run | Hundreds to low thousands of records after delta processing. | Volume that still needs many workers and constant throttle management after the levers above. |
| Shape of the work | Business steps, approvals, notifications, a few writes per record. | Transformation, matching and bulk writes that are mostly compute. |
| Control over throttling | Connector retries are enough. | You need one shared rate limiter honouring Retry-After across all workers, bulk messages and the recommended degree of parallelism. |
| Recovery | A job table and worker flows give enough restartability. | You need a durable queue with dead lettering and exact replay, such as Azure Service Bus or Storage queues with Azure Functions. |
| Ownership | Makers and a support team maintain it. | A developer team owns code, tests and deployment pipelines. |
Should high volume processing stay on the Microsoft platform or run on a system you own?
Can afford licensing and want the Microsoft ecosystem
Dynamics 365
Microsoft 365, Teams and Outlook integration, a mature partner ecosystem, Copilot, and apps for sales, service and field operations that are configured rather than built.
Need full control and zero licensing
Custom CRM
A CRM built on React, Node.js, PostgreSQL or .NET that you own outright: your data model, your hosting, no per-user subscription, and features shaped exactly to your process.
Not sure which fits
We help you decide
A short discovery weighs licensing budget, process complexity, integrations and long-term ownership, then recommends one path. We deliver both, so the recommendation has no reason to lean.
Is an intermittent 401 Unauthorized the same problem as a 429?
No, and treating them as one wastes days. A 429 means the call was authenticated and the platform refused it for volume. A 401 means the platform did not accept the credential at all, so retrying or slowing down will not help. When a long run shows both, fix the 401 first, because failed authentication makes the throttling picture impossible to read.
Intermittent 401s in flows usually come from the identity behind the connection: the person who authorised it left or was disabled, changed a password or re-registered MFA so the refresh token was revoked, fell under a new conditional access policy, or a service principal secret or certificate expired. Runs that start before the event succeed and runs after it fail, which is why it looks random. Connection ownership, dedicated service accounts, service principals and connection references are covered on our Power Automate consulting service page, including what to do when the owner has already left.
| 401 Unauthorized | 429 Too Many Requests | |
|---|---|---|
| What the platform is saying | The credential is missing, expired or no longer valid. | The credential is fine; this identity or connection is sending too much. |
| Typical pattern | Every flow using one connection fails from a point in time, often across unrelated processes. | Failures cluster at peak volume and ease when load drops. |
| Does waiting help | No. | Yes, for the Retry-After interval, but it does not meet a deadline. |
| Durable fix | Service identity, connection references, secret rotation owned by someone. | Fewer calls, batching, deltas, controlled concurrency, separate identities, workers. |
How do you stage the redesign so the critical processes stabilise first?
Do not redesign the whole estate at once. Rank the throttled processes by what it costs the business when they miss their window, stabilise the top one, prove it through a full business cycle including a month end, then move on. Senior consultants and full-stack developers at Solzet run this as a defined engagement, remotely from Yerevan, Armenia, with 8+ years of Dynamics 365 Customer Engagement and Power Platform work, directly or white-label for Microsoft partners. The wider flow engineering sits in our Power Automate consulting and Power Platform development services.
- Measure first: actions per record, throttled action counts, run duration against the deadline, and which identities and connections each flow uses.
- Separate 401 identity failures from 429 volume failures and fix identity first.
- Apply the cheap levers to the critical process: columns, filters, no per item Get a row, no-op writes skipped.
- Give the batch its own identity and connection so it stops competing with daytime flows and users.
- Introduce deltas, then the job table with initiator and worker flows and a kill switch, run in parallel with the old flow and compared record by record before cutover.
- Move the heavy step to Azure Functions or a scheduled Web API job only where the measurements still say so.
- Add a reconciliation at the end of each run that compares processed counts with the source, and alert on it, then repeat for the next process.
What do people ask us?
How do I fix 429 Too Many Requests in Power Automate?
First read the failed action's raw output to see which limit you hit: a Dataverse service protection limit, a connector limit or a target service such as SharePoint. Then reduce the work rather than adding retries: select fewer columns, filter on the server, remove per item Get a row calls, batch writes, process only changed records and lower concurrency on loops that write. If it still does not fit, split the process into worker flows or move the heavy step to code.
Should I add retry policies and delays to a throttled Power Automate flow?
Keep the connector's default retry handling, which already honours Retry-After, but do not add retry loops or Delay actions as the fix. They spend the same limited budget more slowly, retries count as actions against the flow's request allowance, and a run with a deadline finishes later. Microsoft also documents that consistently throttled flows can be turned off. Reduce calls per record, batch, process deltas and control concurrency instead.
How do I make a long-running Power Automate process resumable?
Move the progress out of the flow run into a Dataverse job table with one row per work item and a status. An initiator flow creates Pending rows; worker flows claim a few rows at a time, process them and mark each Done or Failed. Claim rows with an ETag and If-Match through the Web API so two workers cannot take the same row, release stale claims on a sweep, and make writes idempotent with an alternate key.
Why does my Power Automate flow get 429 errors on a large SharePoint list?
Usually because each query is expensive. Filtering or sorting on columns that are not indexed makes SharePoint scan the list, and above the list view threshold such queries can fail outright. Index the filtered columns, put the filter in Get items on an indexed column, limit columns and page deliberately, stop calling Get item inside loops, process only items modified since the last run, and group updates with SharePoint REST batch requests.
Why do I get intermittent 401 Unauthorized and 429 errors from Dataverse in the same flow?
They are two separate problems. The 401 means the connection's credential stopped being valid, typically because its owner left, changed a password or MFA, fell under a new conditional access policy, or a service principal secret expired. The 429 means an authenticated identity sent too much. Fix the identity first with a service account or service principal behind connection references, then address volume with fewer calls, batching, deltas and controlled concurrency.
Does Dataverse change tracking work with Power Automate?
Yes, with some design. Enable Track changes on the table, then request changes through the Dataverse Web API with the change tracking preference, usually from an HTTP request or custom connector, and store the delta token in a configuration table for the next run. Where that is not practical, use a modifiedon watermark with a small overlap and idempotent upserts. Either way the flow processes only rows that changed rather than the whole table.
When should Power Automate processing move to Azure Functions?
When a process still runs near the limits after cutting calls, batching, processing deltas and splitting into worker flows, or when the work is mostly bulk transformation and writes rather than business steps. Keep the flow as the orchestrator for the schedule, approvals, notifications and status, and move the heavy step to Azure Functions with a queue, or to a scheduled job against the Dataverse Web API with one shared rate limiter.
Where should you go next?
Power Automate consulting
Cloud flows, desktop RPA, flow takeover, service accounts and connection references for production estates.
Dataverse bulk import strategy
One-off loads of millions of rows: the published limits, bulk messages, disabling per row logic and throttling as flow control.
Protecting interactive users from Dataverse API limits
Why a batch identity can starve a portal or daytime users, and how to separate workloads and monitor consumption.
Power Automate and Power Platform support
Reading 429, 403 and trigger failures symptom by symptom, silent pagination truncation and proactive monitoring.
Point-to-point integration rationalisation
Kill switches, smoke tests, outbox tables with backoff and idempotent consumers for integrations that keep failing.
Custom CRM Development
CRM and back office systems on React, Node.js, PostgreSQL and .NET for organizations that need full control without Microsoft licensing.
Which solution is right for your business?
Tell us what you need. A senior consultant replies within one business day with a recommendation - Dynamics 365, Power Platform, or a custom-built CRM - not a sales script.