Chapter 20 Key Takeaways: Event-Driven Architecture with COBOL


Core Architectural Shift

From request/reply to publish/subscribe inverts the communication model. Instead of "System A asks System B to do something and waits," it becomes "System A announces that something happened, and any system that cares reacts independently." The producer doesn't know or care who the consumers are. Adding a new consumer is a configuration change (one subscription definition), not a code change.


Three Tools for Event-Driven COBOL

1. MQ Triggers — React to Messages

  • MQ triggers automatically start COBOL programs when messages arrive on a queue
  • TRIGTYPE(FIRST): Fires once when the first message arrives on an empty queue. The triggered program must drain all messages. Standard choice for high-volume queues.
  • TRIGTYPE(EVERY): Fires for every message. Only for low-volume queues — will overwhelm CICS on high-volume queues.
  • TRIGTYPE(DEPTH): Fires when queue depth reaches a threshold. For batch-oriented triggered processing.
  • CKTI is the CICS trigger monitor that reads the initiation queue and starts transactions
  • Triggered programs use EXEC CICS RETRIEVE to get the trigger message and discover the queue name

2. CICS Event Processing — Capture Without Code Changes

  • EP intercepts CICS API commands at runtime and emits events through adapters (MQ, HTTP, TS Queue)
  • Event bindings are XML configuration deployed as CICS bundles — no code compilation, no application modification
  • EP can capture FILE operations, LINK/XCTL, START, and other CICS commands
  • EP cannot capture pure COBOL logic (no EXEC CICS interception point)
  • Default EP emission is asynchronous — not part of the application's unit of work (phantom events possible)

3. MQ Pub/Sub — Broadcast to Multiple Consumers

  • Topics are hierarchical (forward-slash delimited): CNB/EVENTS/WIRE/SUBMITTED
  • # wildcard matches zero or more levels; + matches exactly one level
  • Durable subscriptions survive disconnections and restarts — required for production financial systems
  • Non-durable subscriptions exist only while connected — monitoring and dev only
  • Administrative subscriptions (created by MQ admin) are preferred over programmatic subscriptions for operational visibility
  • Publishing from COBOL uses MQOT-TOPIC in the MQOD; the MQPUT call itself is identical to queue-based PUT

Event Schema Design Rules

  1. Every event has a header: version, type, ID, timestamp, source system, correlation ID
  2. Semantic versioning: Major changes break compatibility. Minor changes add fields only.
  3. Never remove or redefine fields within a major version
  4. Self-describing events: Include all data the consumer needs — don't force database lookups
  5. FILLER fields (20%+) in COBOL copybooks for forward compatibility
  6. Correlation ID in every event for end-to-end tracing
  7. Maintain an event catalog — registry of all event types, schemas, producers, and consumers

Event-Driven Patterns

Pattern Use When Mainframe Implementation
Event Sourcing Immutable audit trails, point-in-time reconstruction Event stream as source of truth; materialized DB2 views for fast reads
CQRS Write model and read model need different optimizations Normalized write tables + denormalized read tables, bridged by events
Saga Distributed transactions across systems without 2PC Saga coordinator program with state in DB2, compensating actions for rollback
Idempotent Consumer Always (MQ provides at-least-once, not exactly-once) Event log table checked before processing, in the same unit of work
Circuit Breaker Consumer connecting to an unreliable downstream service Failure count tracking, three states (closed/open/half-open), configurable cooldown

Production Rules

  • TRIGTYPE(FIRST) for high-volume queues. Always. TRIGTYPE(EVERY) on a high-volume queue will crash your CICS region.
  • Drain the queue in a triggered program. Process messages until MQGET returns 2033. Use a short wait interval (5 seconds) to catch messages that arrive during processing.
  • Monitor CKTI health. If the initiation queue depth is growing, CKTI is either not running or not keeping up.
  • Every subscription queue gets depth monitoring. Alert at 80% of MAXDEPTH. No exceptions.
  • Durable subscriptions for production. Non-durable subscriptions lose messages when the subscriber disconnects.
  • Idempotent consumers. Always. Check the event log before processing. Log and process in the same UOW.
  • MQPMO-SYNCPOINT for critical events. The event and the business operation must commit or roll back together.
  • Monitor the DLQ for event messages. A DLQ entry is a failed business event, not just a failed message.

Common Mistakes

Mistake Consequence Fix
TRIGTYPE(EVERY) on high-volume queue CICS region hits MAXT, SOS, cascading abends TRIGTYPE(FIRST), drain the queue
Triggered program processes one message and exits Queue messages sit unprocessed until next trigger cycle Process all messages until MQGET returns 2033
No idempotency in event consumers Duplicate events cause duplicate business processing (double debits, double notifications) Event log table, check before processing
Asynchronous EP for transactionally critical events Phantom events emitted for rolled-back transactions Application-level MQPUT under syncpoint
Non-durable subscriptions in production Messages lost when subscriber disconnects for maintenance DURABLE(YES) on all production subscriptions
No subscription queue monitoring Queue fills silently, events lost to DLQ Depth monitoring with alerts on every subscription queue
God Event (200 fields in one event) Every consumer coupled to every field; schema changes affect everyone Domain-specific events with focused payloads
Topic explosion (per-branch, per-currency topics) Unmanageable subscription count Hierarchical topics with wildcard subscriptions; filter on content
Saga without persistent state Saga cannot resume after crash; orphaned partial transactions Saga state in DB2, committed with each step
Event sourcing without snapshots State reconstruction time grows unbounded Periodic snapshots to bound replay to a fixed interval

Architecture Decision: Event-Driven vs. Request/Reply

Use Event-Driven (Pub/Sub) When: - Multiple consumers need the same data - The producer doesn't need a response before continuing - You need to add consumers without modifying the producer - Different consumers process at different speeds - Audit logging, analytics, and monitoring are needed alongside primary processing

Use Request/Reply When: - The sender needs a response before proceeding (authorization, balance inquiry) - There is exactly one consumer - The interaction is inherently synchronous (ATM: dispense cash only after approval) - Strong transactional coupling is required between request and response

At CNB, ~30% of flows converted to event-driven. ~70% remained request/reply. The skill is knowing which flows belong in which model.


Looking Ahead

This chapter gave you the event-driven toolkit: MQ triggers for reactive processing, CICS EP for non-invasive event capture, pub/sub for multi-consumer distribution, and event schemas for sustainable contracts. Chapter 21 extends these patterns to the API world — exposing mainframe events through API gateways, webhooks, and z/OS Connect so that systems outside the mainframe can participate in the event-driven architecture. Chapter 22 completes the integration picture with data integration patterns that combine file-based, message-based, and API-based feeds.