[object Object]

The asyncoperation table is the canary for Dataverse health. When it fills with hundreds of thousands of pending or in-progress rows, users feel it as slow saves and silent automation delays. Understand what feeds it and you can keep it lean.

The job catalog

Asynchronous jobs include:

  • Async plugin steps (registered with Mode = Asynchronous)
  • Workflows running async
  • Power Automate flow runs that touch Dataverse async
  • System jobs: bulk delete, duplicate detection, import, recalc, search index updates
  • SLA timers
  • Outbound email and server-side sync

All share a single execution surface per environment with throttled concurrency. Microsoft does not publish exact concurrency limits, but practical ceilings are roughly 4 to 16 concurrent jobs depending on environment SKU. Excess jobs queue.

See your queue

Run this Web API query daily:

GET /api/data/v9.2/asyncoperations?$filter=statecode eq 0 or statecode eq 1
&$select=name,statecode,statuscode,createdon,startedon,operationtype
&$orderby=createdon asc&$top=5000

statecode 0 is Ready (queued), statecode 1 is Suspended/Locked/InProgress. A healthy environment shows fewer than 1000 rows total during business hours. Above 5000 means you are bleeding throughput.

Identify the noisemakers

Group the result by operationtype and name. Common offenders:

  • Operationtype 1 (Event) when an async plugin runs millions of times per day
  • Operationtype 10 (Workflow) for legacy workflows triggered on every record update
  • Operationtype 13 (Recalculate) when a rollup or formula column ripples
  • Operationtype 31 (Calculate Rollup Field) on large hierarchies

Each demands different remediation.

Convert async plugins to sync where safe

A common anti-pattern: registering plugins async “for performance.” If the plugin is fast (under 200 ms) and the user does not need the result immediately, sync registration is often cheaper because it skips the queue overhead. Profile before assuming async is faster.

Bulk delete the dead

Asyncoperation completed rows accumulate. The system has a default cleanup job that deletes successful completed operations after 30 days. Confirm it is enabled in admin center. For high-volume environments, add a custom bulk delete that purges rows older than 7 days, scoped to statecode = 3 (Completed) and statuscode = 30 (Succeeded).

Throttle the source

If a flow or integration creates 100,000 records in a minute, async jobs spike. Add throttling at the source:

  • Flow loops: configure concurrency control at 1 or 2
  • External integrations: cap calls per second at the connector or gateway layer
  • Bulk imports: split into smaller files with a 30-second pause between batches

The Dataverse throttling docs describe per-user limits; design within them rather than discovering them at peak.

Watch the SLA

Microsoft’s SLA on async job execution is “best effort, generally within minutes.” When the queue exceeds capacity, that becomes hours. Set a Power Automate flow that alerts when queue length exceeds 2000 for 15 minutes. By the time users complain, you are already an hour behind.

Capacity planning

If your queue keeps overflowing despite tuning, you may need a higher SKU or a separate environment for batch workloads. Move bulk imports and reporting jobs to a dedicated environment connected via integration so the user-facing environment stays responsive.

What to do this week: query the asyncoperation table for the past 7 days, identify your top three operation types by row count, and either throttle the source or move the work synchronous.

[object Object]
Share