---
id: WF-PFM-NOT-005
title: Deliver queued chat and text deliveries
trigger: Due channel work reaches dispatch and a channel queue.
product_area: platform
module: notifications
revision: 1
status: draft
design_intent: proposed
implementation_evidence: partially-observed
inference: []
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
implements:
- CAP-PFM-NOT-007
- CAP-PFM-NOT-008
moves:
- STATE-PFM-NOT-005
- STATE-PFM-NOT-003
crosses:
- SVC-PFM-NOT-notifications
hops:
- n: 1
  actor_or_service: Notifications dispatcher
  action: Claim due channel work, publish delivery items and delete acknowledged work rows.
  anchor: services-platform:modules/notifications/services/dispatch/dispatch-notifications.ts:dispatchNotifications
  seam: schedule
  on_failure: Leave failed dispatch for a later run.
  left_inconsistent: A lost item after deletion can leave queued delivery without dispatch work.
  observer: The nightly sweep repairs work missing for over an hour.
  provenance: observed
  source: services-platform:modules/notifications/services/reconcile/reconcile-tenant.ts:reconcileTenant
- n: 2
  actor_or_service: Chat delivery consumer
  action: Check queued state, notice applicability and request expiry; terminate withdrawn or expired
    work.
  anchor: services-platform:modules/notifications/services/dispatch/deliver-delivery.ts:deliverQueuedDelivery
  seam: queue
  on_failure: Acknowledge work that is already terminal.
  left_inconsistent: No additional sending for the rejected item.
  observer: Delivery history.
  provenance: test
  source: services-platform:modules/notifications/tests/integration/services/dispatch/deliver-delivery.integration.spec.js#cancels,
    not sends, a delivery whose notification was superseded after it was queued
- n: 3
  actor_or_service: Chat delivery consumer
  action: Conditionally claim queued delivery as sending and refresh notice progress.
  anchor: services-platform:modules/notifications/services/persistence/deliveries.ts:transitionDelivery
  seam: sync
  on_failure: A lost claim acknowledges without sending.
  left_inconsistent: A separately failed summary refresh may leave stale notice progress.
  observer: Claim outcome logs.
  provenance: test
  source: services-platform:modules/notifications/tests/integration/services/persistence/deliveries.integration.spec.js#lets
    only one of two consumers racing for the send win it
- n: 4
  actor_or_service: Channel adapter (Rhythm HQ Slack today)
  action: Call the adapter outside the transaction and classify its delivery result.
  anchor: services-platform:modules/notifications/services/channels/channel-adapter.ts
  seam: sync
  on_failure: Treat an exception as retryable; current exception logging can retain raw provider text.
  left_inconsistent: Provider acceptance followed by a crash can leave sending unresolved.
  observer: Reconciliation marks old unresolved sends ambiguous.
  provenance: observed
  source: services-platform:modules/notifications/services/dispatch/deliver-delivery.ts:deliverQueuedDelivery
- n: 5
  actor_or_service: Chat delivery consumer
  action: Persist success and reference, requeue temporary failure with delay, or fail permanent and exhausted
    work; return final-receive failure for dead-letter handling.
  anchor: services-platform:modules/notifications/services/dispatch/deliver-delivery.ts:deliverQueuedDelivery
  seam: queue
  on_failure: Retry the received item if outcome processing fails.
  left_inconsistent: Delivery outcome can commit before a later notice-summary refresh fails.
  observer: Delivery latency and outcome metrics, HQ failure alarm and dead-letter monitoring.
  provenance: test
  source: services-platform:modules/notifications/tests/integration/services/dispatch/deliver-delivery.integration.spec.js#fails
    the delivery attempts_exhausted on the last receive and gives the item back at once to reach the dead-letter
    queue
idempotency: Expected queued state permits one send claim; repeated items for other states do no further
  sending.
concurrency: Channel processing uses four-way item concurrency with one reserved function slot; withdrawal
  can race with a claim.
branches:
- Unknown adapters produce terminal skips.
- Missing Slack credentials or mappings skip with limited warnings.
- The text queue currently has no consumer.
waits:
- Temporary failures use thirty-second exponential backoff, thirty-minute cap and twenty-percent jitter,
  respecting longer provider delays.
evidence:
- 'services-platform at ad3f6a65: modules/notifications/services/dispatch/deliver-delivery.ts; services/channels/**;
  aws/lambda/DELIVER_CHAT.handler.ts; aws/logic/notifications-functions.lambda.ts.'
controls: [TC-AVL-001, TC-AVL-004, TC-AVL-005, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-CHG-001, TC-CHG-002, TC-CHG-003, TC-CHG-004, TC-CHG-005, TC-CHG-006, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-DAT-004, TC-IAM-001, TC-IAM-002, TC-IAM-004, TC-IAM-005, TC-IAM-006, TC-LOG-001, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-MON-001, TC-MON-002, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-PRV-001, TC-PRV-002, TC-PRV-004, TC-SEC-001, TC-SEC-002, TC-SEC-003, TC-SEC-004, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-TEN-004, TC-VEN-001, TC-VEN-002, TC-VEN-003]
---
# Deliver queued chat and text deliveries

## What It Does

Due channel work reaches dispatch and a channel queue.

## The Flow

```mermaid
flowchart TD
    h0["Claim due channel work, publish delivery items and delete acknowledged work rows"]
    h1["Check queued state, notice applicability and request expiry"]
    h0 --> h1
    h2["Conditionally claim queued delivery as sending and refresh notice progress"]
    h1 --> h2
    h3["Call the adapter outside the transaction and classify its delivery result"]
    h2 --> h3
    h4["Persist success and reference, requeue temporary failure with delay, or fail permanent and exhausted work"]
    h3 --> h4
```

## When Something Fails

The hop rows identify each retry boundary, any state left behind and the available observer. Expected queued state permits one send claim; repeated items for other states do no further sending. Channel processing uses four-way item concurrency with one reserved function slot; withdrawal can race with a claim.

## Open Design Questions

Unknown adapters produce terminal skips. Missing Slack credentials or mappings skip with limited warnings. The text queue currently has no consumer. Temporary failures use thirty-second exponential backoff, thirty-minute cap and twenty-percent jitter, respecting longer provider delays.
