Event-Driven Microservices with IBM MQ

Microservices split applications into small deployable units with bounded contexts—orders, payments, inventory, notifications—each owning its data and releasing on its own cadence. Event-driven microservices go further: they announce what happened in one service so others react without compile-time coupling to every downstream API. IBM MQ is a practical transport for that style in enterprises that already run queue managers for mainframe and payment traffic. Containers connect over TLS client channels; topics fan out ORDER.CREATED to fraud, warehouse, and analytics; work queues buffer commands when a downstream pod restarts. This tutorial connects microservice principles to MQ objects you can define today: topic trees, durable subscriptions, correlation for sagas, outbox publishers, hub queue managers in Kubernetes, and coexistence with z/OS producers on the same event backbone.

Commands, Events, and Queries

A useful split (popularized as CQRS alongside event-driven design) keeps three message intents separate even when they share one queue manager. Commands instruct one logical handler: ReserveInventory with a single consumer group reading INVENTORY.COMMANDS. Events announce facts: OrderPlaced on topic commerce/order/placed for any subscriber. Queries are usually synchronous HTTP or request/reply on a dedicated queue when you must read authoritative state from another service—MQ request/reply with ReplyToQ avoids inventing a new REST hop through a brittle chain. Mixing commands and events on one queue without naming discipline confuses operators—depth on ORDER.WORK might be commands or duplicate events.

Message intent and MQ objects
IntentMQ objectConsumers
CommandQLOCAL work queueOne active consumer per partition
Domain eventTOPIC + SUBMany independent subscribers
Query (async)Request + reply queuesOne responder
Integration eventHub alias queueBridge to legacy

Topic Design for Microservices

Topic strings should reflect business language, not deployment names. A hierarchy like commerce/order/placed scales better than team-a-queue because teams change; domains endure. Wildcard subscriptions let analytics subscribe to commerce/order/> while shipping subscribes to commerce/order/shipped only. Durable subscriptions keep subscriber queues receiving messages while the notification service is down for deploy—messages accumulate until the pod returns. Non-durable suits ephemeral test consumers. Retained publications (where configured) help new instances of a read-model service catch the latest product catalog snapshot without a separate bootstrap API.

shell
1
2
3
4
5
6
7
DEFINE TOPIC('COMMERCE.ORDER') TOPICSTR('commerce/order/>') DEFINE SUB('SUB.NOTIFY') TOPICSTR('commerce/order/placed') + DEST('NOTIFY.ORDER.PLACED') DESTQMGR('QM_COMMERCE_HUB') DEFINE SUB('SUB.ANALYTICS') TOPICSTR('commerce/order/>') + DEST('ANALYTICS.ORDER.EVENTS') DESTQMGR('QM_COMMERCE_HUB') * commerce/order/> — matches placed, shipped, cancelled * commerce/order/placed — exact match for notification service only

Transactional Outbox Pattern

Dual-write failure happens when a service commits an order row then crashes before MQPUT—or puts to MQ then the database rolls back. The outbox table lives in the service database: columns for event type, payload JSON, and published flag. The same transaction inserts the order and an outbox row. A relay process polls or uses change-data capture, MQPUTs to the topic, then marks published. MQ persistence and syncpoint on the relay side ensure at-least-once delivery; consumers remain idempotent. On mainframe estates, the relay may run on Linux reading Db2 change tables fed from z/OS replication—same pattern, different plumbing.

Sagas and Long-Running Processes

A saga coordinates multiple services without a single distributed two-phase commit. Each step consumes a command, performs local work, publishes success or failure events. Compensation commands undo prior steps—ReleaseInventory after PaymentFailed. MQ carries each step message; correlation IDs tie the saga instance together in logs and payloads. If step three retries, idempotency keys prevent double charge. Choreography uses only events (services listen and react); orchestration uses a central coordinator putting commands to step queues—both work on MQ; orchestration is easier to debug, choreography avoids a single point of failure.

Kubernetes and Client Connections

Microservice pods are stateless; the queue manager is stateful. Deploy IBM MQ as a StatefulSet or use IBM MQ on Cloud / enterprise hub. Applications set MQCONN to the service DNS name, use CCDT or environment variables (MQSERVER, MQCHLLIB), and connect through SVRCONN with TLS. Horizontal pod autoscaling increases consumer instances; competing GETs on a work queue distribute load. Channel CHLAUTH maps certificate DN or asserted user to MCAUSER with minimal authority. Liveness probes should not open MQ connections on every HTTP health check—use a lightweight indicator or separate readiness that tolerates brief MQ outages.

Kubernetes deployment options for MQ
PatternWhen to useTrade-off
Shared hub QMMost microservice fleetsCentral ops; network hop
QM per domainStrong isolationMore channels and certs
QM in StatefulSetEdge or devPod storage and backup duty
Managed MQ cloudFast start, ops outsourcedCost and residency rules

Hybrid: Mainframe Events and Cloud Consumers

CICS can MQPUT OrderPlaced to a shared z/OS queue; a channel forwards to the commerce hub topic where microservices subscribe. Payload format may be COBOL copybook on the wire and JSON inside the cloud consumer after transformation in an adapter flow. The event-driven microservices tutorial in the real-world track pairs with mainframe integration: never assume one serialization fits all tiers. Version events in the payload (schemaVersion: 2) so consumers evolve independently.

Observability and Operations

Propagate trace context in MQRFH2 or message properties when your APM tool supports it. Alert on subscriber queue depth, not only topic publish rate—a silent subscriber looks healthy until its queue hits MAXDEPTH. Use message IDs in structured logs. Poison messages from bad deploys land in DLQ; roll back the consumer deployment before requeueing thousands of bad events. REST admin API and Prometheus metrics complement runmqsc for GitOps estates.

Explainer: Neighborhood Bulletin Board

Microservices are shops on a street. Instead of each shop calling every other shop by phone for every sale, they pin notes on a bulletin board (topic). Shops read only the notes they care about (subscriptions). Urgent one-to-one instructions (commands) still go in sealed envelopes to one mailbox (work queue).

Anti-Patterns to Avoid

  • God topic where every event uses one string—subscribers cannot filter and load explodes.
  • Synchronous chains of ten REST calls that should be one event and async processing.
  • Non-persistent financial events to save disk—regulators and recovery teams disagree.
  • Shared MCAUSER on all microservices—one compromise owns every queue.
  • Infinite retry without DLQ—poison message blocks the whole consumer group.

Explain Like I'm Five: Event Microservices

Lots of little robot helpers do one job each. When something happens, one helper shouts it on a loudspeaker (topic) and the other helpers who care about that news do their job. IBM MQ is the loudspeaker system that saves the shout if some helpers are napping, so no news is lost.

Practice Exercises

Exercise 1

Design topic strings for order placed, paid, shipped, and cancelled in one domain hierarchy.

Exercise 2

Sketch outbox flow: database tables, relay, topic, two subscribers.

Exercise 3

Write compensation commands for a three-step saga (reserve, charge, ship).

Frequently Asked Questions

Frequently Asked Questions

Test Your Knowledge

Test Your Knowledge

1. Domain events in microservices usually use:

  • Topics for fan-out
  • Only DLQ
  • FTP
  • DNS records

2. Outbox pattern separates:

  • DB commit from MQ publish
  • TLS from TCP
  • JCL from COBOL
  • Browse from get

3. Saga compensation messages are often:

  • Commands on dedicated queues
  • Only non-persistent
  • Never correlated
  • Browse-only

4. Microservices connect to MQ via:

  • Client connection channels
  • Only batch JCL
  • Only listeners
  • No queue manager
Published
Read time22 min
AuthorMainframeMaster
Verified: IBM MQ 9.4 documentation