configuration/principle/data/event.data.json

configuration/principle/data/event.data.json is a file in GovLab Context. 728 lines of code and 0 definitions.

{
    "category": "Event / Messaging / Asynchronous Architecture",
    "check": {
        "population": "every event, message, topic and consumer that crosses an asynchronous boundary",
        "freshness": "a verdict stands until an event schema, a consumer or the delivery guarantee changes",
        "refusal": "the schema registry, idempotency test or workflow test fails the change that breaks delivery or contract",
        "observation": "published schemas, consumer registrations, and redelivery, lag and dead-letter counts from the broker",
        "evidence": "none: the catalog states this check as a class, so a watched run belongs to each system that adopts it",
        "authority": "the published schema and the delivery guarantee, which every producer and consumer conforms to"
    },
    "records": [
        {
            "id": "event-driven-architecture",
            "name": "Event-Driven Architecture",
            "aliases": ["EDA"],
            "definition": "A convention of connecting services through published events, with each consumer reacting independently of the producer.",
            "type": "style",
            "scope": [
                "service",
                "integration",
                "system"
            ],
            "requires": [
                "Events",
                "Message Contract",
                "Idempotency"
            ],
            "reinforces": [
                "Loose Coupling",
                "Asynchronous Communication"
            ],
            "enables": [
                "Event Sourcing",
                "CQRS",
                "Saga"
            ],
            "conflicts_with": ["Hidden Temporal Coupling"],
            "tensions_with": [
                "Debuggability",
                "Strong Consistency"
            ],
            "violated_by": [
                "lexicon:non-idempotent-operation",
                "lexicon:ad-hoc-payloads"
            ],
            "detected_by": [
                "missing correlation IDs",
                "direct synchronous chains"
            ],
            "measured_by": [
                "event contract coverage",
                "retry safety"
            ],
            "refactored_by": [
                "architecture:domain-events",
                "architecture:outbox-pattern",
                "lexicon:consumer-driven-contract-tests"
            ],
            "enforced_by": [
                "schema registry",
                "idempotency tests"
            ],
            "severity": "contextual",
            "exemplar": {
                "before": "async function createFoo(foo: Foo) {\n  await fooStore.save(foo);\n  await barService.refresh(foo.id);\n  await bazService.notify(foo.id);\n}",
                "after": "async function createFoo(foo: Foo) {\n  await fooStore.save(foo);\n  await events.publish({ type: \"FooCreated\", fooId: foo.id });\n}\nevents.on(\"FooCreated\", updateBarProjection);\nevents.on(\"FooCreated\", notifyBaz);",
                "lang": "ts"
            }
        },
        {
            "id": "publish-subscribe-pattern",
            "name": "Publish/Subscribe Pattern",
            "aliases": ["Pub/Sub"],
            "definition": "A design pattern in which publishers send messages to a topic and every subscriber to that topic receives them.",
            "type": "pattern",
            "scope": [
                "integration",
                "eventing"
            ],
            "requires": [
                "Publisher",
                "Subscriber",
                "Broker/Event Bus"
            ],
            "reinforces": ["Loose Coupling"],
            "enables": ["Fan-Out Notification"],
            "conflicts_with": ["Direct Point-to-Point Calls"],
            "tensions_with": ["Delivery Ordering"],
            "violated_by": ["lexicon:point-to-point-coupling"],
            "detected_by": ["direct calls to subscriber list"],
            "measured_by": ["publisher-subscriber coupling"],
            "refactored_by": ["architecture:event-bus"],
            "enforced_by": ["messaging contracts"],
            "severity": "contextual",
            "exemplar": {
                "before": "function saveFoo(foo: Foo) {\n  fooStore.save(foo);\n  auditFoo(foo);\n  indexFoo(foo);\n}",
                "after": "publisher.publish(\"foo.saved\", { fooId: foo.id });\nsubscriber.on(\"foo.saved\", auditFoo);\nsubscriber.on(\"foo.saved\", indexFoo);",
                "lang": "ts"
            }
        },
        {
            "id": "message-queue",
            "distinctFrom": [
                {
                    "id": "lexicon:consumer",
                    "reason": "A message queue holds messages until they are acknowledged, while the consumer is the component that takes and processes them."
                }
            ],
            "name": "Message Queue",
            "definition": "A mechanism that holds messages durably until a consumer takes and acknowledges each one.",
            "type": "mechanism",
            "scope": [
                "integration",
                "async processing"
            ],
            "requires": [
                "Message Contract",
                "Consumer"
            ],
            "reinforces": [
                "Resilience",
                "Backpressure"
            ],
            "enables": ["Asynchronous Processing"],
            "conflicts_with": ["In-Memory Direct Invocation"],
            "tensions_with": ["Latency"],
            "violated_by": ["architecture:missing-backpressure"],
            "detected_by": ["synchronous blocking chains for async work"],
            "measured_by": [
                "queue depth",
                "retry/dead-letter rates"
            ],
            "refactored_by": ["architecture:competing-consumers"],
            "enforced_by": [
                "infrastructure policy",
                "load tests"
            ],
            "severity": "contextual",
            "exemplar": {
                "before": "for (const foo of foos) await processFoo(foo);",
                "after": "for (const foo of foos) await fooQueue.enqueue({ type: \"ProcessFoo\", foo });\nfooWorker.consume(fooQueue, message => processFoo(message.foo));",
                "lang": "ts"
            }
        },
        {
            "id": "message-broker",
            "name": "Message Broker",
            "definition": "Descriptive data about topics, queues and routing rules, held by an intermediary service that delivers messages between producers and consumers.",
            "type": "artifact",
            "scope": [
                "integration",
                "messaging"
            ],
            "requires": [
                "Message Queue",
                "Routing"
            ],
            "reinforces": [
                "Decoupling",
                "Scalability"
            ],
            "enables": [
                "Pub/Sub",
                "Work Distribution"
            ],
            "conflicts_with": ["Point-to-Point Coupling"],
            "tensions_with": ["Operational Dependency"],
            "violated_by": ["lexicon:direct-point-to-point-calls"],
            "detected_by": ["direct service calls in async workflows"],
            "measured_by": ["broker usage coverage"],
            "refactored_by": ["architecture:message-queue"],
            "enforced_by": ["architecture policy"],
            "severity": "contextual",
            "exemplar": {
                "before": "await fooService.sendToBar(barMessage);\nawait fooService.sendToBaz(bazMessage);",
                "after": "await broker.publish(\"foo.created\", fooMessage, { durable: true });\nbroker.subscribe(\"foo.created\", { group: \"bar-consumer\", ack: \"manual\" }, handleBar);\nbroker.subscribe(\"foo.created\", { group: \"baz-consumer\", ack: \"manual\" }, handleBaz);",
                "lang": "ts"
            }
        },
        {
            "id": "event-bus",
            "name": "Event Bus",
            "definition": "A mechanism that dispatches each emitted event to the handlers registered for its type.",
            "type": "mechanism",
            "scope": [
                "application",
                "integration"
            ],
            "requires": [
                "Event Contract",
                "Subscriber Model"
            ],
            "reinforces": [
                "Pub/Sub",
                "Event-Driven Architecture"
            ],
            "enables": ["Decoupled Event Distribution"],
            "conflicts_with": ["Direct Event Handler Calls"],
            "tensions_with": ["Event Storm / Traceability"],
            "violated_by": ["lexicon:hidden-dependency"],
            "detected_by": ["undocumented subscribers"],
            "measured_by": ["event dependency visibility"],
            "refactored_by": ["architecture:registry-pattern"],
            "enforced_by": ["handler registry validation"],
            "severity": "contextual",
            "exemplar": {
                "before": "fooEditor.onSave = foo => fooView.refresh(foo);\nfooEditor.onDelete = id => fooView.remove(id);",
                "after": "eventBus.emit({ type: \"FooSaved\", foo });\neventBus.emit({ type: \"FooDeleted\", fooId: id });\neventBus.on(\"FooSaved\", event => fooView.refresh(event.foo));",
                "lang": "ts"
            }
        },
        {
            "id": "event-stream",
            "name": "Event Stream",
            "definition": "A mechanism that keeps events in an ordered, replayable log that consumers read from their own offset.",
            "type": "mechanism",
            "scope": [
                "stream processing",
                "integration"
            ],
            "requires": [
                "Ordered Log",
                "Event Schema"
            ],
            "reinforces": ["Streaming Architecture"],
            "enables": [
                "Replay",
                "Continuous Processing"
            ],
            "conflicts_with": ["Mutable State Only"],
            "tensions_with": ["Storage Volume"],
            "violated_by": ["lexicon:non-replayable-processing"],
            "detected_by": [
                "missing offsets",
                "missing event schema"
            ],
            "measured_by": [
                "replay success",
                "lag"
            ],
            "refactored_by": ["lexicon:offset-tracking"],
            "enforced_by": ["stream contract tests"],
            "severity": "contextual",
            "exemplar": {
                "before": "const latest = await fooApi.getCurrentState(fooId);",
                "after": "const stream = fooEvents.stream(fooId);\nfor await (const event of stream) fooProjection.apply(event);",
                "lang": "ts"
            }
        },
        {
            "id": "event-sourcing",
            "distinctFrom": [
                {
                    "id": "architecture:command-query-responsibility-segregation",
                    "reason": "Event sourcing stores state as its events, while CQRS separates the command model from the query model whatever the storage."
                },
                {
                    "id": "architecture:append-only-log",
                    "reason": "Event sourcing rebuilds state by replay, while an append-only log is the storage it replays from."
                },
                {
                    "id": "architecture:domain-events",
                    "reason": "Event sourcing makes events the source of state, while domain events can be published with state stored some other way."
                },
                {
                    "id": "architecture:saga-pattern",
                    "reason": "Event sourcing is how state is stored, while a saga is how a distributed transaction is coordinated."
                }
            ],
            "name": "Event Sourcing",
            "definition": "A design pattern that stores state as the sequence of events that produced it and rebuilds current state by replaying them.",
            "type": "pattern",
            "scope": [
                "domain",
                "persistence"
            ],
            "requires": [
                "Append-Only Log",
                "Domain Events"
            ],
            "reinforces": [
                "Auditability",
                "Temporal Modeling"
            ],
            "enables": [
                "Replay",
                "Historical Reconstruction"
            ],
            "conflicts_with": ["CRUD-Only State Persistence"],
            "tensions_with": ["Query Complexity"],
            "violated_by": ["lexicon:crud-only-state-persistence"],
            "detected_by": ["state changes lacking events"],
            "measured_by": ["event/state consistency"],
            "refactored_by": ["lexicon:query-projection"],
            "enforced_by": ["event append rules"],
            "severity": "contextual",
            "exemplar": {
                "before": "type FooRow = { id: FooId; name: string; status: string };\nawait fooTable.update(foo);",
                "after": "type FooEvent = FooCreated | FooRenamed | FooClosed;\nawait fooEventStore.append(foo.id, foo.uncommittedEvents());\nconst foo = fooEventStore.read(fooId).reduce(applyFooEvent, emptyFoo());",
                "lang": "ts"
            }
        },
        {
            "id": "command-query-responsibility-segregation",
            "distinctFrom": [
                {
                    "id": "architecture:saga-pattern",
                    "reason": "CQRS splits the write model from the read model, while a saga sequences local transactions with compensations."
                }
            ],
            "aliases": ["CQRS"],
            "name": "Command Query Responsibility Segregation (CQRS)",
            "definition": "A design pattern that separates the model that handles commands from the model that answers queries.",
            "type": "pattern",
            "scope": [
                "application",
                "data access"
            ],
            "requires": ["Command/Query Separation"],
            "reinforces": [
                "Scalability",
                "Event Sourcing"
            ],
            "enables": ["Read/Write Model Optimization"],
            "conflicts_with": ["Unified CRUD Model"],
            "tensions_with": ["Eventual Consistency"],
            "violated_by": ["lexicon:unified-crud-model"],
            "detected_by": ["command/query side-effect violations"],
            "measured_by": ["read/write separation compliance"],
            "refactored_by": [],
            "enforced_by": [
                "handler conventions",
                "tests"
            ],
            "severity": "contextual",
            "exemplar": {
                "before": "class FooRepository {\n  save(foo: Foo) {}\n  search(query: string): Foo[] { return complexJoin(query); }\n}",
                "after": "class FooCommandStore { save(foo: Foo) { return fooDb.write(foo); } }\nclass FooQueryStore { search(query: string) { return fooReadModel.search(query); } }\ncommandBus.execute(new SaveFoo(foo));\nqueryBus.execute(new SearchFoos(query));",
                "lang": "ts"
            }
        },
        {
            "id": "domain-events",
            "name": "Domain Events",
            "definition": "A design pattern that records each significant change in the domain as an event named in the domain's language.",
            "type": "pattern",
            "scope": [
                "domain",
                "bounded context"
            ],
            "requires": [
                "Domain Model",
                "Event Semantics"
            ],
            "reinforces": [
                "DDD",
                "Event-Driven Architecture"
            ],
            "enables": ["Decoupled Domain Reactions"],
            "conflicts_with": ["Infrastructure Events in Domain"],
            "tensions_with": ["Event Granularity"],
            "violated_by": ["lexicon:infrastructure-events-in-domain"],
            "detected_by": ["CRUD-named domain events"],
            "measured_by": ["semantic event quality"],
            "refactored_by": ["lexicon:name-the-concept"],
            "enforced_by": ["domain review"],
            "severity": "recommended",
            "exemplar": {
                "before": "class Foo {\n  rename(name: string) { this.name = name; }\n}",
                "after": "class Foo {\n  #events: FooDomainEvent[] = [];\n  rename(name: string) {\n    this.name = name;\n    this.#events.push({ type: \"FooRenamed\", fooId: this.id, name });\n  }\n}",
                "lang": "ts"
            }
        },
        {
            "id": "integration-events",
            "name": "Integration Events",
            "definition": "A design pattern that publishes a versioned public event, mapped from an internal domain event, for consumers outside the service.",
            "type": "pattern",
            "scope": [
                "service boundary",
                "messaging"
            ],
            "requires": [
                "Message Contract",
                "Versioning"
            ],
            "reinforces": ["Interoperability"],
            "enables": ["Cross-Service Communication"],
            "conflicts_with": ["Internal Domain Event Leakage"],
            "tensions_with": ["Duplication with Domain Events"],
            "violated_by": ["lexicon:internal-domain-event-leakage"],
            "detected_by": ["internal event schema published externally"],
            "measured_by": ["boundary event contract coverage"],
            "refactored_by": [],
            "enforced_by": ["event schema review"],
            "severity": "recommended",
            "exemplar": {
                "before": "barService.consume(fooDomainEvent);",
                "after": "const integrationEvent: FooCreatedV1 = {\n  type: \"com.example.foo-created.v1\",\n  fooId: event.fooId,\n  occurredAt: clock.now().toISOString(),\n};\nintegrationBus.publish(integrationEvent);",
                "lang": "ts"
            }
        },
        {
            "id": "asynchronous-communication",
            "name": "Asynchronous Communication",
            "definition": "A design rule that work the caller does not need at once is sent as a message, so the caller does not wait on it.",
            "type": "principle",
            "scope": [
                "service",
                "system"
            ],
            "requires": [
                "Message Contract",
                "Retry Safety"
            ],
            "reinforces": [
                "Resilience",
                "Loose Coupling"
            ],
            "enables": ["Event-Driven Architecture"],
            "conflicts_with": [
                "Blocking Synchronous Chains",
                "Synchronous Chain Trap"
            ],
            "tensions_with": ["Immediate Consistency"],
            "violated_by": ["architecture:synchronous-chain-trap"],
            "detected_by": ["long blocking chains"],
            "measured_by": ["sync dependency depth"],
            "refactored_by": [
                "architecture:message-queue",
                "lexicon:query-projection"
            ],
            "enforced_by": ["architecture review"],
            "severity": "contextual",
            "exemplar": {
                "before": "const bar = await barService.createFromFoo(foo);\nconst baz = await bazService.createFromBar(bar);",
                "after": "await outbox.append({ type: \"FooCreated\", fooId: foo.id });\nreturn { accepted: true, fooId: foo.id };",
                "lang": "ts"
            }
        },
        {
            "id": "eventual-consistency",
            "distinctFrom": [
                {
                    "id": "architecture:causal-consistency",
                    "reason": "Eventual consistency promises only that replicas converge, while causal consistency also promises that no effect is read before its cause."
                }
            ],
            "name": "Eventual Consistency",
            "definition": "A conceptual representation of a consistency guarantee in which replicas and projections converge once updates stop arriving.",
            "type": "model",
            "scope": [
                "distributed system",
                "data"
            ],
            "requires": [
                "Idempotency",
                "Retry",
                "Reconciliation"
            ],
            "reinforces": [
                "Availability",
                "Scalability"
            ],
            "enables": ["Distributed Autonomy"],
            "conflicts_with": [],
            "tensions_with": [
                "User Expectations",
                "Strong Immediate Consistency"
            ],
            "violated_by": ["lexicon:global-acid-transaction"],
            "detected_by": ["synchronous compensation hacks"],
            "measured_by": [
                "convergence time",
                "inconsistency window"
            ],
            "refactored_by": [
                "lexicon:query-projection",
                "lexicon:reconciliation-job",
                "architecture:saga-pattern"
            ],
            "enforced_by": ["consistency tests"],
            "severity": "contextual",
            "exemplar": {
                "before": "await fooStore.save(foo);\nawait fooSearch.update(foo);\nawait fooAnalytics.update(foo);",
                "after": "await fooStore.save(foo);\nfooEvents.emit({ type: \"FooSaved\", foo });\nconst view = await fooSearchView.find(foo.id);\nconst converged = view.version >= foo.version;\nreturn { foo: view, converged };",
                "lang": "ts"
            }
        },
        {
            "id": "saga-pattern",
            "name": "Saga Pattern",
            "aliases": ["Saga"],
            "definition": "A design pattern that runs a cross-service transaction as a sequence of local steps, each paired with a compensating step.",
            "type": "pattern",
            "scope": [
                "service workflow",
                "distributed system"
            ],
            "requires": [
                "Compensating Transaction",
                "Idempotency"
            ],
            "reinforces": ["Eventual Consistency"],
            "enables": ["Long-Running Transactions"],
            "conflicts_with": ["Global ACID Transaction"],
            "tensions_with": ["Workflow Complexity"],
            "violated_by": [
                "lexicon:global-acid-transaction",
                "lexicon:hidden-distributed-transaction"
            ],
            "detected_by": ["distributed transaction attempts"],
            "measured_by": ["compensation coverage"],
            "refactored_by": ["architecture:compensating-transaction"],
            "enforced_by": ["workflow tests"],
            "severity": "contextual",
            "exemplar": {
                "before": "const tx = coordinator.begin();\nawait fooService.prepare(tx, foo);\nawait barService.prepare(tx, bar);\nawait bazService.prepare(tx, baz);\nawait coordinator.commit(tx);",
                "after": "await saga([\n  { action: () => fooService.create(foo), compensate: id => fooService.cancel(id) },\n  { action: () => barService.create(bar), compensate: id => barService.cancel(id) },\n  { action: () => bazService.create(baz), compensate: id => bazService.cancel(id) },\n]).run();",
                "lang": "ts"
            }
        },
        {
            "id": "outbox-pattern",
            "name": "Outbox Pattern",
            "aliases": ["Transactional Outbox"],
            "definition": "A design pattern that writes an outgoing message in the same local transaction as the state change, and a relay publishes it afterwards.",
            "type": "pattern",
            "scope": [
                "persistence",
                "messaging"
            ],
            "requires": [
                "Local Transaction",
                "Message Relay"
            ],
            "reinforces": ["Event Reliability"],
            "enables": ["Atomic State Change + Message Publish"],
            "conflicts_with": ["Dual Write"],
            "tensions_with": ["Relay Complexity"],
            "violated_by": ["architecture:dual-write"],
            "detected_by": ["dual-write patterns"],
            "measured_by": [
                "lost-message rate",
                "outbox coverage"
            ],
            "refactored_by": ["lexicon:message-relay"],
            "enforced_by": [
                "persistence rules",
                "integration tests"
            ],
            "severity": "recommended",
            "exemplar": {
                "before": "await fooStore.save(foo);\nawait eventBus.publish({ type: \"FooSaved\", fooId: foo.id });",
                "after": "await database.transaction(async tx => {\n  await tx.foos.save(foo);\n  await tx.outbox.insert({ id: eventId(), type: \"FooSaved\", fooId: foo.id });\n});\nawait outboxRelay.publishPending();",
                "lang": "ts"
            }
        },
        {
            "id": "compensating-transaction",
            "name": "Compensating Transaction",
            "aliases": ["Compensating Action"],
            "definition": "A mechanism that undoes the business effect of a completed step when a later step of the workflow fails.",
            "type": "mechanism",
            "scope": [
                "workflow",
                "distributed transaction"
            ],
            "requires": ["Reversible/Compensable Step"],
            "reinforces": [
                "Saga Pattern",
                "Resilience"
            ],
            "enables": ["Failure Recovery"],
            "conflicts_with": ["Irreversible Side Effects"],
            "tensions_with": ["Business Complexity"],
            "violated_by": ["lexicon:irreversible-side-effects"],
            "detected_by": ["saga steps without compensation"],
            "measured_by": ["compensation coverage"],
            "refactored_by": [],
            "enforced_by": ["workflow tests"],
            "severity": "contextual",
            "exemplar": {
                "before": "await fooService.create(foo);\nawait barService.create(bar);",
                "after": "const fooId = await fooService.create(foo);\ntry {\n  await barService.create(bar);\n} catch (error) {\n  await fooService.compensateCreate(fooId);\n  throw error;\n}",
                "lang": "ts"
            }
        },
        {
            "id": "append-only-log",
            "distinctFrom": [
                {
                    "id": "architecture:domain-events",
                    "reason": "An append-only log is the storage shape that never rewrites an entry, while domain events are what gets recorded, named in the domain's language."
                }
            ],
            "name": "Append-Only Log",
            "definition": "A design pattern that records history as immutable entries added at the end of the log.",
            "type": "pattern",
            "scope": [
                "event store",
                "audit",
                "stream"
            ],
            "requires": ["Immutable Events"],
            "reinforces": [
                "Auditability",
                "Event Sourcing"
            ],
            "enables": [
                "Replay",
                "Temporal Queries"
            ],
            "conflicts_with": ["In-Place Mutation"],
            "tensions_with": ["Storage Growth"],
            "violated_by": ["lexicon:in-place-mutation"],
            "detected_by": ["mutable event rows"],
            "measured_by": ["append-only compliance"],
            "refactored_by": ["lexicon:snapshot-compaction"],
            "enforced_by": ["database constraints"],
            "severity": "contextual",
            "exemplar": {
                "before": "fooState.set(foo.id, foo);\nfooState.delete(foo.id);",
                "after": "type FooLogEntry = FooCreated | FooUpdated | FooRemoved;\nfooLog.append({ seq: nextSeq(), type: \"FooRemoved\", fooId: foo.id });\nconst state = projectFooLog(fooLog.read());",
                "lang": "ts"
            }
        },
        {
            "id": "dead-letter-queue",
            "name": "Dead-Letter Queue",
            "aliases": ["DLQ"],
            "definition": "A design pattern that moves a message which keeps failing into a separate queue, where it can be inspected and reprocessed.",
            "type": "pattern",
            "scope": [
                "service",
                "messaging",
                "resilience"
            ],
            "requires": ["Message Queue"],
            "reinforces": [
                "Fault Isolation",
                "Observability"
            ],
            "enables": [
                "Poison-Message Quarantine",
                "Reprocessing After Fix"
            ],
            "conflicts_with": ["Infinite Redelivery Loop"],
            "tensions_with": ["Operational Overhead"],
            "violated_by": ["lexicon:infinite-redelivery-loop"],
            "detected_by": ["retry storms on a single poison message"],
            "measured_by": ["redelivery count per failed message"],
            "refactored_by": [],
            "enforced_by": ["messaging design review"],
            "severity": "contextual",
            "mandatoryFor": "production systems",
            "exemplar": {
                "before": "worker.consume(fooQueue, async message => {\n  await processFoo(message);\n});",
                "after": "worker.consume(fooQueue, async message => {\n  try {\n    await processFoo(message);\n  } catch (error) {\n    if (message.attempts >= 5) return fooDeadLetterQueue.send(message, error);\n    throw error;\n  }\n});",
                "lang": "ts"
            }
        },
        {
            "id": "idempotent-consumer",
            "name": "Idempotent Consumer",
            "definition": "A design pattern in which a consumer records each message it has processed, so a redelivered message has no second effect.",
            "type": "pattern",
            "scope": [
                "service",
                "messaging",
                "correctness"
            ],
            "requires": ["Deduplication Key"],
            "reinforces": [
                "Eventual Consistency",
                "At-Least-Once Delivery Safety"
            ],
            "enables": ["Safe Message Redelivery"],
            "conflicts_with": ["Duplicate Side Effects"],
            "tensions_with": ["State Overhead"],
            "violated_by": ["lexicon:duplicate-side-effects"],
            "detected_by": ["duplicate effects under at-least-once delivery"],
            "measured_by": ["duplicate-processing incident rate"],
            "refactored_by": [],
            "enforced_by": ["messaging design review"],
            "severity": "contextual",
            "mandatoryFor": "distributed systems",
            "exemplar": {
                "before": "worker.consume(fooQueue, message => chargeFoo(message.fooId, message.amount));",
                "after": "worker.consume(fooQueue, async message => {\n  if (await processedMessages.has(message.id)) return;\n  await chargeFoo(message.fooId, message.amount);\n  await processedMessages.add(message.id);\n});",
                "lang": "ts"
            }
        },
        {
            "id": "competing-consumers",
            "name": "Competing Consumers",
            "definition": "A design pattern in which several consumers read from one queue, and each message goes to only one of them.",
            "type": "pattern",
            "scope": [
                "service",
                "messaging",
                "scalability"
            ],
            "requires": ["Message Queue"],
            "reinforces": [
                "Horizontal Scaling",
                "Load Balancing"
            ],
            "enables": [
                "Parallel Message Processing",
                "Consumer Elasticity"
            ],
            "conflicts_with": ["Single Serial Consumer"],
            "tensions_with": ["Ordering"],
            "violated_by": ["lexicon:single-serial-consumer"],
            "detected_by": ["queue depth rising with a single processor"],
            "measured_by": ["consumer utilization vs backlog growth"],
            "refactored_by": [],
            "enforced_by": ["messaging design review"],
            "severity": "contextual",
            "exemplar": {
                "before": "fooWorker.consume(fooQueue, processFoo);",
                "after": "for (let worker = 0; worker < WORKER_COUNT; worker += 1) {\n  new FooWorker(worker).consume(fooQueue, processFoo);\n}",
                "lang": "ts"
            }
        }
    ]
}