Skip to content

Quiz

Click "Answer" to reveal the correct answer and explanation.


Core Concepts

Q1. Which of the following best describes the difference between an event, a command, and a message?

  • A. They are all equivalent terms for the same concept in messaging systems
  • B. A command is an instruction that can be rejected; an event is an immutable record of something that already happened; a message is a generic data container that may represent either
  • C. An event is sent to a single recipient; a command is broadcast to all consumers; a message is stored in a database
  • D. A command carries no payload; an event carries a payload; a message carries metadata only
Answer

B β€” Command = instruction (rejectable); event = immutable fact; message = generic container.

The distinction is semantic but important for system design. A command (PlaceOrder) expresses intent and implies a single handler that may reject it. An event (OrderCreated) is a statement of fact β€” it has already happened and cannot be undone. A message is the neutral transport-level term that encompasses both. Using the right vocabulary prevents ambiguity about who owns the decision.


Q2. In Kafka, when a topic has 3 partitions and a consumer group has 3 consumers, how are partitions assigned?

  • A. All 3 consumers read from all 3 partitions simultaneously, tripling throughput
  • B. Each partition is assigned to exactly one consumer in the group; each consumer owns one partition
  • C. Kafka randomly delivers each message to any available consumer regardless of partition
  • D. Only one consumer is active at a time; the other two are on standby
Answer

B β€” Each partition is owned by exactly one consumer in the group.

Kafka's partition assignment protocol guarantees that within a consumer group, each partition is consumed by exactly one consumer at a time. This ensures ordered, non-duplicated processing within a partition. With 3 partitions and 3 consumers the assignment is 1:1. If a consumer leaves the group, Kafka triggers a rebalance and reassigns its partition to a remaining consumer.


Q3. Why are events considered immutable in event-driven systems?

  • A. Because Kafka does not support update operations at the protocol level
  • B. Because immutability allows brokers to compress events more efficiently
  • C. Because events record something that already happened β€” the fact cannot change β€” making them safe to replay, audit, and use as a reliable source of truth
  • D. Because consumer groups require a fixed schema to parse messages
Answer

C β€” Events are facts about the past; facts cannot be retroactively changed.

Immutability is a design principle, not just a technical constraint. If an event could be mutated after publication, consumers that already processed it would hold a different view of history than consumers processing it later β€” destroying consistency. The append-only log is what makes event sourcing, time-travel debugging, and zero-downtime projection rebuilds possible.


Q4. In a CQRS architecture, which side handles write operations?

  • A. The read model, because it holds the most recent state
  • B. The query handler, which reads from the event store and materialises a projection
  • C. The command handler, which validates the command, appends an event to the event store, and publishes it to the event bus
  • D. The API gateway, which routes writes and reads to the same underlying service
Answer

C β€” The command handler owns writes: validate, append event, publish.

CQRS separates the write path (commands β†’ command handler β†’ event store / event bus) from the read path (queries β†’ read model). The command handler enforces business invariants and produces events as its output. The read model is a derived, denormalised projection updated asynchronously from those events. This separation allows each side to be optimised and scaled independently.


Q5. A user initiates a login and your service must return a session token before the HTTP response is sent. Which communication style is the correct choice and why?

  • A. Asynchronous event, because publishing to Kafka is faster than an HTTP round-trip
  • B. Synchronous REST, because the caller requires the result immediately before it can proceed
  • C. Asynchronous event with a callback, so the UI polls for the token
  • D. Either style β€” the choice only affects internal architecture, not latency visible to the user
Answer

B β€” Synchronous REST, because the caller is blocked waiting for the result.

The defining question for choosing synchronous vs asynchronous is: does the caller need the answer before it can continue? For authentication the answer is yes β€” without the token there is nothing to do next. Asynchronous patterns introduce latency indirection (polling, webhooks, long-polling) that adds complexity without benefit when the result is required immediately.


Q6. What is the purpose of a Dead Letter Queue (DLQ)?

  • A. To store messages that have been successfully processed so they can be audited later
  • B. To buffer messages when the broker is under high load, releasing them when load drops
  • C. To capture messages that could not be processed after exhausting retry attempts, preventing them from blocking the main stream while preserving them for investigation
  • D. To compact the topic by removing duplicate messages with the same key
Answer

C β€” DLQ captures unprocessable messages without blocking the main stream.

Without a DLQ, a message that consistently causes a consumer to throw an exception would either be retried forever (stalling progress) or silently dropped (losing data). The DLQ is a safety valve: failing messages are moved there so the stream continues, and an operator can inspect the message, fix the root cause, and replay it. Spring Kafka's @RetryableTopic automates retry scheduling and DLQ routing.


Q7. What does consumer group offset tracking enable that a simple queue does not?

  • A. It allows multiple independent groups to read the same topic at their own pace without interfering with each other
  • B. It prevents consumers from reading the same partition more than once per day
  • C. It encrypts messages so that only the group with the correct key can decode them
  • D. It limits the rate at which producers can publish to a topic
Answer

A β€” Each group owns its own offset, so groups progress independently.

In a traditional queue, once a message is consumed it is gone. In Kafka, the message remains in the log and each consumer group maintains its own pointer (offset) per partition. The notification-group can be at offset 42 while the analytics-group is still at offset 10 β€” both reading the same topic without interfering. This is what makes fan-out (pub/sub) to multiple independent consumers possible at scale.


Q8. In event sourcing, what does "replaying events" mean, and why is it useful?

  • A. Resending failed events to consumers that did not acknowledge receipt
  • B. Re-publishing events to a new topic to trigger downstream services again
  • C. Iterating through the full history of stored events in order to reconstruct the current state of an entity, or to populate a new read model projection from scratch
  • D. Synchronising the event store with a relational database by re-executing SQL statements
Answer

C β€” Replay reconstructs state by iterating the event history in order.

Because the event store is append-only and immutable, the complete history is always available. Replaying means iterating events from offset 0 (or a snapshot) and applying each event to an in-memory aggregate until the current state is reached. This enables building entirely new projections, migrating to a new schema, or debugging by inspecting what the system looked like at any point in the past.


Q9. What is the key operational difference between pub/sub (fan-out) and competing consumers?

  • A. In pub/sub each consumer group receives a full copy of every message; in competing consumers multiple consumers in one group share the partitions so each message is processed by exactly one consumer
  • B. Pub/sub requires a dedicated broker per consumer; competing consumers share a single broker
  • C. Competing consumers are only possible with RabbitMQ, not Kafka
  • D. In pub/sub only one consumer can be active at a time; in competing consumers all consumers run in parallel on the same message
Answer

A β€” Fan-out = every group gets a copy; competing consumers = one group shares the work.

The distinction is determined by consumer group membership. Put email-service, analytics-service, and audit-service in separate groups β†’ each receives every OrderCreated event (fan-out). Put three instances of payment-processor in the same group β†’ Kafka assigns each partition to one instance, so each event is processed once (competing consumers). The same Kafka topic supports both patterns simultaneously.


Q10. Within a single Kafka partition, message ordering is guaranteed. Why is ordering not guaranteed across partitions of the same topic?

  • A. Because Kafka replicates partitions to different brokers, introducing variable network delays
  • B. Because each partition is an independent ordered log with its own offset sequence; a message in partition 0 at offset 5 and a message in partition 1 at offset 3 have no defined temporal relationship β€” the consumer receives them based on whichever is polled first
  • C. Because consumer groups read partitions in reverse order by default to balance load
  • D. Because Kafka uses timestamps instead of offsets for cross-partition ordering, and clocks are never perfectly synchronised
Answer

B β€” Each partition is an independent log; offsets are not comparable across partitions.

A partition is an ordered, append-only sequence. Within partition 0 you know message at offset 5 came after offset 4. But partition 0 offset 5 and partition 1 offset 3 were written independently β€” there is no global sequence number linking them. If strict global ordering is required, use a single partition (at the cost of parallelism) or include an application-level timestamp and sort at read time.


Q11. The order service publishes OrderCreated, OrderPaid and OrderShipped for each order to a topic with 6 partitions. The shipping consumer must see the events of the same order in sequence. What should the producer do?

  • A. Publish without a key so Kafka balances the load evenly
  • B. Use the orderId as the message key, so all events of one order land in the same partition
  • C. Use a single consumer for the whole topic
  • D. Add a timestamp to each event; Kafka orders messages by timestamp across partitions
Answer

B β€” Key by orderId.

The default partitioner hashes the key, so the same key always goes to the same partition, and Kafka guarantees order within a partition. Different orders still spread over the 6 partitions and are processed in parallel. Option A loses ordering; C keeps ordering only by giving up parallelism (and does not fix the order across partitions); D is false β€” Kafka does not reorder messages by timestamp.


Q12. The notification service commits the Kafka offset after sending the e-mail. It crashes right after sending, before committing. What happens on restart, and what should the code do about it?

  • A. The message is lost; nothing can be done
  • B. The message is read again (at-least-once delivery); the consumer must be idempotent, e.g. skip orders it already notified
  • C. Kafka detects the crash and deletes the message so it is not processed twice
  • D. The message goes to the dead letter queue automatically
Answer

B β€” Redelivery; make the consumer idempotent.

Committing after processing gives at-least-once delivery: the consumer resumes from the last committed offset and sees the message again. Committing before processing would give at-most-once (lost message instead of duplicate). Kafka's exactly-once transactions cover only Kafka-to-Kafka processing, not an e-mail, so the realistic design is at-least-once plus an idempotent consumer (a processed-messages table, upserts or unique constraints).


Q13. The order service saves an order in Postgres and then calls kafkaTemplate.send(...). What problem does the transactional outbox solve here?

  • A. It makes Kafka faster by batching messages in Postgres
  • B. It removes the need for consumer groups
  • C. It avoids the dual write: the order and the event are written in the same local database transaction, and a relay publishes the event afterwards, so a crash can no longer leave an order without its event (or an event without its order)
  • D. It guarantees that each event is delivered exactly once to every consumer
Answer

C β€” It turns two writes to two systems into one local transaction.

Without the outbox, a crash between the database commit and the publish loses the event; a rollback after the publish produces an event for an order that does not exist. With the outbox, both rows commit together, and a relay (polling or CDC) publishes the event. The relay may publish twice after a crash, so D is false β€” consumers still need to be idempotent.


Q14. In a choreographed saga, inventory reserves stock after OrderCreated, but the payment service then emits PaymentFailed. What should happen?

  • A. The database rolls back the stock reservation automatically, as in an ACID transaction
  • B. The inventory service runs a compensating transaction that releases the stock, and the order is marked as cancelled
  • C. The order service retries the payment forever until it succeeds
  • D. Nothing β€” the stock remains reserved until an operator fixes it manually
Answer

B β€” Compensate the steps already done.

Each saga step is a local transaction in a different service and database, so there is no global rollback (A). Instead, every step that can be undone has a compensating action β€” here, StockReleased β€” triggered by the failure event, and the order moves to CANCELLED. Compensations, like the steps, must be idempotent because events may be redelivered.