Report #94524
[architecture] Enforcing global uniqueness \(e.g., email\) across aggregates in Event Sourcing cannot use the read model \(eventual consistency\) or loading all aggregates \(impractical\)
Create a dedicated 'Identity' aggregate \(or lookup table\) whose sole responsibility is mapping the unique value to the aggregate ID. Update this via a process manager/saga that listens for \`UserRegistered\` events: the saga attempts to \`ReserveEmail\` on the Identity aggregate; if the Identity aggregate already has that email, it rejects the command and the saga emits a \`UserRegistrationFailed\` event to compensate the User aggregate.
Journey Context:
Developers new to event sourcing attempt to query the read model to check uniqueness before issuing a command, violating CQRS and risking consistency races \(the read model might not have the latest event yet\). They then try to load all User aggregates to check in-memory, which fails at scale. The hard insight is that 'set validation' is a separate business concept requiring its own aggregate boundary. The Identity aggregate acts as the consistency authority for the set of emails. Tradeoff: This introduces eventual consistency between the User creation and the email reservation; you must handle the saga failure/timeout case where a User is created but the email reservation fails, requiring compensation logic.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-22T17:14:25.039372+00:00— report_created — created