Muokkaa

Jaa


Bypass Power Automate Flows

Power Automate flows can respond to Dataverse events using the When a row is added, modified, or deleted or When an action is performed triggers. When these events occur, Dataverse creates system jobs to execute these flows.

When a program or plug-in performs bulk operations, a large number of system jobs might be created. A large number of system jobs can cause performance issues for Dataverse. You can choose to bypass creating these system jobs in your program or plug-in by using the SuppressCallbackRegistrationExpanderJob optional parameter.

The CallbackRegistration table manages flow triggers, and there's an internal operation called expander that creates the system jobs.

Note

When this option is used, the flow owners will not receive a notification that their flow logic was bypassed.

When to bypass Power Automate Flows

Important

Don't use the SuppressCallbackRegistrationExpanderJob optional parameter unless you know that the performance issues you are experiencing are because of a large number of specific system jobs that are created.

People add flows for business reasons and they shouldn't be bypassed without careful consideration. Be sure to consider these Mitigation strategies.

Will SuppressCallbackRegistrationExpanderJob help you?

Use this option only if you see performance issues after bulk operations occur and you have a large number of CallbackRegistration Expander Operation system jobs with a StatusCode set to 0 : Waiting for Resources.

You can use the following queries to get information about the status of these jobs.

If the total count is greater than 50,000, these queries return the following error.

Name: AggregateQueryRecordLimitExceeded
Code: 0x8004E023
Number: -2147164125
Message: The maximum record limit is exceeded. Reduce the number of records.

Note

If the queries do not return an error, the number of queued jobs is not likely to be the issue. Typically, the number of queued jobs exceeds 50,000 records before performance issues will occur.

The following examples output the number of CallbackRegistration Expander Operation system jobs by the state code. The operationtype value for this kind of system job is 79.

static void RetrieveCallbackRegistrationExpanderStatus(IOrganizationService service)
{
    string fetchXml = @"<fetch aggregate='true'>
        <entity name='asyncoperation'>
        <attribute name='statuscode' alias='statuscode' groupby='true' />
        <attribute name='statuscode' alias='count' aggregate='count' />
        <filter>
            <condition attribute='operationtype' operator='eq' value='79' />
        </filter>
        </entity>
    </fetch>";

    FetchExpression fetchExpression = new(fetchXml);

    EntityCollection response = service.RetrieveMultiple(fetchExpression);

    foreach (Entity result in response.Entities)
    {
        string statusCode = result.FormattedValues["statuscode"];
        int count = (int)((AliasedValue)result["count"]).Value;
        Console.WriteLine($"{statusCode}: {count}");
    }
}

Output:

Canceled: 4101
Failed: 13
Waiting for Resources: 50,000

How to bypass Power Automate flows

How you bypass flows depends on whether you're using the SDK for .NET or Web API.

Note

For data operations initiated within plug-ins, you must use the SDK for .NET.

The following examples create an account record that don't trigger Power Automate.

static void DemonstrateSuppressCallbackRegistrationExpanderJob(IOrganizationService service)
{
    Entity account = new("account");
    account["name"] = "Sample Account";

    CreateRequest request = new()
    {
        Target = account
    };
    request.Parameters.Add("SuppressCallbackRegistrationExpanderJob", true);
    service.Execute(request);
}

Mitigation strategies

Flow owners expect their logic to be executed. Flow owners aren't notified that their logic was bypassed when you use this option. It's important to communicate to flow owners that the logic wasn't applied so that they know when and why their logic wasn't applied. They can then determine whether or how to apply their logic.

People can create child flows that contain logic that is invoked by multiple triggers, even manually. If the logic is contained within a child flow, it might be triggered by other means later. More information Create child flows

Identify flows that will be bypassed

You might not be able to identify exactly which flows will be bypassed. You can query the CallbackRegistration table table to assess how much impact there will be and who to contact about their flows not running. The following table describes some CallbackRegistration table columns that are useful;

Column Description
name If this value is a GUID value, it should match the flowid value and you should be able to view the flow definition in a URL with this value by adding it to this URL: https://make.powerautomate.com/environments/<environmentid>/flows/<flowid>/details.
message When the flow uses the When a row is added, modified, or deleted trigger, it might subscribe to all the combinations of Create, Update, and Delete operations with these options:
- 1: Added
- 2: Deleted
- 3: Modified
- 4: Added or Modified
- 5: Added or Deleted
- 6: Modified or Deleted
- 7: Added or Modified or Deleted
sdkmessage When the flow uses the When an action is performed trigger, this column contains the name of the message.
scope Flows only apply to the scope specified by the user as defined using these options:
- 1: User
- 2: BusinessUnit
- 3: ParentChildBusinessUnit
- 4: Organization
ownerid The owner of the callback registration and the flow.
softdeletestatus Whether the flow is deleted. 0 isn't deleted. 1 is deleted.

The following example queries return these values:

static void RetrieveCallbackOperations(IOrganizationService service)
{

    QueryExpression callbackRegistrationQuery = new("callbackregistration")
    {
        ColumnSet = new ColumnSet("name", "entityname", "message", "sdkmessagename", "scope", "ownerid"),
        Criteria = new FilterExpression(LogicalOperator.And)
        {
            Conditions = {
                { new ConditionExpression("softdeletestatus",ConditionOperator.Equal,0) },
                // Add more conditions here to filter the results
            }
        }
    };

    EntityCollection callbackRegistrations = service.RetrieveMultiple(callbackRegistrationQuery);

    foreach (Entity callbackRegistration in callbackRegistrations.Entities)
    {
        string ownerid = callbackRegistration.FormattedValues["ownerid"];
        string scope = callbackRegistration.FormattedValues["scope"];
        string name = callbackRegistration.GetAttributeValue<string>("name");
        string message = callbackRegistration.FormattedValues["message"];
        string entityname = callbackRegistration.GetAttributeValue<string>("entityname");
        string sdkmessage = callbackRegistration.GetAttributeValue<string>("sdkmessagename");

        Console.WriteLine($"{ownerid},{scope},{name},{message},{entityname},{sdkmessage},");
    }
}

Output

FirstName LastName,Organization,de7153ba-9221-4079-82cc-c884bbd05dc0,Modified,account,,
FirstName LastName,Organization,Callback Registration Id: b44090aa-adde-4866-ac2e-d68fbcbe7d5a,Added,account,,
FirstName LastName,Organization,Callback Registration Id: dabfa1a1-b794-44d0-ad34-cd49ea650606,Added,none,sample_BusinessEvent,

Frequently asked questions about bypassing Power Automate flows (FAQ)

Following are frequently asked questions about using the SuppressCallbackRegistrationExpanderJob optional parameter to bypass Power Automate flows.

Do users need a special privilege?

No. Unlike options to bypass custom Dataverse logic, no special privilege is required.

If my client application uses this optional parameter, will any operations performed by plug-ins registered against the operation also apply it?

No. The parameter isn't passed through to any operations performed by plug-ins that are registered for the events that occur because of requests from your client application. If you want to bypass flows for operations performed by plug-ins, you must use the SuppressCallbackRegistrationExpanderJob optional parameter in your plug-in code.

See also

Bypass Custom Dataverse Logic
Use optional parameters