When working with a message broker or event broker to push data into a Saas like Dataverse, it’s essential to understand the data volume and the ingress capability to avoid passing the limits or moving too slowly when you have a certain amount of data that needs to get in a short period.
It turns out that the defaults for the Service Bus and Event Hub trigger functions and their interaction with the Azure Function controller are significantly different.
If you don’t know what the controller is:
“Azure Functions uses a component called the scale controller to monitor the rate of events and determine whether to scale out or scale in. The scale controller uses heuristics for each trigger type. For example, when you’re using an Azure Queue storage trigger, it uses target-based scaling.“
Event-driven scaling in Azure Functions | Microsoft Learn
This table shows the different defaults between hub and bus:

Target-based scaling in Azure Functions | Microsoft Learn
Based on the above, Event hub trigger pull small batches of 10 events while service bus trigger pulls up to 1000. The Service bus allows to set the max amount of concurrent calls. Event hub does not have that setting and based on some testing I concluded the event hub function controller does not scale out like the service bus side.
First, it’s important to notice how this affect a function processing batches vs single events.
This will pull a batch and loop through it per function instance:
[FunctionName("EventHubTriggerCSharp")]
public void Run([EventHubTrigger("samples-workitems", Connection = "EventHubConnectionAppSetting")] EventData[] eventHubMessages, ILogger log)
{
foreach (var message in eventHubMessages)
{
log.LogInformation($"C# function triggered to process a message: {Encoding.UTF8.GetString(message.Body)}");
log.LogInformation($"EnqueuedTimeUtc={message.SystemProperties.EnqueuedTimeUtc}");
}
}
This will pull 1 event per function instance:
[FunctionName("EventHubTriggerCSharp")]
public void Run([EventHubTrigger("samples-workitems", Connection = "EventHubConnectionAppSetting")] string myEventHubMessage, ILogger log)
{
log.LogInformation($"C# function triggered to process a message: {myEventHubMessage}");
}
Basic host.json and no changes to defaults:
Default Host.json:
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
}
}
}
}
Service Bus pulling Batches, using default settings on a consumption function app:
This is using all default settings, no custom settings. I didn’t add anything to delay or increase performance. The Azure Function code is the Visual Studio template and the function app has nothing extra than the initial setup.

Result: A whooping 1000 records per minute. The code just inserts data into a custom Dataverse entity without any underlying logic from plugins or any custom code.
The “combined” Service Bus and Function App controller (with default settings) scales more than the event hub.
Does it mean Service Bus is faster? Not necessarily. You can change those defaults (for both bus trigger and hub trigger) to a more suitable pace that is not to slow but does not exceed the Saas limits (more here).
In the case of Service Bus default speed, it is borderline dangerous for Dataverse. To slow down there are a few things we can do:
1 – Hard code same session id
This have reduced the speed to 300 records per/min
2 – You can specify a lower maximum for a specific app by modifying the functionAppScaleLimit value. The functionAppScaleLimit can be set to 0 or null for unrestricted, or a valid value between 1 and the app maximum.
az resource update --resource-type Microsoft.Web/sites -g <RESOURCE_GROUP> -n <FUNCTION_APP-NAME>/config/web --set properties.functionAppScaleLimit=<SCALE_LIMIT>
using the above with SCALE_LIMIT = 1 reduced the pace to 200 records per minute.
Now, Event Hub “Function trigger on defaults” with a “single or couple throughput units” can be slow. like 200 records per min. We can increase performance by increasing settings in the host.json file like “maxEventBatchSize” and “prefetchCount”. But the Event Hub also allow us to add more partitions and increase the amount of throughput units.
{
"version": "2.0",
"extensions": {
"eventHubs": {
"maxEventBatchSize": 300,
"minEventBatchSize": 25,
"maxWaitTime": "00:05:00",
"batchCheckpointFrequency": 1,
"prefetchCount": 500,
"targetUnprocessedEventThreshold": 75,
"clientRetryOptions": {
"mode": "exponential",
"tryTimeout": "00:01:00",
"delay": "00:00:00.80",
"maximumDelay": "00:01:00",
"maximumRetries": 3
}
}
}
}
Partitions can increase parallelism:

But the above still rely on the function app to provision more parallel instances. when another parallel instance appear, will be on the same consumer group and then we should notice performance.
I have noticed immediate improvement when increasing throughput units.

With more throughput units and changing the host.json to pull larger batchsize, the speed now changed from
200 records created per min to 400 records created per minute.
In the end, considering the consumer has Dataverse in the other end, either broker will do fine. The important is to avoid exceeding the maximum amount of concurrent or cumulative requests.
Dataverse limits:

Salesforce limits:

Conclusion
When the objective is to push data into a service without much ingress, the goal is to not exceed but find the best pace to push as much as we can without trespassing the limits.
The fact Event hub default is lower does not mean we can’t change to a higher pace.
When using Service Bus, the defaults start very high. You will need to reduce it to avoid to many connections passing the Dataverse limits.
When using Event Hub to push events into Dataverse, if the pace is to slow, you can:
- Increase the amount of throughput units.
- Enable batch and increase the batch size and prefetch to an amount that feeds data without passing the threshold.
But after all, if you have a large amount of data to push into Dataverse in a short period of time and after tunning the functions you start to have errors regarding exceeding requests, change the code to use bulk insert:
Execute batch operations using the Web API (Microsoft Dataverse) – Power Apps | Microsoft Learn
Leave a Reply