pencils ready ✎

Apache Kafka MCQs multiple-choice questions with answers & explanations

All 20 Apache Kafka quiz questions on one page. Pick an answer in your head, then open Show answer to check it and read why. Want a score and a timer? Take them as a quiz instead.

20 questions
  1. 1.

    A producer with default settings sends these three records to a 6-partition topic. What does Kafka guarantee?

    easy
    producer.send(new ProducerRecord<>("orders", "order-1", "CREATED"));
    producer.send(new ProducerRecord<>("orders", "order-2", "CREATED"));
    producer.send(new ProducerRecord<>("orders", "order-1", "PAID"));
    1. AAll three records are read in exactly this order by any consumer
    2. BBoth order-1 records land in the same partition, with CREATED before PAID
    3. CEach record goes to a different partition for load balancing
    4. DNothing about order, because the producer is asynchronous
    Show answer

    Answer: B (Both order-1 records land in the same partition, with CREATED before PAID)

    Records with the same key hash to the same partition, and order is guaranteed within a partition (the default idempotent producer keeps retries in order too). order-2 may land in another partition, so there is no ordering guarantee between it and the order-1 records.

  2. 2.

    With 6 partitions, key order-1 hashes to partition 4. The topic is altered to 8 partitions. What happens to order-1?

    mid
    kafka-topics.sh --bootstrap-server localhost:9092 \
      --alter --topic orders --partitions 8
    1. ANothing changes: keys keep their original partition
    2. BKafka moves the existing order-1 records to the new partition
    3. CNew order-1 records go to murmur2(key) % 8 (partition 6 here); old ones stay in partition 4
    4. DThe command fails because keyed topics cannot be altered
    Show answer

    Answer: C (New order-1 records go to murmur2(key) % 8 (partition 6 here); old ones stay in partition 4)

    The default partitioner computes the partition from the current count, so the mapping changes and existing data is never moved. A consumer can now see newer order-1 events in partition 6 before older ones still waiting in partition 4, which breaks per-key ordering across the change.

  3. 3.

    A topic has 4 partitions. Six consumers start with the same group.id. How many consumers receive records?

    easy
    1. A6, each getting a share of every partition
    2. B4, and the other 2 stay idle
    3. C1, the group leader
    4. D6, because Kafka splits partitions when needed
    Show answer

    Answer: B (4, and the other 2 stay idle)

    Within one group, each partition is assigned to exactly one member, so at most 4 consumers can be active. The two extra members get no partitions; they only take over if an active member leaves.

  4. 4.

    Service A (group billing) and service B (group analytics) both subscribe to orders. Who receives a new order event?

    easy
    1. AOnly one of them, whichever polls first
    2. BBoth groups, each tracking its own offsets
    3. COnly the group that subscribed first
    4. DBoth, but B only after A commits
    Show answer

    Answer: B (Both groups, each tracking its own offsets)

    Consumer groups are independent. Every group receives every record and stores its own committed offsets in __consumer_offsets. Load is shared only between members of the same group.

  5. 5.

    Group billing has a committed offset of 120 on orders-0, and offset 120 is still retained. The consumer restarts with this config. Where does it start reading?

    easy
    group.id=billing
    auto.offset.reset=earliest
    1. AOffset 0, the beginning of the partition
    2. BThe oldest retained offset
    3. COffset 120
    4. DThe log end offset
    Show answer

    Answer: C (Offset 120)

    auto.offset.reset applies only when there is no valid committed offset: a new group, or a committed offset deleted by retention. Here a valid commit exists, so the consumer resumes at 120.

  6. 6.

    Why does this manual commit add 1 to the record offset?

    mid
    process(record);
    consumer.commitSync(Map.of(
        new TopicPartition(record.topic(), record.partition()),
        new OffsetAndMetadata(record.offset() + 1)));
    1. AOffsets are 1-based on the broker but 0-based in the client
    2. BThe committed offset is the next record to read, not the last one processed
    3. CIt skips the control marker that follows every record
    4. DIt is a workaround for a bug in commitSync
    Show answer

    Answer: B (The committed offset is the next record to read, not the last one processed)

    A committed offset means "resume here". Committing record.offset() would make a restarted consumer read that record again. The no-argument commitSync() already commits the position after the last polled record.

  7. 7.

    The process crashes inside process(record) halfway through a batch. What delivery guarantee does this loop give?

    mid
    while (running) {
        ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(500));
        consumer.commitSync();
        for (ConsumerRecord<String, String> record : records) {
            process(record);
        }
    }
    1. AAt-least-once
    2. BAt-most-once: unprocessed records in the batch are skipped
    3. CExactly-once
    4. DNone: the commit fails because processing has not finished
    Show answer

    Answer: B (At-most-once: unprocessed records in the batch are skipped)

    The offsets of the whole batch are committed before any record is processed, so after the crash the group resumes after the batch and the rest is never processed. Moving the commit after the loop gives at-least-once.

  8. 8.

    Why does commitAsync() not retry a failed commit automatically, while commitSync() does?

    mid
    1. AAsync commits are never sent to the broker
    2. BA retried older commit could arrive after a newer one and move the offset backwards
    3. CRetries would block the poll loop
    4. DAsync commits are stored only in memory
    Show answer

    Answer: B (A retried older commit could arrive after a newer one and move the offset backwards)

    With async commits several can be in flight. If commit 2000 failed and was retried after commit 3000 succeeded, it would rewind the group. The usual pattern is commitAsync() in the loop and a final commitSync() on shutdown or revocation.

  9. 9.

    A topic has replication factor 3 and min.insync.replicas=2. Two of its three replicas are down. What happens to an acks=all producer?

    mid
    1. AWrites succeed on the leader alone
    2. BWrites fail with NotEnoughReplicasException and are retried until delivery.timeout.ms
    3. CThe partition goes offline for reads and writes
    4. DThe broker silently lowers min.insync.replicas to 1
    Show answer

    Answer: B (Writes fail with NotEnoughReplicasException and are retried until delivery.timeout.ms)

    The ISR has shrunk to the leader, below the minimum of 2, so the leader rejects acks=all writes with a retriable error. Consumers can still read records below the high watermark; the partition is effectively read-only until a follower catches up.

  10. 10.

    Same topic, same two replicas down, but this producer uses acks=1. What happens?

    hard
    1. AThe write is accepted after the leader appends it
    2. BThe write fails with NotEnoughReplicasException
    3. CThe producer upgrades itself to acks=all
    4. DThe record is buffered until a follower returns
    Show answer

    Answer: A (The write is accepted after the leader appends it)

    min.insync.replicas is enforced only for acks=all. With acks=1 the leader acknowledges after its own write, so the record exists on one broker and is lost if that broker fails before followers copy it.

  11. 11.

    A topic uses cleanup.policy=compact. These records are written for key user-7. After compaction runs and delete.retention.ms has passed, what remains for user-7?

    mid
    user-7 -> {"email":"a@example.com"}
    user-7 -> {"email":"b@example.com"}
    user-7 -> null
    1. AThe b@example.com record
    2. BOnly the null tombstone, forever
    3. CNothing: the key is gone
    4. DAll three, because compaction keeps history
    Show answer

    Answer: C (Nothing: the key is gone)

    A null value is a tombstone. Compaction drops earlier values for the key, keeps the tombstone for delete.retention.ms (24 hours by default) so consumers can observe the delete, then removes it too. This assumes the records are no longer in the active segment, which is never compacted.

  12. 12.

    A compacted partition held offsets 0 to 9, and compaction removed offsets 2, 3 and 7. What offsets do consumers see afterwards?

    mid
    1. A0 to 6, renumbered
    2. B0, 1, 4, 5, 6, 8, 9 with gaps
    3. C0 to 9, with removed records returned as null
    4. DOnly the active segment
    Show answer

    Answer: B (0, 1, 4, 5, 6, 8, 9 with gaps)

    Compaction never changes the offset of a surviving record. Consumers simply skip the gaps, which is why code must not assume that offsets are contiguous or count records by subtracting offsets.

  13. 13.

    A low-traffic topic has retention.ms=3600000 (1 hour), yet records written yesterday can still be read. What is the most likely reason?

    mid
    1. ARetention only starts counting after a consumer reads a record
    2. BRetention deletes whole closed segments, and yesterday's records are still in the active segment
    3. CRetention is applied only when the broker restarts
    4. Dretention.ms is ignored when retention.bytes is unlimited
    Show answer

    Answer: B (Retention deletes whole closed segments, and yesterday's records are still in the active segment)

    Deletion works per segment, and the active segment is never deleted. A segment rolls at segment.bytes (1 GiB) or segment.ms (7 days), so a quiet partition can keep old data far beyond retention.ms. Lower segment.ms if strict expiry matters.

  14. 14.

    Each poll() returns up to 500 records and each record takes about 1 second to process. max.poll.interval.ms is the default. What happens?

    hard
    1. ANothing: heartbeats from the background thread keep the member alive
    2. BThe member leaves the group after 5 minutes, its partitions move, and its next commit fails with CommitFailedException
    3. CThe broker throttles the consumer
    4. DThe consumer skips records to catch up
    Show answer

    Answer: B (The member leaves the group after 5 minutes, its partitions move, and its next commit fails with CommitFailedException)

    Heartbeats only cover session.timeout.ms. If the application does not call poll() within max.poll.interval.ms (5 minutes), the consumer leaves the group, and the records are reprocessed elsewhere. Lower max.poll.records or speed up processing.

  15. 15.

    A consumer with group.instance.id=orders-0 and session.timeout.ms=60000 is restarted and rejoins after 20 seconds. What happens?

    hard
    1. ATwo rebalances: one on leave and one on join
    2. BIt gets its previous partitions back without a rebalance
    3. CIt is rejected because the ID is already registered
    4. DIt joins as a new member and gets a random assignment
    Show answer

    Answer: B (It gets its previous partitions back without a rebalance)

    With static membership, a member does not send a leave request on shutdown, and the coordinator holds its assignment until the session timeout. Rejoining within that window with the same instance ID returns the same partitions with no rebalance.

  16. 16.

    An app with the default idempotent producer sends an event, crashes before saving that it was sent, restarts and sends the same event again. What ends up in the topic?

    hard
    1. AOne copy: the broker deduplicates by key
    2. BTwo copies: the restarted producer has a new producer ID, so its sequence numbers start fresh
    3. COne copy: idempotence deduplicates by record content
    4. DThe second send fails with DuplicateSequenceException
    Show answer

    Answer: B (Two copies: the restarted producer has a new producer ID, so its sequence numbers start fresh)

    Idempotence deduplicates retries of the same batch within one producer session, using the producer ID and per-partition sequence numbers. A new process gets a new producer ID. Deduplicate by event ID downstream, or use transactions with a stable transactional.id.

  17. 17.

    This program exits normally. What happens to the 1,000 records?

    mid
    public static void main(String[] args) {
        KafkaProducer<String, String> producer = new KafkaProducer<>(props);
        for (int i = 0; i < 1000; i++) {
            producer.send(new ProducerRecord<>("events", "k" + i, "v" + i));
        }
    }
    1. AAll are delivered, because send() writes synchronously
    2. BSome or all may be lost, because they sit in the producer buffer and nothing flushes it
    3. CThe JVM waits for the sender thread to drain the buffer
    4. DThey are written to disk and sent on the next run
    Show answer

    Answer: B (Some or all may be lost, because they sit in the producer buffer and nothing flushes it)

    send() only appends to an in-memory batch; a background daemon thread ships it later. Without flush() or close() before exit, buffered records are dropped. Use try-with-resources so close() flushes them.

  18. 18.

    What is the default linger.ms for the Java producer in Kafka 4.0?

    easy
    1. A0 ms
    2. B5 ms
    3. C100 ms
    4. D1000 ms
    Show answer

    Answer: B (5 ms)

    KIP-1030 changed the default from 0 to 5 ms in Kafka 4.0, so the producer waits briefly to fill batches. A batch is still sent immediately once it reaches batch.size.

  19. 19.

    A transactional producer writes 3 records and then calls abortTransaction(). A consumer uses the default isolation.level. What does it see?

    hard
    1. ANothing: aborted records are deleted
    2. BThe 3 records, because the default is read_uncommitted
    3. COnly the abort marker
    4. DThe 3 records, flagged as aborted
    Show answer

    Answer: B (The 3 records, because the default is read_uncommitted)

    Transactional records are written to the log before the outcome is known; an abort only adds a marker. Only read_committed consumers filter aborted data, and the default is read_uncommitted. Control markers themselves are never returned to applications.

  20. 20.

    Instance A uses transactional.id=payments-0 and freezes in a long GC pause. Instance B starts with the same ID and calls initTransactions(). What happens when A wakes up and tries to commit?

    hard
    1. ABoth commits succeed, producing duplicates
    2. BA is fenced: its operation fails with ProducerFencedException because B bumped the epoch
    3. CB is fenced because A registered first
    4. DThe coordinator merges both transactions
    Show answer

    Answer: B (A is fenced: its operation fails with ProducerFencedException because B bumped the epoch)

    initTransactions() increments the producer epoch for that transactional.id and aborts any open transaction from the older epoch. Requests with the old epoch are rejected, so the zombie cannot write. A must close its producer.

esc