Getting Started
Architecture
NServiceBus
Transports
Persistence
ServiceInsight
ServicePulse
ServiceControl
Monitoring
Modernization
Samples

Publish/subscribe topology

Component: IBM MQ Transport
NuGet Package: NServiceBus.Transport.IBMMQ 1.x
Target Version: NServiceBus 10.x

The IBM MQ transport implements publish/subscribe messaging using IBM MQ's native topic and subscription infrastructure. Event subscriptions do not require NServiceBus persistence.

Topology

The transport uses one IBM MQ topic per concrete event type. When an event is published, the message is sent to the corresponding topic. Subscribers create durable subscriptions against the topic, with messages delivered to their input queue.

graph LR P[Publisher Endpoint] -->|publish| T[Topic: DEV.ORDERPLACED] T -->|durable subscription| S1[Subscriber A Queue] T -->|durable subscription| S2[Subscriber B Queue]

Sending (unicast)

Commands are sent directly to the destination queue by name. No topics are involved.

graph LR S[Sender Endpoint] -->|put message| Q[Destination Queue] Q --> R[Receiver Endpoint]

Publishing (multicast)

When an endpoint publishes an event, the message is published to the topic for that event type. IBM MQ delivers a copy to every endpoint with a durable subscription on that topic.

Subscribing

When an endpoint subscribes to an event type, the transport creates a durable subscription linking the event's topic to the endpoint's input queue. When the endpoint starts, existing subscriptions are resumed automatically.

Unsubscribing

When an endpoint unsubscribes from an event type, the durable subscription is deleted from the queue manager.

IBM MQ resources

The transport uses three types of IBM MQ resources:

Queues

Local queues (QLOCAL) are used for point-to-point messaging (commands) and as the destination for durable subscriptions (events). Each endpoint has an input queue named after the endpoint.

Topic objects

An administrative topic object defines the mapping between a topic name (the admin object identifier, max 48 characters) and a topic string (the routing path used by publishers and subscribers). For example:

PropertyExample
Topic name (admin object)DEV.MYAPP.EVENTS.ORDERPLACED
Topic stringdev/myapp.events.orderplaced/

Publishers open the topic by its topic string to publish messages. The admin object must exist on the queue manager before publishing.

Subscriptions

A durable subscription links a topic string to a destination queue. When a message is published to a matching topic string, IBM MQ delivers a copy to the subscription's destination queue. Subscription names follow the format EndpointName:topicstring/, for example:

OrderService:dev/myapp.events.orderplaced/

Resource creation

When installers are enabled

When EnableInstallers() is called, the transport creates resources during endpoint startup:

ResourceCreated byWhen
Input queueBoth publisher and subscriberAt startup, for the endpoint's own queue
Error queueBoth publisher and subscriberAt startup
Send destination queuesSenderAt startup, for all configured send-only destinations
Topic objectsPublisher or subscriberAt startup, for all explicitly configured PublishTo and SubscribeTo topic routes
Durable subscriptionsSubscriberAt subscribe time, when the endpoint subscribes to an event type

When installers are not enabled

The transport validates that all explicitly configured topics exist on the queue manager. If any are missing, startup fails with an InvalidOperationException listing the missing topics. Queues and subscriptions must be pre-created using the command-line tool or native IBM MQ administration.

See security and permissions for the IBM MQ authorities required for each operation.

Polymorphism

IBM MQ uses a topic-per-event model: each concrete event type is published to its own topic. Subscribing to a base class or interface does not automatically subscribe to topics for derived types. Without explicit configuration, a handler for IOrderEvent would only receive messages published directly to the IOrderEvent topic, missing messages published as OrderPlaced or OrderCancelled.

To prevent accidental under-subscription, the transport throws an InvalidOperationException at startup when subscribing to a type that has known descendants in the loaded assemblies. This guard is controlled by ThrowOnPolymorphicSubscription (default: true).

Explicit subscription routing

Use SubscribeTo to map a subscribed event type to the concrete types' topics that should be received:

var transport = new IBMMQTransport
{
    // ... connection settings ...
};

// Subscribe to OrderPlaced and all known concrete types
transport.Topology.SubscribeTo<IOrderEvent, OrderPlaced>();
transport.Topology.SubscribeTo<IOrderEvent, ExpressOrderPlaced>();

This creates subscriptions on both the OrderPlaced and ExpressOrderPlaced topics, delivering both to the subscriber's input queue:

graph LR subgraph "SubscribeTo&lt;IOrderEvent, OrderPlaced&gt;() + SubscribeTo&lt;IOrderEvent, ExpressOrderPlaced&gt;()" T1[Topic: DEV.ORDERPLACED] -->|subscription| Q[OrderHandler Queue] T2[Topic: DEV.EXPRESSORDERPLACED] -->|subscription| Q end

Alternatively, specify topic strings directly when they don't follow the naming convention:

var transport = new IBMMQTransport
{
    // ... connection settings ...
};

// Subscribe using explicit topic strings
transport.Topology.SubscribeTo<IOrderEvent>("prod/mycompany.events.orderplaced/");
transport.Topology.SubscribeTo<IOrderEvent>("prod/mycompany.events.expressorderplaced/");

Explicit publish routing

Use PublishTo to override the topic for a published event type. This is useful when integrating with existing topic structures:

var transport = new IBMMQTransport
{
    // ... connection settings ...
};

// Override the default topic for a published event type
transport.Topology.PublishTo<OrderPlaced>("legacy/order/events/");

// When the admin object name can't be derived from the topic string
transport.Topology.PublishTo<OrderPlaced>("LEGACY.ORDER.EVENTS", "legacy/order/events/");

Disabling the polymorphic subscription guard

If a subscriber intentionally subscribes to only one type's topic (without receiving descendants), disable the guard:

var transport = new IBMMQTransport
{
    // ... connection settings ...
};

// Disable the guard that throws when subscribing to a type with descendants
transport.Topology.ThrowOnPolymorphicSubscription = false;

Deployment recommendations for polymorphic event hierarchies

When using polymorphic events, distribute event types in dedicated, independently versioned packages. This allows subscribers to reference new concrete types and update their subscriptions before the publisher begins publishing those events.

Ensure that the deployment pipeline runs all subscriber subscription steps before starting the new version of the publisher. If a publisher starts publishing a new concrete event type before subscribers have created their subscriptions, those messages will be lost because no durable subscription exists to route them to a queue.

A typical deployment order:

  1. Deploy the updated message contracts package containing the new event type.
  2. Update subscriber endpoint configurations to add SubscribeTo routes for the new type.
  3. Run the command-line tool to create subscriptions for all subscribers, or deploy and start all subscribing endpoints so they create their durable subscriptions.
  4. Deploy and start the publishing endpoint.

Topic naming

Topics are named using a configurable strategy. The prefix defaults to DEV and the fully qualified type name determines the rest:

ConceptExample
Topic nameDEV.MYAPP.EVENTS.ORDERPLACED
Topic stringdev/myapp.events.orderplaced/
Subscription nameOrderService:dev/myapp.events.orderplaced/