---
id: ADR-CRM-ENT-005
title: Records Commit Before Their Reactions
product_area: crm
module: entities
revision: 1
status: proposed
design_intent: confirmed
source_sha:
  services-crm: 7ea48a414c42eade10d60753b8bcc323b1dd726f
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
decision: >-
  Contact and organization aggregate writes commit with database-captured change
  events; independent handlers react after commit with at-least-once delivery;
  reconciliation handlers reread current data, while search forwards captured
  snapshots.
constrains:
  - SVC-CRM-ENT-entities
  - DOM-CRM-ENT-001
  - DOM-CRM-ENT-002
  - WF-CRM-ENT-002
  - WF-CRM-ENT-004
  - WF-CRM-ENT-011
  - RESP-CRM
origin: >-
  Andrew, 2026-10-09 (change events replace the shared outbox; one event per
  record per save; the SQS hop kept), cited in
  services-crm:docs/change-events.md
alternatives:
  - option: Run every reaction inside the record transaction.
    why_not: >-
      That would expose ordinary saves to remote-service latency and unrelated
      handler failures.
  - option: Maintain a separate handwritten outbox topic for each reaction.
    why_not: >-
      The retired approach required repeated trigger and topic work and could
      omit a write path. Shared capture registers handlers independently.
consequences:
  - 'A committed record can precede updated compliance, region or search results.'
  - >-
    Failed handler deliveries reach a dead-letter queue after five receives
    without a record-screen notification.
  - >-
    Reconciliation owns current-state repair, while Platform owns stale or
    repeated search-snapshot handling.
evidence:
  - 'services-crm at 7ea48a41: docs/change-events.md; aws/crm.change-events.ts'
  - 'services-platform at ad3f6a65: docs/queued-work.md'
---
# Records Commit Before Their Reactions

## Context

The approved change-event architecture separates a successful aggregate save from its projections and follow-on work. Database capture covers the record and children, while the queue owns delivery and retry.

## Decision

Contact and organization aggregate writes commit with database-captured change events; independent handlers react after commit with at-least-once delivery; reconciliation handlers reread current data, while search forwards captured snapshots.

## Alternatives Considered

Run every reaction inside the record transaction. That would expose ordinary saves to remote-service latency and unrelated handler failures.

Maintain a separate handwritten outbox topic for each reaction. The retired approach required repeated trigger and topic work and could omit a write path. Shared capture registers handlers independently.

## Consequences

Each handler receives its own message. Failure in one projection does not rerun another successful handler or reverse the original save. Current-state reconciliation and snapshot indexing are different contracts, and the design identifies which one each handler uses.

A committed record can precede updated compliance, region or search results. Failed handler deliveries reach a dead-letter queue after five receives without a record-screen notification. Reconciliation owns current-state repair, while Platform owns stale or repeated search-snapshot handling.
