---
id: WF-MBR-MEM-008
title: Sweep the status cache every night
trigger: 'The local-midnight schedule is delivered, or staff request an immediate sweep.'
product_area: membership
module: memberships
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
inference: []
source_sha:
  services-membership: 5994c270e8a37a30f848e99ba5b5ee6b87c08893
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
implements:
  - CAP-MBR-MEM-005
  - CAP-MBR-MEM-020
moves:
  - STATE-MBR-MEM-001
  - STATE-MBR-MEM-013
crosses:
  - SVC-MBR-MEM-memberships
  - SVC-MBR-MEM-events
idempotency: >-
  Detection uniqueness prevents duplicate lifecycle and lapse events when a day
  is swept repeatedly.
concurrency: >-
  Each membership is locked in a separate short transaction, so concurrent term
  writes serialize with that membership’s refresh.
hops:
  - 'n': 1
    actor_or_service: Schedule dispatcher
    action: Claim a due workspace occurrence through the schedule dispatcher.
    anchor: 'services-membership:modules/memberships/aws/lambda/SCHEDULE_DISPATCHER.ts'
    seam: schedule
    on_failure: A later dispatcher pass can claim due work that was not admitted.
    left_inconsistent: List caches can remain outdated before occurrence execution.
    observer: Dispatch execution logs
    provenance: observed
    source: >-
      services-membership:modules/memberships/services/sweep/status-sweep-schedule.ts:statusSweepScheduleDefinition
  - 'n': 2
    actor_or_service: Schedule consumer
    action: Invoke the sweep with the occurrence’s business date in the consumer.
    anchor: 'services-membership:modules/memberships/aws/lambda/SCHEDULE_CONSUMER.ts'
    seam: queue
    on_failure: >-
      Schedule failure handling retries due work and can pause it after repeated
      failures.
    left_inconsistent: >-
      Affected list caches stay stale, but computed rights do not depend on
      them.
    observer: Occurrence result and schedule pause state
    provenance: observed
    source: >-
      services-membership:modules/memberships/aws/lambda/SCHEDULE_CONSUMER.ts:STATUS_SWEEP_AUTO_PAUSE_AFTER_FAILURES
  - 'n': 3
    actor_or_service: Memberships service
    action: >-
      Select boundary holdings or all holdings when prior sweep history requires
      catch-up.
    anchor: >-
      services-membership:modules/memberships/services/sweep/status-sweep.ts:sweepTenant
    seam: sync
    on_failure: Abort selection and report failure for scheduled retry.
    left_inconsistent: No membership refresh has committed at this selection stage.
    observer: Completed sweep record
    provenance: test
    source: >-
      services-membership:modules/memberships/tests/integration/services/status-sweep.integration.spec.ts#catches
      up after a missed night, recomputing every membershi
  - 'n': 4
    actor_or_service: Memberships service
    action: >-
      Lock and recompute each holding, record new detections and publish the
      first lapse event.
    anchor: >-
      services-membership:modules/memberships/services/membership-caches.ts:recomputeMembershipCache
    seam: sync
    on_failure: Roll back this holding’s refresh and stop the failed sweep for retry.
    left_inconsistent: >-
      Previously refreshed holdings retain their caches while later holdings
      await retry.
    observer: Lifecycle entries and published event log
    provenance: test
    source: >-
      services-membership:modules/memberships/tests/integration/services/status-sweep.integration.spec.ts#records
      lapsed_detected effective the day after grace ended
  - 'n': 5
    actor_or_service: Memberships service
    action: 'Record sweep completion and its examined, changed and detected totals.'
    anchor: >-
      services-membership:modules/memberships/services/persistence/status-sweeps.ts:recordSweep
    seam: sync
    on_failure: Missing completion history causes a later sweep to use catch-up selection.
    left_inconsistent: >-
      Without the completion record, the next qualifying pass can refresh every
      holding.
    observer: Completed sweep record
    provenance: observed
    source: >-
      services-membership:modules/memberships/services/persistence/status-sweeps.ts:recordSweep
branches:
  - >-
    Staff-triggered sweeping uses the same implementation with the current
    business date.
  - >-
    The dispatcher also checks the daily idempotency-purge window near 03:00
    UTC.
waits:
  - >-
    The local-midnight occurrence is discovered through minute polling rather
    than a strict latency guarantee.
evidence:
  - >-
    services-membership at 5994c270: modules/memberships/services/sweep/*.ts;
    aws/lambda/SCHEDULE_*.ts; modules/terms/services/sweep.ts;
    aws/membership.idempotency.ts
controls: [TC-AVL-002, TC-AVL-003, TC-AVL-004, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-005, TC-AZ-006, TC-CHG-001, TC-CHG-002, TC-CHG-003, TC-CHG-004, TC-CRY-001, TC-CRY-002, TC-CRY-003, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-DAT-007, TC-IAM-001, TC-IAM-002, TC-IAM-004, TC-IAM-005, TC-IAM-006, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-MON-001, TC-MON-002, TC-MON-004, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-PRV-001, TC-PRV-002, TC-SEC-001, TC-SEC-004, TC-TEN-001, TC-TEN-002, TC-TEN-003]
---

# Sweep the status cache every night

## What It Does

The nightly sweep refreshes list caches at period and grace boundaries. It records expiry and lapse detection once and publishes a termination event for a newly detected lapse.

## The Flow

```mermaid
flowchart TD
  H1["Claim a due workspace occurrence through the schedule dispatcher"]
  H2["Invoke the sweep with the occurrence’s business date in the consumer"]
  H1 --> H2
  H3["Select boundary holdings or all holdings when prior sweep history requires catch-up"]
  H2 --> H3
  H4["Lock and recompute each holding, record new detections and publish the first lapse event"]
  H3 --> H4
  H5["Record sweep completion and its examined, changed and detected totals"]
  H4 --> H5
```

## When Something Fails

A mid-sweep error preserves completed memberships and leaves later ones stale until retry. A missing prior night triggers a full recomputation. Schedule failure handling can pause repeated failing work; rights continue to use computed standing.

## Open Design Questions

Termination delivery for a late detection uses the expired term’s last day, rather than when the sweep noticed it.
