At-Least-Once Delivery

At-least-once delivery is the workhorse guarantee behind most serious IBM MQ installations: messages should survive queue manager restarts and consumer failures, and if processing does not finish cleanly, MQ makes the work available again. Duplicates are the price. Enterprise payments, supply chain, and mainframe batch bridges rely on this model plus idempotent applications. This page explains how persistence and logging prevent loss, how syncpoint on MQGET creates the redelivery window, how backout counts and poison messages interact with retries, what channel restart implies for cross-site delivery, and how architects document at-least-once honestly while aiming for exactly-once business outcomes upstream in the exactly-once tutorial.

The At-Least-Once Contract

Producers promise: after a successful persistent put and commit, the message will exist until a consumer removes it with a committed get (subject to expiry and administrative actions). Consumers promise: they will use syncpoint so a failure before commit does not silently delete work. MQ promises: restart recovery from logs for persistent data. None of that prevents the same message from being seen twice after a crash between processing and commit—that is still within the contract.

Components that enable at-least-once
ComponentRole in at-least-once
MQPER_PERSISTENT / DEFPSIST(YES)Survive QM restart
Log files / z/OS log streamsRecovery media
Syncpoint on GETHold message until commit or backout
MQCMITRemove message atomically with other UoW resources
MQBACKReturn message for retry
BOTHRESH / BOQNAMEEscalate poison messages after repeated backouts

Producer Side: Put and Commit

Applications can MQPUT under syncpoint with a database update in the same global transaction. If MQBACK rolls back, the message never appears on the queue for other consumers. If MQCMIT succeeds, the message is durable. Put without syncpoint still creates a persistent message once the put completes successfully—the boundary is whether the put itself can roll back with other work. Batch jobs often put thousands of messages then commit once per batch for efficiency, understanding that a crash mid-batch may require reconciliation.

Consumer Side: Get, Process, Commit

Under syncpoint, MQGET with appropriate options makes the message unavailable to other consumers until commit or backout. Process business logic, update Db2 on z/OS or distributed database, then MQCMIT. If processing throws, MQBACK returns the message and BackoutCount may increment. A second worker performing the same logic must not assume first-time-only delivery—use natural keys, status columns, or deduplication tables.

Channels and At-Least-Once Across Sites

Persistent messages on transmission queues survive sender channel outages. When the channel runs again, forwarding resumes—at-least-once across the network hop. If the receiver channel fails after the partner thinks delivery completed, partner-specific recovery and DLQ handling apply; operations monitor XMITQ depth and channel in-doubt states. Non-persistent cross-site traffic weakens the guarantee to at-most-once for that segment.

Poison Messages and Backout

At-least-once retry is painful when the message is malformed. Each backout requeues until BOTHRESH triggers movement to the backout queue (BOQNAME) or manual intervention. Without thresholds, one bad message blocks a queue forever while consumers spin. Configure thresholds, monitor backout queues, and route to dead-letter queues for human repair—still at-least-once philosophy, but bounded retry.

Idempotency: Required Companion Pattern

  • Detect duplicate MsgId or business key before side effects.
  • Use upsert semantics instead of blind insert.
  • Store processing state: RECEIVED, PROCESSING, DONE.
  • Make downstream puts conditional on state transition.

Tutorial: MQGET Options Concept

text
1
2
3
4
5
6
7
8
9
10
Consumer loop (conceptual): MQBEGIN or implicit syncpoint MQGET with MQGMO_SYNCPOINT validate payload update database MQCMIT -> message removed, DB committed (XA if coordinated) On validation failure: MQBACK -> message redelivered, BackoutCount may increase if BackoutCount > BOTHRESH -> message to backout queue

Explain Like I'm Five: At-Least-Once

The teacher gives you a worksheet. If you drop your pencil and have not handed it in yet, you still have the worksheet on your desk to try again. You might finish the same worksheet twice if you forgot you already did question 1—so you check your answers at the top before starting again. MQ keeps the worksheet; you must not double-count stars on the chart.

Practice Exercises

Exercise 1: Trace Backout

BackoutCount is 3, BOTHRESH is 5. What happens on the next two failures? What should operations watch?

Exercise 2: Idempotent Design

Order message ORDER-77 arrives twice. Describe a status column pattern that makes the second get harmless.

Exercise 3: Cross-Site

XMITQ depth grows during WAN outage with persistent messages. After channel restart, could duplicates appear at the remote? Explain.

Frequently Asked Questions

Frequently Asked Questions

Test Your Knowledge

Test Your Knowledge

1. Persistent message + syncpoint get + crash before MQCMIT usually means:

  • Message lost forever
  • Message available for redelivery
  • Queue deleted
  • Channel stops permanently

2. To reduce duplicate business effects you should:

  • Disable logging
  • Use idempotent consumers
  • Use only non-persistent
  • Set MAXDEPTH(1)

3. BackoutCount increases when:

  • Message is committed
  • Get is backed out without commit
  • Queue is empty
  • Channel is BINDING

4. At-least-once pairs best with:

  • Commit get before processing
  • Process then commit under syncpoint
  • Never use persistence
  • Ignore MsgId
Published
Read time15 min
AuthorMainframeMaster
Verified: IBM MQ 9.3 documentation