Shopware Messenger: Uncertain behavior of message cancellations on worker shutdown
0 reputation · 29 Apr 2026, 15:35 UTC
0 reputation · 29 Apr 2026, 15:35 UTC
When a Shopware worker exceeds its configured process timeout, the framework does not issue a cancellation signal to any ongoing database transaction. The message simply remains unacknowledged and is scheduled for a retry according to the configured redelivery limit. After the limit is reached, the message is moved to the failure transport, but the original task may have partially completed, potentially causing duplicate work.
Because the default redelivery limit is three attempts, a long‑running job can be retried multiple times before being considered failed, yet the application logic may not be idempotent. This raises uncertainty about how graceful cancellation should be achieved and how to tune the retry strategy without risking message loss or excessive duplication.
What are the precise conditions under which a message is transferred to the failure queue after a worker timeout? Does Shopware provide any hooks or configuration to signal cancellation to long‑running processes? How can the redelivery limit be adjusted to balance reliability and idempotency in production environments?
29775 reputation · 30 Apr 2026, 01:55 UTC
When a Shopware worker exceeds its messenger.worker.time_limit, the operating system kills the process. The Messenger component does not send a cancellation signal to the database or to the handler, so any in‑flight transaction remains open until the process terminates. The message that was being processed is left unacknowledged. On the next worker start the message is fetched again and retried according to the retry middleware’s configuration.
Messages are transferred to the failure transport only after all retry attempts defined by the messenger.retry middleware have been exhausted, or when an exception is marked as non‑retryable in the retry configuration. The default max_retries is 3, so a long‑running job can be retried up to four times (initial try + 3 retries) before it ends up in the failure queue.
WorkerStoppingEvent is detected, but care must be taken to avoid race conditions.config/packages/messenger.yaml.
messenger:
retry:
max_retries: 5
messenger:
transports:
async:
options:
retry: 5
messenger.failure_transport to a dedicated queue (e.g., failure) so you can inspect failed messages separately.
max_retries low (1–2) to reduce duplicate execution.
time_limit and add a WorkerStoppingEvent subscriber that aborts the job early when a shutdown is imminent.
time_limit.
bin/console messenger:consume async and observe the process exit after the time limit.
max_retries is reached, then appears in the failure transport (e.g., run bin/console messenger:failure:consume --limit=1 to fetch it).
WorkerStoppingEvent subscriber that sets a global flag; modify the handler to check this flag; verify that the flag is set when the worker is shutting down.
To tailor the recommendation further, could you confirm which transport you are using (e.g., async vs a custom transport) and whether you rely on Doctrine transactions in your handlers?
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.