What if a consumer crashes before committing?
Solution and explanation
What happens
- The consumer stops sending heartbeats; after
session.timeout.ms(45 s default) the group coordinator removes it (or immediately if it closed cleanly). - A **rebalance** assigns its partitions to other consumers.
- The new owner starts from the **last committed offset**.
- Records that were processed after that commit are **processed again**.
Committed offset: 500
Processed 500–549, crashed before committing 550
New consumer reads from 500 → 500–549 processed twice
No records are lost (they are still in the log), but there are **duplicates**: this is at-least-once delivery.
Consequences
- Duplicate emails or SMS, double inventory reservations, or double payment attempts if the consumer is not idempotent.
- The processing time of the reprocessed range adds lag.
Making reprocessing safe
- **Idempotent processing:** upserts, unique constraints, "processed event id" tables:
INSERT INTO payments (payment_id, amount, status) VALUES (?, ?, 'CAPTURED')
ON DUPLICATE KEY UPDATE status = status;
- **Commit more often** (per record or small batches) to shrink the reprocessing window, at a performance cost.
- **Transactions** for Kafka-to-Kafka pipelines: output records and offset commit are atomic, so a crash rolls both back.
- **Store offsets with results** in the same database transaction.
- **Idempotency keys** when calling external APIs (payment gateways accept them).
Summary
After a crash, the partition's new owner resumes from the last committed offset, so records processed after that commit are redelivered; design consumers to be idempotent.
