---
id: WF-MBR-MEM-024
title: Generate and publish a monthly membership snapshot
trigger: >-
  The snapshot planner and dispatcher admit a scheduled or requested monthly
  run.
product_area: membership
module: memberships
revision: 1
status: draft
design_intent: proposed
implementation_evidence: partially-observed
inference: []
source_sha:
  services-membership: 5994c270e8a37a30f848e99ba5b5ee6b87c08893
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
implements:
  - CAP-MBR-MEM-019
moves:
  - STATE-MBR-MEM-012
crosses:
  - SVC-MBR-MEM-snapshots
  - SVC-MBR-MEM-history
idempotency: >-
  The run’s date and recording instant drive reconstruction. Existing captured
  contact characteristics are retained for equivalent reruns; tested member,
  affiliation and count rows reproduce.
concurrency: >-
  Planner and dispatcher each use reserved concurrency one, and the dispatcher
  claim uses an owner advisory lock. The generation transaction publishes
  atomically.
hops:
  - 'n': 1
    actor_or_service: Snapshot planner
    action: 'Plan due monthly runs, provision the monthly partition and nudge dispatch.'
    anchor: 'services-membership:modules/snapshots/aws/lambda/PLANNER.ts'
    seam: schedule
    on_failure: Retry planning on a subsequent scheduled pass.
    left_inconsistent: The unplanned month remains unavailable as a new publication.
    observer: Planner execution logs and alarms
    provenance: observed
    source: >-
      services-membership:modules/snapshots/aws/logic/snapshot-functions.lambda.ts
  - 'n': 2
    actor_or_service: Snapshot dispatcher
    action: >-
      Claim admissible planned runs under the configured cap and request their
      execution jobs.
    anchor: 'services-membership:modules/snapshots/aws/lambda/DISPATCHER.ts'
    seam: schedule
    on_failure: A later dispatch pass can retry admission of eligible planned work.
    left_inconsistent: Unadmitted work remains in the planned ledger state.
    observer: Snapshot run ledger
    provenance: observed
    source: >-
      services-membership:modules/snapshots/aws/logic/snapshot-functions.lambda.ts
  - 'n': 3
    actor_or_service: Snapshot run job
    action: >-
      Reconstruct and insert member, dated unit ancestry, selected
      characteristic and movement-count rows in one transaction.
    anchor: >-
      services-membership:modules/snapshots/services/types/membership-snapshot.ts:membershipSnapshot
    seam: state_machine
    on_failure: >-
      Abort generation without publication; the ledger schedules bounded
      back-off retries.
    left_inconsistent: The previous published version remains current.
    observer: Ledger attempt status and final-failure alarm
    provenance: test
    source: >-
      services-membership:modules/snapshots/tests/integration/snapshot-pipeline.integration.spec.ts#captures
      nothing recorded after the month’s end
  - 'n': 4
    actor_or_service: Snapshot run job
    action: >-
      Validate grouped totals, type references, independent counts and
      affiliation ownership before publication.
    anchor: >-
      services-membership:modules/snapshots/services/generation/membership-snapshot-checks.ts:membershipSnapshotChecks
    seam: state_machine
    on_failure: A failed validation prevents publication of this version.
    left_inconsistent: No partial local change remains.
    observer: Snapshot run ledger
    provenance: test
    source: >-
      services-membership:modules/snapshots/tests/integration/membership-snapshot.integration.spec.ts#fails
      the run on the counts check, publishes nothing
  - 'n': 5
    actor_or_service: Snapshot run job
    action: Confirm publication and settle the run job.
    anchor: >-
      services-membership:modules/snapshots/services/runs/snapshot-run-workflow.ts:ensureSnapshotRunJobTypeRegistered
    seam: state_machine
    on_failure: Record the failure in the job outcome.
    left_inconsistent: No partial local change remains.
    observer: Durable execution record
    provenance: observed
    source: >-
      services-membership:modules/snapshots/services/runs/snapshot-run-workflow.ts
      (header)
branches:
  - >-
    Initial latest-month capture reads current contact characteristics; older
    backfills without a publication have no captured values.
waits:
  - >-
    Scheduled reconstruction uses the exclusive local month-end instant
    regardless of the later execution time.
evidence:
  - >-
    services-membership at 5994c270: modules/snapshots (services, aws/logic,
    aws/snapshots.module.ts); docs/migrations/history/README.md
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-001, 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]
---

# Generate and publish a monthly membership snapshot

## What It Does

Monthly generation builds member, affiliation, characteristic and count datasets at the run’s recording instant. Validation gates publication of a complete version.

## The Flow

```mermaid
flowchart TD
  H1["Plan due monthly runs, provision the monthly partition and nudge dispatch"]
  H2["Claim admissible planned runs under the configured cap and request their execution jobs"]
  H1 --> H2
  H3["Reconstruct and insert member, dated unit ancestry, selected characteristic and movement-count rows in one transaction"]
  H2 --> H3
  H4["Validate grouped totals, type references, independent counts and affiliation ownership before publication"]
  H3 --> H4
  H5["Confirm publication and settle the run job"]
  H4 --> H5
```

## When Something Fails

Failed generation preserves the prior current version and uses the ledger retry policy. Blank captured characteristics and migration-time reconstruction have existing findings. The single generation transaction creates a scaling concern, without establishing a measured maximum customer size.
