5.4 Registering Plug-ins with the Plug-in Registration Tool & Optimizing Plug-in Performance

Key Takeaways

  • The Plug-in Registration Tool (PRT) registers assemblies, plugin types, steps, and images in a strict hierarchy, and requires Sandbox isolation mode for custom code.
  • Step registration fields -- Message, Primary Entity, Stage, Execution Mode, Filtering Attributes, and Secure/Unsecure Configuration -- determine when a step fires and what data it can access.
  • Filtering Attributes restrict a step to fire only when specific fields are part of the update, which is one of the highest-leverage performance levers available at registration time.
  • Secure Configuration stores secrets like API keys outside the UI and solution export; Unsecure Configuration is visible to anyone who can view the step.
  • Sandboxed plug-ins run under a hard two-minute execution timeout; long-running work belongs in an Azure Function or Power Automate flow, not inline in the plug-in.
Last updated: July 2026

Writing the plug-in class is only half the job -- Dataverse doesn't know a compiled assembly exists until you register it, and how you register each step directly affects both correctness and performance. The Plug-in Registration Tool (PRT) is the primary tool for this, and the choices it exposes map directly to the pipeline concepts from 5.1-5.3.

The Plug-in Registration Tool

PRT is a standalone application, distributed as a NuGet package (Microsoft.CrmSdk.XrmTooling.PluginRegistrationTool) and also installable through the Power Platform CLI, that connects to a Dataverse environment and lets you register, update, and manage plug-in assemblies without writing SDK code by hand. Registration follows a strict hierarchy:

  1. Assembly -- upload the compiled DLL. You choose an Isolation Mode: Sandbox is required for essentially all custom, non-Microsoft code -- it runs the assembly in a restricted, isolated worker process. The legacy None mode runs unrestricted with full trust and is reserved for privileged first-party scenarios; it isn't available for typical ISV or customer plug-in deployment.
  2. Plugin Type -- the specific class within the assembly (an assembly can contain multiple IPlugin classes).
  3. Step -- the registration that ties a plugin type to a specific message, table, stage, and mode. One plugin type can have multiple steps.
  4. Image -- optional, registered under a step (5.3).

Step Registration Fields

FieldPurpose
MessageThe SDK message to subscribe to (Create, Update, Delete, a custom message, etc.)
Primary EntityThe table the step fires for
Event Pipeline StagePre-validation, Pre-operation, or Post-operation (5.1)
Execution ModeSynchronous or Asynchronous
DeploymentTypically Server Only for modern deployments
Run in User's ContextWhich security context the plug-in executes under
Filtering AttributesRestricts the step to fire only when one of the listed attributes is present in the update
Unsecure / Secure ConfigurationTwo free-text strings passed into the plug-in's constructor

Filtering Attributes deserve special attention: without them, an Update step fires on every update to the table, regardless of which field changed. Filtering to just the attributes the logic actually cares about means the plug-in -- and the sandbox overhead of invoking it -- is skipped entirely for unrelated changes. This is one of the single highest-leverage performance decisions available at registration time.

Secure vs. Unsecure Configuration solve different problems. The unsecure configuration string is visible to anyone with access to view the step, including through solution export, so it's appropriate for non-sensitive settings. The secure configuration string is stored separately, is never exposed through the UI or solution export, and can only be read by the plug-in itself at runtime -- the correct place for API keys, connection strings, or other secrets. Both strings, if present, are passed into the plug-in class's constructor:

public class MyPlugin : IPlugin
{
    private readonly string _secureConfig;

    public MyPlugin(string unsecureConfig, string secureConfig)
    {
        _secureConfig = secureConfig;
    }

    public void Execute(IServiceProvider serviceProvider) { /* ... */ }
}

Optimizing Plug-in Performance

The exam expects concrete, applied performance judgment, not just terminology. The recurring levers:

  • Filter aggressively. Use Filtering Attributes so a step only fires for relevant field changes, and restrict registered images to the specific columns the logic reads rather than the full record.
  • Prefer asynchronous where the user doesn't need to wait. Anything that doesn't have to block the save -- notifications, non-critical downstream updates, calls to slow external systems -- belongs at post-operation, asynchronous, so the caller's transaction isn't held open.
  • Respect the sandbox timeout. Sandboxed plug-ins run in an isolated worker process with a hard two-minute execution limit; a step that exceeds it is terminated and fails. Genuinely long-running work, such as large batch processing or slow third-party calls, doesn't belong inline in a plug-in at all -- hand it off to an Azure Function or a Power Automate flow (7.4, 8-series) and have the plug-in just kick off that work.
  • Guard against recursion. Check context.Depth before a plug-in performs writes that could re-trigger its own step, both for correctness and to avoid wasted sandbox cycles.
  • Query narrowly. Always pass an explicit ColumnSet on Retrieve/RetrieveMultiple instead of requesting every column, and add filter criteria to QueryExpression or FetchXML rather than retrieving broadly and filtering in code.
  • Reuse the service instance. Create one IOrganizationService per Execute call, via the factory, rather than requesting it repeatedly, and batch multiple related operations through ExecuteMultipleRequest instead of looping individual calls when a plug-in must perform several writes.
  • Trace judiciously. ITracingService.Trace calls are useful for debugging but add overhead in high-volume synchronous steps; keep them meaningful rather than verbose in production code.

Registration and performance decisions aren't separable from the design choices in 5.1-5.3: a step registered at the wrong stage, without filtering attributes, or with an oversized image, is a correctness and a performance problem at the same time -- and it's exactly the kind of combined judgment PL-400 scenario questions test.

Test Your Knowledge

A step is registered on the Update message for a table with no Filtering Attributes configured. What is the performance consequence?

A
B
C
D
Test Your Knowledge

Where should a plug-in store an external API key so it stays out of solution exports and is not visible to users who can view the step's registration?

A
B
C
D