← Back to list

Kafka Offset Commit Strategies — What Actually Works in Production

There’s a moment in every Kafka system where everything looks fine — consumers are running, lag is low, throughput is healthy — and yet…

Arvind Kumar in Codefarm(Java Ecosystem) · 2026-04-16 14:31 · 118 claps · 4.4 min read paywalled
#kafka #apache-kafka #event-driven-architecture #kafka-offset #system-design-interview
Open on Medium ↗
Wiki topics: 🏛️ · Architecture 🏃 · Running & Endurance

Kafka Offset Commit Strategies — What Actually Works in Production

There’s a moment in every Kafka system where everything looks fine — consumers are running, lag is low, throughput is healthy — and yet, quietly, data is being lost or duplicated.

That moment almost always traces back to one thing: offset management.

Offsets are deceptively simple. A number that says, “I’ve processed up to here.”

But in a distributed system, that number becomes your contract with reality.

Let’s walk through the real strategies, their failure modes, and how to implement them correctly in Spring Boot — without glossing over the uncomfortable edges.

Full story for non-members | codefarm.in

1. What an Offset Commit Really Means

In Apache Kafka, committing an offset is not tied to processing. Kafka does not know if your business logic succeeded.

It only knows:

“The consumer claims it is safe to move forward.”

This creates three broad models:

  • Kafka decides (auto commit)
  • You decide (manual commit)
  • Kafka + you decide atomically (transactions)

Everything else is a variation of these.

2. Auto Commit — Fast, and Quietly Dangerous

Configuration

spring:
  kafka:
    consumer:
      enable-auto-commit: true
      auto-offset-reset: earliest

Kafka periodically commits the last polled offset.

Failure Scenario

Offsets are committed before processing completes.

Result: Data loss

When it works

  • Logs, analytics, telemetry
  • Systems where losing a few messages is acceptable
  • High-throughput pipelines prioritizing speed

3. Manual Commit — The Default for Real Systems

Now the control shifts to you.

You decide when a message is “done.”

3.1 Manual Commit (Batched)

Configuration

spring:
  kafka:
    consumer:
      enable-auto-commit: false
    listener:
      ack-mode: manual

Code

@KafkaListener(topics = "orders")
public void consume(String message, Acknowledgment ack) {
    process(message);
    ack.acknowledge();
}

Failure Behavior

Result: At-least-once delivery

Trade-off

  • Safe against data loss
  • Possible duplicates

3.2 Manual Immediate Commit

spring:
  kafka:
    listener:
      ack-mode: manual_immediate

Each acknowledgment triggers an immediate commit.

Trade-off

  • Lower duplication window
  • Higher commit overhead

4. Batch Processing — Throughput Optimization

Instead of processing one record at a time:

Configuration

spring:
  kafka:
    listener:
      type: batch
      ack-mode: manual

Code

@KafkaListener(topics = "orders")
public void consume(List<String> messages, Acknowledgment ack) {

for (String msg : messages) {
        process(msg);
    }
    ack.acknowledge();
}

Problem

If one message fails, the entire batch is retried.

Practical Fix

for (String msg : messages) {
    try {
        process(msg);
    } catch (Exception e) {
        sendToDLQ(msg);
    }
}
ack.acknowledge();

5. Per-Record Commit — Precision at a Cost

@KafkaListener(topics = "orders")
public void consume(ConsumerRecord<String, String> record,
                    Acknowledgment ack) {

process(record.value());
    ack.acknowledge();
}

Trade-off

  • Strong safety guarantees
  • Increased network overhead
  • Lower throughput

6. Transactions — Closing the Consistency Gap

This is where Kafka becomes a proper data pipeline engine.

You can atomically:

  • Consume a record
  • Produce a new record
  • Commit the offset

Configuration

spring:
  kafka:
    producer:
      transaction-id-prefix: tx-
    consumer:
      enable-auto-commit: false
      isolation-level: read_committed

Code

@KafkaListener(topics = "input-topic")
@Transactional
public void process(ConsumerRecord<String, String> record) {

String result = transform(record.value());
    kafkaTemplate.send("output-topic", result);
}

Failure Case

Result

  • No partial writes
  • No duplicate downstream messages
  • Exactly-once semantics

7. Rebalancing — The Hidden Offset Killer

Even with perfect logic, rebalances can break assumptions.

Scenario

  • Consumer takes too long to process
  • max.poll.interval.ms exceeded
  • Kafka triggers rebalance

Result

  • Uncommitted work is reprocessed
  • Duplicates appear

8. Critical Configurations That Shape Behavior

These are not tuning knobs. They define system behavior.

max.poll.records

Controls batch size.

  • Too high → processing delays
  • Too low → underutilization

max.poll.interval.ms

  • Upper bound on processing time before rebalance.

session.timeout.ms

  • Failure detection latency.

fetch.min.bytes & fetch.max.wait.ms

  • Batch efficiency vs latency.

isolation.level=read_committed

  • Mandatory for transactional consumers.

9. Strategy Selection by Use Case

Think in terms of failure cost:

Low-cost data (logs, metrics)

  • Auto commit
  • High throughput
  • Acceptable loss

Business-critical processing (orders, workflows)

  • Manual commit
  • Retry + DLQ
  • Idempotent logic

Financial correctness (payments)

  • Manual immediate OR transactions
  • Strict retry control
  • Audit trails

Kafka-to-Kafka pipelines

  • Transactions
  • Exactly-once processing

Closing Thoughts

Offset strategy does not guarantee correctness.

Even with transactions:

  • Rebalances happen
  • Retries happen
  • Consumers restart

You will see duplicates.

The real contract is:

Your processing must be idempotent.

Without that, no offset strategy will save you.

Most systems don’t fail because Kafka is unreliable. They fail because offset commits are treated as a configuration detail rather than a correctness boundary.

Once you start thinking of offsets as a distributed agreement about truth, the design decisions become clearer — and harder to ignore.

Next topics to dig deeper into

  • Retry strategies with backoff
  • Dead Letter Queues
  • Idempotency with Redis or database constraints
  • Chaos testing with forced rebalances

That’s where offset management stops being theory and starts becoming engineering.

Liked this deep dive story? If Yes Please 👏 Clap(50) | 📤 Share | 🔔 Follow

=======

Below is a collection of all related stories in one place

[embed]List: Apache Kafka | Kafka Deep Dive | Kafka Interview Questions | Curated by Arvind Kumar | Medium Apache Kafka | Kafka Deep Dive | Kafka Interview Questions · All about Kafka and its real world use cases. If you…codefarm0.medium.com


메타데이터
post_id
aed7eb9af7ad
slug
kafka-offset-commit-strategies-what-actually-works-in-production-aed7eb9af7ad
url
https://medium.com/codefarm-java-ecosystem/kafka-offset-commit-strategies-what-actually-works-in-production-aed7eb9af7ad
canonical_url
https://medium.com/codefarm-java-ecosystem/kafka-offset-commit-strategies-what-actually-works-in-production-aed7eb9af7ad
author_url
https://medium.com/@codefarm0
status
ok
fetched_at
2026-06-15 20:49:13