Skip to content

Should Save Wait? Synchronous vs Asynchronous Plug-ins Explained

A user clicks Save. The spinner keeps spinning. Somewhere behind the scenes, a plug-in is validating data, updating records, and waiting for an external system.

The real design question is simple: Which of those tasks has earned the right to make the user wait?

In Dynamics 365 and Microsoft Dataverse, choosing synchronous or asynchronous execution starts with the business requirement—not with which option sounds faster.

The difference in one minute

Synchronous: the operation waits for the plug-in to finish. Use it when the result is required before the caller can treat the operation as successful.

Asynchronous: execution is queued after the record operation completes. Use it when work can happen later and the business can tolerate a gap between saving the record and finishing the follow-up action.

Think of ordering at a café: confirming that your order is valid belongs at the counter. Sending a feedback request can happen later. Both matter; only one should hold up the queue.

Ask this before choosing

“If this work fails, should the original save fail too?”

If yes, consider synchronous logic and the correct transaction stage. If no, asynchronous processing is often a better fit. Then ask whether the user needs the result immediately, how much delay is acceptable, and who will handle a failure.

Your quick decision table

Requirement Choose Why
Reject an invalid request before saving Synchronous The caller needs an immediate decision.
Set a value on the record being saved Synchronous PreOperation Change the incoming Target before the database operation.
Create a related record that must succeed or fail with the original save Synchronous, within the transaction The changes need to commit together.
Send a notification after a successful save Asynchronous Delivery does not need to hold up the save.
Synchronize data with an external service when delay is acceptable Asynchronous integration Separate the save from remote availability; design retries and recovery.
Run very long or heavy processing External worker or service Moving a plug-in to async does not make its execution unlimited.

PostOperation is not the same as asynchronous

Stage and execution mode answer different questions. The stage determines where the plug-in runs relative to the main database operation. The mode determines whether the caller waits.

Synchronous PostOperation still runs inside the transaction. A failure there can roll back the original operation. Asynchronous plug-in steps are registered in PostOperation and run outside that original transaction.

For rejecting invalid requests, PreValidation is usually the right starting point. It normally runs before the initial transaction, but nested operations can already be inside one. Check IsInTransaction when that distinction matters.

Reference: Microsoft Learn: Register a plug-in.

One CRM requirement, two execution modes

Imagine a customer-onboarding process with three requirements: reject a missing mandatory reference, normalize a reference value, and notify a downstream system.

Before saving: validate the mandatory reference synchronously. Use PreOperation to normalize the incoming value on the Target when appropriate.

After saving: send the downstream notification asynchronously if the business accepts delayed delivery. Track an explicit integration status such as Pending, Completed, or Failed so users can distinguish a saved customer from completed onboarding.

This is a design example, not a universal rule. If downstream approval is mandatory before activation, keep the customer in a pending state until approval arrives. A saved record does not have to mean an approved customer.

Async is not “fire and forget”

Background processing needs an owner. Plan for failure visibility, controlled retries, and idempotency—repeating the same operation should not create duplicate business effects.

An asynchronous plug-in failure cannot undo the transaction that queued it. Dataverse records asynchronous failures in System Jobs rather than presenting an immediate save-error dialog. Monitor them and define a recovery process.

Reference: Microsoft Learn: Handle exceptions in plug-ins.

Three shortcuts that cause trouble

“Async is always faster.” It can shorten the user’s wait, but queueing adds overhead and the work may finish later.

“A synchronous call makes the external system part of our transaction.” Do not assume a Dataverse rollback reverses an external API’s side effects. Design reconciliation or compensation where needed.

“Async is suitable for any workload.” Plug-ins still have execution constraints. Very long work belongs in an appropriate external service or worker.

Further reading: Microsoft Learn: Transaction design patterns and Database transactions.

Make every second of waiting earn its place

Validate what must be true now. Defer what can safely happen later. Make failures visible.

Before registering your next plug-in step, ask: does the user need this result to continue, or does the system just need to get it done? That answer is where good design begins.

Rehan Khan originally posted this article on 28 October 2026 at 7:21 PM.

Leave a Reply