Skip to content

Azure Service Bus Transport: Auto-provision correlation filters for both publish and subscribe when events are multiplexed to a shared topic #1337

@danielmarbach

Description

@danielmarbach

When using topology.PublishTo<TEvent>("SharedTopic") to multiplex multiple concrete event types through a single topic, the transport currently has no awareness of this multiplexing at install time. Users must manually provision subscription rules correlation filters) via IaC or the ServiceBusAdministrationClient for both the publishing side (stamping the concrete type) and the subscribing side (filtering to only the desired type).

It would be a significant improvement if the transport could detect this multiplexing pattern and automatically provision sensible correlation filter rules on both sides when endpoint installers are enabled — but this should be an explicit opt-in, not a default behaviour.

Motivation

A common use case for topic multiplexing is polymorphic event hierarchies where:

  • A base event type (e.g. ProductOrdered) is a stable contract in its own assembly
  • Concrete derived types (e.g. CarInsuranceProductOrdered) are published to the shared base topic via PublishTo<TConcrete>("ProductOrdered")
  • Two kinds of subscribers exist:
    • Endpoints handling only a specific concrete type — these need a correlation
      filter to avoid receiving all events on that topic
    • Endpoints handling the base type — these want everything on the topic and need
      a catch-all (no filter) subscription

Without automatic provisioning, users must step outside the NServiceBus installer pipeline to configure these rules, splitting infrastructure concerns across multiple tools and creating a sharp edge when onboarding new event types.

Context

Topic multiplexing and polymorphic routing are advanced, deliberate topology choices. The recommended default for most systems remains topic-per-event, which avoids filtering complexity entirely and maps cleanly to NServiceBus's event model.

Any installer support for correlation filters should therefore be:

  • Explicitly opted into via topology configuration, not inferred automatically from the presence of PublishTo overrides
  • Clearly documented as an advanced scenario with guidance on when it is and isn't appropriate
  • Not a replacement for the auto-forwarding pattern, which remains the better fit when subscribers cannot reference concrete types at all

The goal is to reduce friction for teams who have consciously chosen multiplexing, not to make multiplexing feel like a first-class default path.

Possible Behaviour

Publish side

When an event is published to a shared/multiplexed topic, the transport should consistently stamp a well-known broker property with the concrete CLR type name (e.g. a dedicated application property). This should happen automatically when multiplexing is opted into, without requiring users to wire up OutgoingNativeMessageCustomization manually.

Subscribe side

When installers are enabled and the endpoint has opted into multiplexed subscription support, the transport should inspect IHandleMessages<T> registrations and:

  1. Concrete type handler (e.g. IHandleMessages<CarInsuranceProductOrdered>):
    Provision a CorrelationFilter on the subscription scoped to that concrete type's fully-qualified name, so the endpoint only receives matching events.

  2. Base/shared type handler (e.g. IHandleMessages<ProductOrdered>):
    Provision a catch-all subscription with no filter, receiving all events on the shared topic.

  3. Mixed handlers (endpoint handles both base and one or more concrete types):
    This is an edge case worth explicitly calling out — the transport should either warn or default to the catch-all strategy, since a correlation filter would inadvertently drop messages the endpoint is supposed to handle.

Constraints

  • Behaviour only activates when both installers are enabled and the user has explicitly opted in — zero change in behaviour for the default topic-per-event path
  • A clear, documented convention is needed for which broker property carries the concrete type name — ideally reusing something already present on NServiceBus messages (e.g. NServiceBus.EnclosedMessageTypes) to avoid inventing a new convention
  • Users managing subscription rules entirely via IaC should be able to opt out, even when using multiplexing

References

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions