The IBM MQ transport implements publish/subscribe messaging using IBM MQ's native topic and subscription infrastructure. Event subscriptions do not require NServiceBus persistence as IBM MQ handles durability natively.
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. Messages are delivered to each subscriber's input queue.
Sending (unicast)
Commands are sent directly to the destination queue by name. No topics are involved.
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) handle two functions: point-to-point messaging for commands and destination queues for durable subscription(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:
| Property | Example |
|---|---|
| Topic name (admin object) | DEV. |
| Topic string | dev/ |
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:
| Resource | Created by | When |
|---|---|---|
| Input queue | Both publisher and subscriber | At startup, for the endpoint's own queue |
| Error queue | Both publisher and subscriber | At startup |
| Send destination queues | Sender | At startup, for all configured send-only destinations |
| Topic objects | Publisher or subscriber | At startup, for all explicitly configured PublishTo and SubscribeTo topic routes |
| Durable subscriptions | Subscriber | At 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
The transport uses a topic-per-event model—each concrete event type gets its own topic. This design ensures predictable message routing but requires explicit configuration when using event hierarchies.
When subscribing to a base class or interface, you don't 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 checks for known descendants when you subscribe. If descendants are found, it throws an InvalidOperationException at startup. 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:
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;
Disabling this guard means subscribing to a base type will silently create a subscription only for that exact type's topic. Messages published as derived types will not be received unless explicit routes are configured.
Deployment recommendations for polymorphic event hierarchies
To avoid message loss with polymorphic events, follow these deployment practices. Distribute event types in dedicated, independently versioned packages, which 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:
- Deploy the updated message contracts package containing the new event type.
- Update subscriber endpoint configurations to add
SubscribeToroutes for the new type. - Run the command-line tool to create subscriptions for all subscribers, or deploy and start all subscribing endpoints so they create their durable subscriptions.
- Deploy and start the publishing endpoint.
Topic naming
Topics use a configurable naming strategy with a DEV prefix by default. The fully qualified type name determines the remainder:
| Concept | Example |
|---|---|
| Topic name | DEV. |
| Topic string | dev/ |
| Subscription name | OrderService:dev/ |
IBM MQ topic names are limited to 48 characters. If the generated name exceeds this limit, the transport throws an exception at startup. See topic naming configuration for how to customize the naming strategy.