Skip to content

Add proper support for Azure Service Bus Emulator for development and testing#1331

Closed
yngvebn wants to merge 1 commit intoParticular:release-5.1from
yngvebn:azure-servicebus-emulator-support
Closed

Add proper support for Azure Service Bus Emulator for development and testing#1331
yngvebn wants to merge 1 commit intoParticular:release-5.1from
yngvebn:azure-servicebus-emulator-support

Conversation

@yngvebn
Copy link
Copy Markdown
Contributor

@yngvebn yngvebn commented Feb 20, 2026

Add support for configuring MaxDeliveryCount and AdministrationClientOptions
Related issue #1104

This has been tested and verified on services running on version 5.1.2 of NServiceBus.Transport.AzureServiceBus (as we're not yet on .net 10, we cannot update to 6+ yet)

Questions for the maintainers: Do you want me to also implement the changes as a separate pullrequest on the latest code?


Since Azure Service Bus emulator now exposes the management API, the emulator should now be possible to fully replace learning transport or real azure service bus for testing and development purposes. (Jeremy Miller writes about it here: https://jeremydmiller.com/2026/02/19/using-the-azure-service-bus-emulator-for-local-wolverine-development/)

The emulator exposes the management api on a separate endpoint, so in order to use it it requires the endpoint adress to be explicitly configurable.

Additionally, the Azure Service Bus emulator imposes constraints not present in the real service: it caps MaxDeliveryCount at 10.

  • Add MaxDeliveryCount property to AzureServiceBusTransport (defaults to int.MaxValue for backwards compatibility) and apply it consistently when creating queues and subscriptions across all topology creators and subscription managers.

  • Add AdministrationClientOptions property to allow consumers to customise the ServiceBusAdministrationClient, e.g. to provide a custom HTTP transport redirecting requests to a non-TLS emulator endpoint or an Endpoint connectionstring as exposed by Azure Service Bus Emulator.

Fixes startup failures when using the Azure Service Bus emulator with SetupInfrastructure = true.

…Options

The Azure Service Bus emulator imposes constraints not present in the
real service: it caps MaxDeliveryCount at 10 and does not support TLS
on the administration REST endpoint.

- Add `MaxDeliveryCount` property to `AzureServiceBusTransport` (defaults
  to `int.MaxValue` for backwards compatibility) and apply it consistently
  when creating queues and subscriptions across all topology creators and
  subscription managers.

- Add `AdministrationClientOptions` property to allow consumers to
  customise the `ServiceBusAdministrationClient`, e.g. to provide a
  custom HTTP transport redirecting requests to a non-TLS emulator
  endpoint.

Fixes startup failures when using the Azure Service Bus emulator with
`SetupInfrastructure = true`.
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Feb 20, 2026

CLA assistant check
All committers have signed the CLA.

@danielmarbach
Copy link
Copy Markdown
Contributor

danielmarbach commented Feb 20, 2026

@yngvebn Thank you for taking the time to contribute to the codebase!

It would be best to target the pull request against master. We can then decide on the backporting options as a separate decision.

I have not yet looked into all the details of the PR yet. I have two things, though, that I would like to discuss:

  • Generally we don't want to expose settings that could impose problems with the higher level APIs. So for example, exposing the max delivery count is problematic since that could cause ripple effects with the recoverability policy.
  • Given the emulator uses a well defined connection string "UseDevelopmentEmulator=true" have you considered special casing the transport internals against that? It seems the SDK parser already accounts for the special connection string and it would allow us to discover the emulator. Currently the property is still internal, but we can easily access that with UnsafeAccessor and/or contribute to the SDK to make this public. I also think both the service bus client and admin client automatically adjust to the emulator, see for example https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/servicebus/Azure.Messaging.ServiceBus/src/Administration/ServiceBusAdministrationClient.cs#L109

All this makes me think that we don't need to change the public API surface of the transport. We can switch based on the connection string to support the emulator and override internally the delivery count manually.

Please let me know if you'd like to continue driving this change or whether you'd like us to take over things at some point.

Thoughts?

@yngvebn
Copy link
Copy Markdown
Contributor Author

yngvebn commented Feb 20, 2026

@yngvebn Thank you for taking the time to contribute to the codebase!

It would be best to target the pull request against master. We can then decide on the backporting options as a separate decision.

I have not yet looked into all the details of the PR yet. I have two things, though, that I would like to discuss:

  • Generally we don't want to expose settings that could impose problems with the higher level APIs. So for example, exposing the max delivery count is problematic since that could cause ripple effects with the recoverability policy.
  • Given the emulator uses a well defined connection string "UseDevelopmentEmulator=true" have you considered special casing the transport internals against that? It seems the SDK parser already accounts for the special connection string and it would allow us to discover the emulator. Currently the property is still internal, but we can easily access that with UnsafeAccessor and/or contribute to the SDK to make this public. I also think both the service bus client and admin client automatically adjust to the emulator, see for example https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/servicebus/Azure.Messaging.ServiceBus/src/Administration/ServiceBusAdministrationClient.cs#L109

All this makes me think that we don't need to change the public API surface of the transport. We can switch based on the connection string to support the emulator and override internally the delivery count manually.

Please let me know if you'd like to continue driving this change or whether you'd like us to take over things at some point.

Thoughts?

Ah , yes this makes sense. I totally missed the stuff from the ServiceBusAdministrationClient source. I guess auto setting the MaxDeliveryCount based on the connection-string containing UseDevelopmentEmulator=true flag would be fine, but that's more up to you guys really. This would introduce hidden magic that's invisible for the user, but I recon that would be fine in the case of emulator/dev/testing? Perhaps a log-message telling the user that MaxDeliveryCount is capped at 10 due to emulator or something?

Instead of UnsafeAccessor or contributing to the SDK, a string check would probably also suffice?

I don't mind driving the change forward. It kind of depends on your capacity, and if it makes any difference release/time wise. We'd really like this functionality, cause currently we need to spin up a complete Azure Service Bus resource group in Azure in order to run dev-containers. That's a bit of a hassle :D

@danielmarbach
Copy link
Copy Markdown
Contributor

This would introduce hidden magic that's invisible for the user, but I recon that would be fine in the case of emulator/dev/testing? Perhaps a log-message telling the user that MaxDeliveryCount is capped at 10 due to emulator or something?

I don't think this is a surprise to users. For example, other Azure SDK types also have simulator / emulator support and there are inherent restrictions there too sometimes that get lifted over time. Log debug sounds fine but again I think also having no log and the transport doing the necessary internal adjustment for the emulator being used is fine to since the user explicitly does opt into using the emulator with the provided connection string.

a string check would probably also suffice?

Absolutely

I don't mind driving the change forward. It kind of depends on your capacity, and if it makes any difference release/time wise.

Up to your capacity too. Happy either way, and either way we'll have to figure out when to slot this in and when to release it as part of which version, but we can figure that out. I want to be mostly mindful about your time since you are doing volunteer work, which is well appreciated, by the way. 😍

@PhilBastian
Copy link
Copy Markdown
Contributor

Also note that the emulator has an additional restriction in total number of connections. Each full NServiceBus endpoint sets up two connections, sending and receiving, which takes up 2 of the 10 available connections. This means that dev/demo applications are effectively limited to 5 endpoints.

The learning transport does not have this limitation, so we are unlikely to replace the learning transport in Azure based samples.

@yngvebn
Copy link
Copy Markdown
Contributor Author

yngvebn commented Feb 23, 2026

Also note that the emulator has an additional restriction in total number of connections. Each full NServiceBus endpoint sets up two connections, sending and receiving, which takes up 2 of the 10 available connections. This means that dev/demo applications are effectively limited to 5 endpoints.

The learning transport does not have this limitation, so we are unlikely to replace the learning transport in Azure based samples.

Ah, I missed that. Then this wont cut it for us unfortunately. Our scenario, is running our entire environment in a docker compose, running comprehensive tests with Playwright. This gives us a deterministic throw-away environment. We started off with learning transport, but we simply got too many failures due to IO exceptions on file write/read. Obviously, learning transport isn't meant for real high-volume systems either, but I really had my hopes up for the emulator...

Guess we'll have to continue looking at using a real Service bus for the container still.

@danielmarbach
Copy link
Copy Markdown
Contributor

@yngvebn Feel free to draw inspiration from https://github.com/Particular/setup-azureservicebus-action or use it. We are not officially supporting this for our customers, but every change we do to these repositories is well versioned. This is how we spin up a dynamic ASB namespace for every build and then remove it again

@danielmarbach
Copy link
Copy Markdown
Contributor

@yngvebn We have cherry picked your changes and are streamlining things in this PR. We will keep you posted when it is released. Thanks!

@danielmarbach
Copy link
Copy Markdown
Contributor

@yngvebn Would you mind reaching out to daniel dot marbach at particular dot net? We'd like to send you a small contribution gift.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants