At-least-once delivery in Kafka - Time & Space Complexity
When using Kafka's at-least-once delivery, messages may be sent multiple times to ensure none are lost.
We want to understand how the number of message retries affects the processing time as the input grows.
Analyze the time complexity of the following Kafka consumer processing with at-least-once delivery.
// Pseudocode for Kafka consumer with at-least-once delivery
while (true) {
records = consumer.poll(timeout)
for (record in records) {
process(record)
}
consumer.commitSync()
}
This code continuously polls messages, processes each one, and commits offsets to ensure messages are not lost.
Look for repeated actions that affect time.
- Primary operation: Loop over all messages received in each poll.
- How many times: Once per message batch, repeated continuously as messages arrive.
As the number of messages increases, processing time grows roughly in direct proportion.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 process calls |
| 100 | About 100 process calls |
| 1000 | About 1000 process calls |
Pattern observation: Processing time grows linearly as more messages arrive.
Time Complexity: O(n)
This means processing time grows directly with the number of messages received.
[X] Wrong: "At-least-once delivery means each message is processed only once, so time stays constant regardless of retries."
[OK] Correct: Messages can be delivered multiple times, so processing may repeat, increasing total work as input grows.
Understanding how message retries affect processing time helps you explain real-world Kafka behavior clearly and confidently.
What if we switched from at-least-once to exactly-once delivery? How would the time complexity change?
Practice
at-least-once delivery guarantee in Kafka?Solution
Step 1: Understand delivery guarantees
At-least-once means Kafka ensures messages reach the consumer at least once, so no loss occurs.Step 2: Consider duplicates possibility
Because retries can happen, duplicates may occur, so messages might be delivered multiple times.Final Answer:
Messages are never lost but might be delivered more than once -> Option CQuick Check:
At-least-once = no loss, possible duplicates [OK]
- Confusing at-least-once with exactly-once delivery
- Thinking messages can be lost
- Assuming no duplicates occur
Solution
Step 1: Identify offset commit behavior
At-least-once requires manual control of offset commits to avoid losing messages.Step 2: Choose correct config for manual commit
Settingenable.auto.commit = falsedisables automatic commits, allowing manual commits after processing.Final Answer:
enable.auto.commit = false -> Option AQuick Check:
Manual commit enabled by disabling auto commit [OK]
- Leaving auto commit enabled causes possible message loss
- Confusing auto.offset.reset with commit control
- Assuming max.poll.records affects delivery guarantee
consumer.subscribe(['topic'])
for message in consumer:
process(message)
consumer.commit()Solution
Step 1: Analyze commit timing
Commit happens after processing each message, so offsets are saved only after successful processing.Step 2: Understand delivery guarantee
If a failure occurs before commit, message will be reprocessed, causing duplicates but no loss.Final Answer:
Messages are processed at least once, duplicates possible -> Option AQuick Check:
Commit after processing = at-least-once delivery [OK]
- Assuming commit before processing
- Thinking duplicates cannot happen
- Believing messages are lost on failure
consumer.subscribe(['topic'])
for message in consumer:
consumer.commit()
process(message)Solution
Step 1: Check commit position relative to processing
Offsets are committed before processing, so if processing fails, message is lost.Step 2: Understand at-least-once requirement
To guarantee at-least-once, commit must happen after successful processing to avoid loss.Final Answer:
Committing offset before processing causes message loss on failure -> Option BQuick Check:
Commit after processing to avoid loss [OK]
- Committing before processing causes data loss
- Ignoring commit timing importance
- Confusing subscribe with assign usage
Solution
Step 1: Combine manual commit with processing logic
Manual commit after processing ensures no message loss; idempotent logic handles duplicates safely.Step 2: Evaluate other options
Auto commit risks loss; committing before processing risks loss; exactly-once semantics require special setup.Final Answer:
Manually commit offsets after processing and implement idempotent processing logic -> Option DQuick Check:
Manual commit + idempotency = best at-least-once practice [OK]
- Relying on auto commit for at-least-once
- Committing offsets before processing
- Ignoring idempotent processing importance
Ready to prove it?
Pass the test and this pattern moves unknown
