Skip to main content

Module Quiz

Complete this quiz after finishing all concept and practice pages.

Current Module Questions

Question 1: What Is an Event?

State, in one sentence, the three non-negotiable properties of an event, and give one example of a "message" that is not an event and why.

Answer: An event is past tense, immutable, and authored by the system that knows it happened. SendWelcomeEmail is not an event: it is imperative (a command to a specific handler), not a fact, and its consumer count is one, not many.

Common Errors:

  • Confusing "past tense" with "past timestamp" -- any old CRUD row has a timestamp; only an event is named by the domain transition.
  • Accepting OrderUpdated as an event -- it is a summary, not a specific fact; it erases which transition occurred.

If You Got This Wrong:


Question 2: Event vs Command vs Query

A team proposes a topic called order-events carrying PlaceOrder, OrderPlaced, GetOrderStatus, and CancelOrder. Identify each message's real intent and propose the corrected topic/endpoint for each.

Answer:

  • PlaceOrder -> command -> queue payment.commands or HTTP endpoint; single consumer
  • OrderPlaced -> event -> topic order.placed; pub-sub
  • GetOrderStatus -> query -> HTTP/gRPC endpoint; never on a broker
  • CancelOrder -> command -> queue order.commands or HTTP endpoint

Mixing them on one topic hides intent and forces future engineers to add "only one consumer please" comments.


Question 3: Pick the Messaging Pattern (Scenario 1)

A checkout service publishes that an order was placed; four other services react (billing, inventory, notifications, analytics). Which messaging pattern and why?

Answer: Publish-subscribe topic. Each subscriber reacts independently; adding fraud-detection as a fifth subscriber next month must not require changes to the publisher. Point-to-point queue would give the message to only one consumer; work-distribution semantics here would be wrong.


Question 4: Pick the Messaging Pattern (Scenario 2)

An image-processing service accepts upload events and generates thumbnails. 10 workers share the load. Which messaging pattern and why?

Answer: Point-to-point queue (work distribution). Each image is a task that exactly one worker should process. Pub-sub would cause every worker to regenerate the same thumbnails -- both wasteful and potentially corrupt (race on storage). Scale is adding workers sharing the queue.


Question 5: The Outbox Pattern

A service writes to Postgres and then publishes to Kafka. Sometimes, after a crash, the DB has the row but the broker does not have the event. Name the bug and describe the fix.

Answer: This is the dual-write bug. The DB transaction and the broker publish are not atomic; a crash between them loses the event. The fix is the transactional outbox: inside the same DB transaction, insert a row into an outbox table containing the event. A separate relay process reads unpublished outbox rows, publishes them (at-least-once) to the broker, and marks them published. Either both the state change and the outbox insert happen, or neither does.


Question 6: Queue vs Log-Based Broker

A team argues about RabbitMQ vs Kafka for "an event bus." What two questions decide the choice?

Answer:

  1. Do multiple independent services need to read the same stream? (If yes, log-based; queues are point-to-point.)
  2. Do you need replay -- rebuilding a read model, catching up a new consumer, reprocessing after a bug? (If yes, log-based; queues discard on ack.)

If neither is true, a queue is often operationally cheaper and simpler.


Question 7: Partitions and Consumer Groups

A Kafka topic has 12 partitions. A consumer group has 20 consumers. What happens?

Answer: Only 12 consumers get a partition assignment; the remaining 8 are idle. Consumer count beyond partition count adds no parallelism within a group. To scale further, increase the partition count (disruptive for keyed topics) or redesign for more concurrent work per partition.


Question 8: Ordering Guarantees

A saga orchestrator occasionally sees PaymentCaptured before OrderPlaced. List the two most likely causes.

Answer:

  1. Inconsistent key across topics. order.placed and payment.captured are partitioned by different keys (or by no key at all), so events for the same order hit different partitions and consumer instances.
  2. Consumer commits offsets before processing, then crashes and skips messages on restart -- out-of-order delivery relative to the orchestrator's state.

Fix: partition all saga-relevant topics by the same key (usually the aggregate ID), and commit offsets after processing.


Question 9: Choreography vs Orchestration

A 20-step business workflow with timers, compensations, and several human approvals needs to be modeled across 12 services. Which topology and why?

Answer: Orchestration. At 20 steps with timers and compensations, the workflow state itself is a business-critical artifact. Orchestration (Temporal, Step Functions, Camunda) makes the state machine explicit, handles timers and retries declaratively, and gives support staff a single place to see "where is instance X stuck?" Choreography across 12 services with that many steps produces a graph that no one can reason about or debug.


Question 10: Saga Compensation

In a checkout saga ReserveStock -> ChargeCard -> CreateShipment, CreateShipment fails. Walk the compensation.

Answer:

  1. Orchestrator runs RefundCard(order_id) -> PaymentRefunded event emitted.
  2. Orchestrator runs ReleaseStock(order_id) -> StockReleased event emitted.
  3. Orchestrator marks the saga compensated and emits OrderCancelled(reason=shipment_failed).

Compensations run in reverse order of original steps, each is idempotent, and the payment "rollback" is a new, named event (PaymentRefunded), not a database rollback -- the charge already committed.


Question 11: Idempotency and Exactly-Once

Explain why "at-least-once delivery + idempotent consumers" is effectively exactly-once, and why stronger broker-level "exactly once" is not enough.

Answer: The broker can guarantee at-least-once delivery to the consumer, but once the consumer performs a side effect on an external system (DB write, API call, email send), the broker cannot participate in that system's commit. A crash between the effect and the offset commit causes a redelivery; without consumer-side idempotency, the effect is repeated. "Effectively exactly-once" is achieved at the system level: at-least-once delivery, a dedup key (usually event_id), and the effect + dedup-insert in one transaction. Kafka's EOS applies to Kafka-to-Kafka pipelines only; crossing to any external system returns you to the at-least-once + idempotency model.


Question 12: Event Sourcing Fit

Name three situations where event sourcing is overkill, and one where it is the natural fit.

Answer:

  • Overkill: (1) a simple internal CRUD tool where history is uninteresting; (2) a team with no prior event-sourcing experience under tight deadlines; (3) a system whose primary access pattern is ad-hoc analytical queries.
  • Natural fit: a regulated domain (insurance claims, clinical records, financial ledgers) where audit is a hard requirement, business analysts frequently ask "what did we know on date X?", and multiple read shapes (dashboards, fraud, reporting) coexist.

Question 13: Projections and Rebuildability

Why is it important that every projection be rebuildable, and what does that require of the event stream?

Answer: Rebuildability lets you fix bugs in projection logic, evolve read-model schemas, and add new read models without manual migrations -- you reset the consumer offset to zero and re-consume. This requires the event stream to retain events for at least as long as you need to rebuild any projection. A 7-day Kafka retention cannot rebuild a 2-year projection; for long rebuild horizons, use long retention, log compaction, or a dedicated event store.


Question 14: CQRS Decision

A 5-engineer startup with 2 simple CRUD screens and ~100 customers asks if they should use CQRS. Defend a recommendation.

Answer: No. CQRS is not justified here. The commitments -- eventual consistency on reads, extra deployable components (projections, read stores), more operational complexity (lag monitoring, rebuilds) -- have no matching benefit: there are no distinct read shapes, no heavy read workload, no regulatory audit requirement, and the write side has no complex invariants. Use a single Postgres DB, maybe a materialized view or two, and revisit CQRS when (a) the team grows, (b) read workloads diversify, or (c) event-driven infrastructure is already in place for other reasons.


Question 15: Integration Question -- Tie the Module Together

A payments service emits PaymentCaptured. Downstream: a ledger service, a notification service, and an analytics pipeline. Describe the minimum production-quality integration end-to-end.

Answer:

  • Producer side: PaymentCaptured is an immutable past-tense event with event_id, occurred_at, order_id, amount_cents. Written via outbox pattern in the same DB transaction as the payment record; a relay publishes to a Kafka topic payment.captured partitioned by order_id.
  • Topic design: log-based broker (Kafka) so all three consumers can read independently; retention = 14 days for replay margin; replication factor 3.
  • Consumer side: each downstream service runs its own consumer group (ledger, notifications, analytics). Each consumer is idempotent, dedupe-keyed on event_id with a dedup store that outlives the worst-case redelivery window. Offsets are committed after processing.
  • Workflow: no central orchestrator here; this is reactive fan-out (choreography). If a broader saga exists (e.g., the charge is part of an order workflow), the orchestrator consumes PaymentCaptured as one of its inputs.
  • Observability: correlation IDs flow on every event; dashboards show outbox lag and consumer lag per group.

Interleaved Review Questions

(5 questions from previous modules to maintain retention)

Prior Module Question 1 (from S8M2)

What is a "distributed monolith," and what is the single most reliable signal that a microservices system has become one?

Answer: A distributed monolith is a system split into multiple services that must be deployed and changed together -- the network separation is real but the modular independence is not. The reliable signal is coordinated deploys: every meaningful feature requires simultaneous releases of 3+ services; a change to one service cannot be deployed in isolation without breaking another.

Prior Module Question 2 (from S8M1)

In system design, what is the correct first step when a requirement is ambiguous -- and why not "start drawing components"?

Answer: Clarify requirements and constraints: users, scale, latency, consistency, failure tolerance. Drawing components before the ambiguity is resolved forces decisions that cannot be defended and then calcifies into premature architecture.

Prior Module Question 3 (from S7)

State the dependency rule in Clean Architecture in one sentence.

Answer: Source code dependencies point only inward, from concrete outer layers (frameworks, drivers) toward abstract inner layers (entities, use cases) -- never the other way.

Prior Module Question 4 (from S6)

What does "eventual consistency" actually promise, and what does it explicitly not promise?

Answer: Eventual consistency promises that if writes stop, all replicas will converge to the same value. It does not promise any particular ordering of intermediate reads, nor a bounded staleness window, unless the system additionally offers specific session or monotonic-read guarantees.

Prior Module Question 5 (from S5)

Why does a queue between a fast producer and a slow consumer not "solve" the throughput mismatch -- and what does it actually buy you?

Answer: The queue cannot make the consumer faster; if the producer sustains a higher rate than the consumer, the queue grows without bound. What the queue buys is smoothing of bursts (the consumer handles peaks over time) and back-pressure decoupling (producer does not block on consumer), plus durability (consumer crashes do not lose work). Long-term throughput is still consumer-limited.


Self-Assessment and Remediation

Scoring and Advancement Criteria

Mastery Level (90-100% correct):

  • Status: Ready to advance to next module
  • Action: Proceed to Module 4 (Scale, Reliability & Performance)

Proficient Level (75-89% correct):

  • Action: Review concept pages corresponding to missed questions; redo the matching kata.

Developing Level (60-74% correct):

  • Action: Rework Clusters 2 (messaging + outbox) and 4 (saga + idempotency). These are where most missed questions will cluster. Redo Practice 2 and 3 fully.

Insufficient Level (<60% correct):

  • Action: Return to Concepts 1-3 and rebuild the mental model before attempting the operational clusters. Without the "event is a past fact" discipline, the rest of this module does not stick.

Remediation Resources by Score Range

75-89% Score Range:

  • Targeted Review: Re-read only the specific concept(s) behind missed questions.
  • Quick Practice: 2-3 additional scenarios from Practice 2 or 4.

60-74% Score Range:

  • Systematic Review: Full re-read of Clusters 2 and 4.
  • Extended Practice: All of Practice 3 (saga + idempotency) with different domains.
  • Alternative Explanations: Fowler's "What do you mean by Event-Driven?" and Richardson's saga article on microservices.io.

<60% Score Range:

  • Foundation Check: Verify S7M2 (event-driven topologies) is understood.
  • Comprehensive Remediation: Rework every concept page with notes in your own words.
  • Peer/Instructor: Explain "event vs command" and "the outbox pattern" out loud; the gap will surface quickly.