Dataverse plug-ins explained
How Dataverse plug-ins work — pipeline stages, sync vs async, registration, debugging, and when to use a plug-in vs a Power Automate flow.
A Dataverse plug-in is a piece of .NET code that runs server-side in response to Dataverse events. Plug-ins are the most powerful customisation mechanism in the CRM-side Dynamics 365 stack — they run in the same transaction as the originating operation, can read and modify the entire context, and can call any external service. They are also the most demanding mechanism, with operational realities that Power Automate flows usually let you avoid.
The event pipeline. Every Dataverse operation (Create, Update, Delete, Associate, etc.) runs through a defined pipeline with four stages where plug-ins can register:
-
Pre-validation (stage 10) — runs outside the database transaction, before any validation. Used for plug-ins that need to inspect or modify the request before security or duplicate-detection runs. Common for caller-context-based logic.
-
Pre-operation (stage 20) — runs inside the transaction, before the database write. Used to modify the input target (e.g. compute a derived field that should be stored), or to throw an exception to cancel the operation.
-
Main operation — the database write itself. No custom plug-ins here.
-
Post-operation (stage 40) — runs inside the transaction, after the database write. Used to do follow-on work that should be transactional with the main operation: write a related record, raise a notification, call an external API (carefully).
Synchronous vs asynchronous. Plug-ins register as either:
-
Synchronous — runs immediately, blocks the user's request until complete. Failures roll back the transaction. Use for operations that must complete before the user moves on, or that need transactional rollback semantics.
-
Asynchronous — queued for later execution by the async service. Failures are retried; the user doesn't wait. Use for follow-on work that doesn't need to complete synchronously: notifications, integrations, indexing.
The execution context. Each plug-in receives an IPluginExecutionContext with the originating message, the target entity, the user, the depth (to prevent infinite recursion if plug-ins trigger each other), and shared variables for inter-plug-in data passing.
Registration. Plug-ins are packaged as signed .NET assemblies and registered through the Plug-in Registration Tool or via solution import. Registration includes: assembly, plug-in class, message (Create/Update/etc.), entity, stage, filtering attributes (only fire when these fields change), and async flag.
When to use plug-ins vs Power Automate flows.
- Use plug-ins when:
- The logic must be in the same transaction as the originating operation.
- Performance demands milliseconds rather than seconds.
- You need access to the pre/post images of the entity.
- You need to throw exceptions to cancel the operation cleanly.
- Use Power Automate flows when:
- The logic is asynchronous and orchestration-heavy.
- It crosses systems through connectors.
- It involves human approval.
- Maintenance is by low-code makers, not developers.
In modern practice, flows replace many plug-ins; plug-ins survive for transactional, performance-sensitive, server-only logic.
Debugging. Plug-ins are notoriously hard to debug. The Plug-in Registration Tool supports plug-in profiling that captures runtime context and lets you replay it locally in Visual Studio. Trace logs are visible in the Plug-in Trace Log if enabled.
Operational caveats. Synchronous plug-ins block the user; slow plug-ins make the system feel slow. Asynchronous plug-ins compete for the async service queue; bursty volume can backlog. External API calls from inside plug-ins risk timeouts; wrap them or move to async.
Related guides
- Low-code plug-ins in DataverseHow Dataverse low-code plug-ins let makers run server-side logic without C# — Power Fx, when to use them vs Power Automate vs traditional plug-ins, and the platform trade-offs.
- Async jobs in DataverseHow Dataverse runs background work — system jobs, async plug-ins, workflow runs, and how to monitor, troubleshoot, and prevent the async backlog from getting out of hand.
- Bulk delete jobs in DataverseHow Dataverse's bulk delete handles mass record cleanup — scheduling, filters, retention policies, and the operational discipline around storage management.
- Business rules in DataverseHow business rules let you add field-level logic to forms without code — set value, lock field, show error, recommendation, and the limits of the engine.
- Business units and teams in Dataverse — a deep diveHow business units, owner teams, access teams, and Microsoft 365 group teams compose the security model in Dataverse — what each is for, how they interact, and the common design mistakes.