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.
Official reference: Apache Kafka documentation
- 1.easy
A producer with default settings sends these three records to a 6-partition topic. What does Kafka guarantee?
producer.send(new ProducerRecord<>("orders", "order-1", "CREATED")); producer.send(new ProducerRecord<>("orders", "order-2", "CREATED")); producer.send(new ProducerRecord<>("orders", "order-1", "PAID"));- AAll three records are read in exactly this order by any consumer
- BBoth
order-1records land in the same partition, withCREATEDbeforePAID - CEach record goes to a different partition for load balancing
- DNothing about order, because the producer is asynchronous
Show answer
Answer: B (Both
order-1records land in the same partition, withCREATEDbeforePAID)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-2may land in another partition, so there is no ordering guarantee between it and theorder-1records. - 2.mid
With 6 partitions, key
order-1hashes to partition 4. The topic is altered to 8 partitions. What happens toorder-1?kafka-topics.sh --bootstrap-server localhost:9092 \ --alter --topic orders --partitions 8- ANothing changes: keys keep their original partition
- BKafka moves the existing
order-1records to the new partition - CNew
order-1records go tomurmur2(key) % 8(partition 6 here); old ones stay in partition 4 - DThe command fails because keyed topics cannot be altered
Show answer
Answer: C (New
order-1records go tomurmur2(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-1events in partition 6 before older ones still waiting in partition 4, which breaks per-key ordering across the change. - 3.easy
A topic has 4 partitions. Six consumers start with the same
group.id. How many consumers receive records?- A6, each getting a share of every partition
- B4, and the other 2 stay idle
- C1, the group leader
- 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.easy
Service A (group
billing) and service B (groupanalytics) both subscribe toorders. Who receives a new order event?- AOnly one of them, whichever polls first
- BBoth groups, each tracking its own offsets
- COnly the group that subscribed first
- 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.easy
Group
billinghas a committed offset of 120 onorders-0, and offset 120 is still retained. The consumer restarts with this config. Where does it start reading?group.id=billing auto.offset.reset=earliest- AOffset 0, the beginning of the partition
- BThe oldest retained offset
- COffset 120
- DThe log end offset
Show answer
Answer: C (Offset 120)
auto.offset.resetapplies 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.mid
Why does this manual commit add 1 to the record offset?
process(record); consumer.commitSync(Map.of( new TopicPartition(record.topic(), record.partition()), new OffsetAndMetadata(record.offset() + 1)));- AOffsets are 1-based on the broker but 0-based in the client
- BThe committed offset is the next record to read, not the last one processed
- CIt skips the control marker that follows every record
- 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-argumentcommitSync()already commits the position after the last polled record. - 7.mid
The process crashes inside
process(record)halfway through a batch. What delivery guarantee does this loop give?while (running) { ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(500)); consumer.commitSync(); for (ConsumerRecord<String, String> record : records) { process(record); } }- AAt-least-once
- BAt-most-once: unprocessed records in the batch are skipped
- CExactly-once
- 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.mid
Why does
commitAsync()not retry a failed commit automatically, whilecommitSync()does?- AAsync commits are never sent to the broker
- BA retried older commit could arrive after a newer one and move the offset backwards
- CRetries would block the poll loop
- 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 finalcommitSync()on shutdown or revocation. - 9.mid
A topic has replication factor 3 and
min.insync.replicas=2. Two of its three replicas are down. What happens to anacks=allproducer?- AWrites succeed on the leader alone
- BWrites fail with
NotEnoughReplicasExceptionand are retried untildelivery.timeout.ms - CThe partition goes offline for reads and writes
- DThe broker silently lowers
min.insync.replicasto 1
Show answer
Answer: B (Writes fail with
NotEnoughReplicasExceptionand are retried untildelivery.timeout.ms)The ISR has shrunk to the leader, below the minimum of 2, so the leader rejects
acks=allwrites 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.hard
Same topic, same two replicas down, but this producer uses
acks=1. What happens?- AThe write is accepted after the leader appends it
- BThe write fails with
NotEnoughReplicasException - CThe producer upgrades itself to
acks=all - DThe record is buffered until a follower returns
Show answer
Answer: A (The write is accepted after the leader appends it)
min.insync.replicasis enforced only foracks=all. Withacks=1the 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.mid
A topic uses
cleanup.policy=compact. These records are written for keyuser-7. After compaction runs anddelete.retention.mshas passed, what remains foruser-7?user-7 -> {"email":"a@example.com"} user-7 -> {"email":"b@example.com"} user-7 -> null- AThe
b@example.comrecord - BOnly the
nulltombstone, forever - CNothing: the key is gone
- 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. - AThe
- 12.mid
A compacted partition held offsets 0 to 9, and compaction removed offsets 2, 3 and 7. What offsets do consumers see afterwards?
- A0 to 6, renumbered
- B0, 1, 4, 5, 6, 8, 9 with gaps
- C0 to 9, with removed records returned as null
- 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.mid
A low-traffic topic has
retention.ms=3600000(1 hour), yet records written yesterday can still be read. What is the most likely reason?- ARetention only starts counting after a consumer reads a record
- BRetention deletes whole closed segments, and yesterday's records are still in the active segment
- CRetention is applied only when the broker restarts
- D
retention.msis ignored whenretention.bytesis 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) orsegment.ms(7 days), so a quiet partition can keep old data far beyondretention.ms. Lowersegment.msif strict expiry matters. - 14.hard
Each
poll()returns up to 500 records and each record takes about 1 second to process.max.poll.interval.msis the default. What happens?- ANothing: heartbeats from the background thread keep the member alive
- BThe member leaves the group after 5 minutes, its partitions move, and its next commit fails with
CommitFailedException - CThe broker throttles the consumer
- 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 callpoll()withinmax.poll.interval.ms(5 minutes), the consumer leaves the group, and the records are reprocessed elsewhere. Lowermax.poll.recordsor speed up processing. - 15.hard
A consumer with
group.instance.id=orders-0andsession.timeout.ms=60000is restarted and rejoins after 20 seconds. What happens?- ATwo rebalances: one on leave and one on join
- BIt gets its previous partitions back without a rebalance
- CIt is rejected because the ID is already registered
- 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.hard
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?
- AOne copy: the broker deduplicates by key
- BTwo copies: the restarted producer has a new producer ID, so its sequence numbers start fresh
- COne copy: idempotence deduplicates by record content
- 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.mid
This program exits normally. What happens to the 1,000 records?
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)); } }- AAll are delivered, because
send()writes synchronously - BSome or all may be lost, because they sit in the producer buffer and nothing flushes it
- CThe JVM waits for the sender thread to drain the buffer
- 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. Withoutflush()orclose()before exit, buffered records are dropped. Use try-with-resources soclose()flushes them. - AAll are delivered, because
- 18.easy
What is the default
linger.msfor the Java producer in Kafka 4.0?- A0 ms
- B5 ms
- C100 ms
- 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.hard
A transactional producer writes 3 records and then calls
abortTransaction(). A consumer uses the defaultisolation.level. What does it see?- ANothing: aborted records are deleted
- BThe 3 records, because the default is
read_uncommitted - COnly the abort marker
- 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_committedconsumers filter aborted data, and the default isread_uncommitted. Control markers themselves are never returned to applications. - 20.hard
Instance A uses
transactional.id=payments-0and freezes in a long GC pause. Instance B starts with the same ID and callsinitTransactions(). What happens when A wakes up and tries to commit?- ABoth commits succeed, producing duplicates
- BA is fenced: its operation fails with
ProducerFencedExceptionbecause B bumped the epoch - CB is fenced because A registered first
- DThe coordinator merges both transactions
Show answer
Answer: B (A is fenced: its operation fails with
ProducerFencedExceptionbecause B bumped the epoch)initTransactions()increments the producer epoch for thattransactional.idand 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.
No questions match these filters. Try a different subtopic or clear the filters.