---
id: WF-PFM-NOT-007
title: Reconcile and trim notification records nightly
trigger: The nightly scheduler runs at 03:40 UTC.
product_area: platform
module: notifications
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
inference: []
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
implements:
- CAP-PFM-NOT-008
- CAP-PFM-NOT-006
moves:
- STATE-PFM-NOT-002
- STATE-PFM-NOT-003
- STATE-PFM-NOT-005
crosses:
- SVC-PFM-NOT-notifications
hops:
- n: 1
  actor_or_service: Reconcile scheduler
  action: Start a reconciliation job for each operational workspace using the workspace and UTC date identity.
  anchor: services-platform:modules/notifications/services/reconcile/submit-nightly-reconcile.ts:submitNightlyNotificationReconciles
  seam: schedule
  on_failure: Log a workspace scheduling error and continue.
  left_inconsistent: An omitted workspace waits for a later nightly run.
  observer: Scheduler heartbeat and two-day silence alarm.
  provenance: observed
  source: services-platform:modules/notifications/services/reconcile/submit-nightly-reconcile.ts:submitNightlyNotificationReconciles
- n: 2
  actor_or_service: Reconcile job (state machine, one reconciling step)
  action: Fail sends unresolved beyond fifteen minutes and recreate missing work for channels queued longer
    than an hour.
  anchor: services-platform:modules/notifications/services/reconcile/reconcile-tenant.ts:reconcileTenant
  seam: state_machine
  on_failure: Fail the job and leave remaining repeatable work for a later run.
  left_inconsistent: Unrepaired deliveries stay stuck until reconciliation succeeds.
  observer: Stuck-work counters and state-machine failure alarm.
  provenance: test
  source: services-platform:modules/notifications/tests/integration/services/reconcile/reconcile-tenant.integration.spec.js#settles
    a delivery left sending past the ambiguity window failed ambiguous, and the instance with it, never
    resending
- n: 3
  actor_or_service: Reconcile job
  action: Convert expired producer entries into expired outcomes, then expire accepted unsent deliveries
    and settle requests with no active work.
  anchor: services-platform:modules/notifications/services/reconcile/reconcile-tenant.ts:reconcileTenant
  seam: state_machine
  on_failure: Fail the job for later repeatable processing.
  left_inconsistent: Requests can remain open past their deadline.
  observer: Request outcomes in History.
  provenance: test
  source: services-platform:modules/notifications/tests/integration/services/reconcile/reconcile-tenant.integration.spec.js#settles
    a request past its expiry whose notification was delivered, so a late cancel reaches nothing
- n: 4
  actor_or_service: Reconcile job
  action: Delete retained operational rows older than thirteen months and challenges more than a day past
    expiry in bounded batches.
  anchor: services-platform:modules/notifications/services/persistence/retentions.ts:deleteRecordsPastRetention
  seam: state_machine
  on_failure: Fail the job and retain remaining rows until another run.
  left_inconsistent: Older records remain temporarily.
  observer: Reconciliation duration metric.
  provenance: test
  source: services-platform:modules/notifications/tests/integration/services/reconcile/reconcile-tenant.integration.spec.js#deletes
    requests, deliveries, events, instance keys and challenges past it and keeps what is younger
- n: 5
  actor_or_service: Partition maintenance (Operations)
  action: Maintain thirteen months of notice partitions and prepare two future months.
  anchor: services-platform:modules/notifications/notifications.settings.ts:NOTIFICATION_INSTANCE_RETENTION_MONTHS
  seam: schedule
  on_failure: Missing-partition inserts fail and queue processing retries.
  left_inconsistent: New notice creation can be blocked until partition maintenance succeeds.
  observer: Partition maintenance checks.
  provenance: documented
  source: services-platform:docs/notifications.md#6. The pipeline
idempotency: Workspace-and-date job identity and bounded repeatable cleanup support later recovery.
concurrency: Reconciliation runs beside live processing using conditional settlement and expiry updates.
branches:
- The reserved system workspace participates when operational.
- Identity refresh work reports zero while channel identities remain dormant.
waits:
- Settlement can lag request expiry until a successful nightly run.
evidence:
- 'services-platform at ad3f6a65: modules/notifications/services/reconcile/*.ts; services/persistence/retentions.ts;
  aws/logic/notifications-reconcile.*.ts; docs/notifications.md §6 and §7; docs/jobs.md (job families).'
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-CHG-007, 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-002, TC-LOG-003, 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-TEN-001, TC-TEN-002, TC-TEN-003, TC-TEN-004, TC-VEN-001, TC-VEN-002, TC-VEN-003]
---
# Reconcile and trim notification records nightly

## What It Does

The nightly scheduler runs at 03:40 UTC.

## The Flow

```mermaid
flowchart TD
    h0["Start a reconciliation job for each operational workspace using the workspace and UTC date identity"]
    h1["Fail sends unresolved beyond fifteen minutes and recreate missing work for channels queued longer than an hour"]
    h0 --> h1
    h2["Convert expired producer entries into expired outcomes, then expire accepted unsent deliveries and settle requests "]
    h1 --> h2
    h3["Delete retained operational rows older than thirteen months and challenges more than a day past expiry in bounded b"]
    h2 --> h3
    h4["Maintain thirteen months of notice partitions and prepare two future months"]
    h3 --> h4
```

## When Something Fails

The hop rows identify each retry boundary, any state left behind and the available observer. Workspace-and-date job identity and bounded repeatable cleanup support later recovery. Reconciliation runs beside live processing using conditional settlement and expiry updates.

## Open Design Questions

The reserved system workspace participates when operational. Identity refresh work reports zero while channel identities remain dormant. Settlement can lag request expiry until a successful nightly run.
