Skip to content

Best tools to manage poison pills in Kafka

Comparisons
Chad Harris·September 22, 2026·12 min read·Updated

Kafka poison pill tools work at two layers: frameworks inside the consumer that isolate a bad record automatically (Spring Kafka’s error handlers, Kafka Streams exception handlers, Kafka Connect’s error tolerance, share group delivery limits), and operator tools that find and skip one after it stalls a partition (the Kafka CLI, kcat, Kpow, AKHQ, Kafbat UI, Conduktor Console).

Most production teams need one from each layer, because the framework only catches the failures it was written for. It sits in the second layer. A partition that is stuck right now is better served by how to find and skip a poison pill in Kafka, which has the commands in order. The complete Kafka guide covers the rest of the tooling picture.

At a glance

Eight options are scored here on this page's five weighted criteria, 70 points in all. The rubric is weighted: Who can do it, and the record counts three times, and Isolates before the loop, Finds record and error, Skips it safely and Keeps the record count once. The five listed first, of eight, each out of 70: Kpow 56, which takes its best score on Finds record and error (10 out of 10) and its lowest on Isolates before the loop (0 out of 10); Spring Kafka error handling 38; AKHQ and Kafbat UI 37; Kafka Connect error tolerance 32; Kafka Streams exception handlers 25.

Isolating poison pills inside the consumer

These frameworks act without a human, which makes them the first line of defence. Each only covers the application type it belongs to.

Spring Kafka error-handling deserializer and dead letter publishing. Spring’s documentation is direct about the gap: when a deserializer fails, “Spring has no way to handle the problem, because it occurs before the poll() returns.” The ErrorHandlingDeserializer, described in Spring Kafka’s serialization documentation, wraps the real deserializer and, on failure, returns a null value with the exception and raw bytes in a header. The DefaultErrorHandler, per Spring Kafka’s error handling documentation, then treats DeserializationException as fatal, skipping retries, and a DeadLetterPublishingRecoverer publishes the record to <originalTopic>-dlt on the same partition by default. For processing errors the handler retries and then logs the record after ten failures by default, unless you configure a recoverer.

Spring Kafka non-blocking retries. @RetryableTopic, covered in Spring Kafka’s non-blocking retries documentation, moves a failing record to back-off retry topics and finally a dead letter topic, so the main partition keeps flowing. The trade is ordering, because later records overtake the one being retried.

Kafka Streams exception handlers. The deserialization.exception.handler setting in the Kafka Streams configuration reference chooses LogAndFailExceptionHandler or LogAndContinueExceptionHandler, and processing.exception.handler does the same for errors in your topology. A dead letter topic means a custom handler, and the Apache documentation notes that those writes are side effects outside Streams’ processing guarantees.

Kafka Connect error tolerance. For sink connectors, errors.tolerance=all skips problematic records and errors.deadletterqueue.topic.name sends them to a DLQ topic, per the Kafka Connect configuration reference. errors.deadletterqueue.context.headers.enable defaults to false, and it is worth turning on so each DLQ record carries its error context.

Share groups. Queues for Kafka count delivery attempts per record. Once a record reaches group.share.delivery.count.limit (default 5, per the broker configuration reference), KIP-932 moves it to the Archived state instead of delivering it again. That is a broker-side answer, but only for consumers that use share groups.

Any of these that writes to a retry or DLQ topic needs a way out of its own loop. The failure to design against is an ETL that reads from and writes back to the same DLQ or retry topic, so every failure re-enters the loop and the backlog grows without end. A retry count header, checked before each re-publish, breaks it.

Poison pill tools compared

The table scores every option on the five criteria in order. Consumer-side frameworks come first, operator tools second.

Rank Tool Isolates automatically Finds the record and the error Skips it safely Keeps the record Who can do it, and the record of it Source
1 Kpow No, it is an operator tool Yes, Data Inspect’s Poison only mode lists records that failed to deserialize, with partition and offset Yes, a partition-level Skip offset action, scheduled until the group is EMPTY Yes, Clone to topic copies records byte for byte RBAC, staged mutations for approval, and an audit log (Enterprise) Kpow docs
2 Spring Kafka ErrorHandlingDeserializer + DeadLetterPublishingRecoverer Yes, for Spring listeners, including deserialization failures The exception and raw bytes travel in headers The container commits past the record once it is recovered Yes, to <topic>-dlt Whatever deploys the application Spring Kafka docs
3 Spring Kafka @RetryableTopic Yes, for processing failures, through retry topics Retry and DLT topics hold the record The main partition keeps moving Yes, in the final DLT Whatever deploys the application Spring Kafka docs
4 Kafka Connect errors.tolerance + DLQ Yes, for converter and transform errors in sink connectors DLQ records carry error headers when enabled Tolerated records are skipped by the task Yes, on the DLQ topic Whoever edits the connector config Apache Kafka docs
5 AKHQ No Browses topic data in the UI Per-partition offset update, gated by the UPDATE_OFFSET role Can produce records back to a topic Roles, plus opt-in audit events to a Kafka topic akhq.io
6 Kafbat UI No Browses messages in the UI Offset reset, gated by the RESET_OFFSETS permission Can produce messages back to a topic RBAC, plus an audit log to a topic or the console Kafbat UI docs
7 Kafka Streams exception handlers Yes, log-and-continue or a custom handler Logs, or a quarantine topic you write to Log-and-continue skips inside the app Only with a custom handler Whatever deploys the application Apache Kafka docs
8 Share groups (KIP-932) Yes, after the delivery count limit Records move to the Archived state The broker stops delivering it Archived, not copied to a topic Broker and group configuration Apache Kafka docs
9 kafka-console-consumer.sh + kafka-consumer-groups.sh No Yes, read one offset from one partition, then work out the error yourself Yes, --shift-by 1 on topic:partition, dry run by default, group must be inactive Only if you copy the bytes yourself Whoever holds CLI credentials, with no audit Apache Kafka docs
10 kcat No Reads one offset and prints raw bytes, good for a hex dump No offset reset Can re-produce what you captured Whoever holds credentials, with no audit GitHub: edenhill/kcat
11 Conduktor Console No Browses and consumes topic data in the UI Offset reset scoped to topic-partitions, with shift-by and a preview, group must be inactive Can produce records back to a topic RBAC with a consumer group Reset permission, and an audit log Conduktor’s documentation, Consumer groups, Topics, RBAC and Audit logs pages

How the options score

On isolating the record automatically, Spring Kafka is the most complete framework, because the ErrorHandlingDeserializer closes the deserialization gap and the recoverer keeps the record. Kafka Connect is the only option that needs no code, and share groups are the only broker-side answer. None of the operator tools, Kpow included, stop a pill from stalling a partition in the first place.

On finding the record and the error, Kpow leads. Its Poison only mode returns nothing but the records that failed against the deserializer you chose, and Retain mode keeps them in normal results flagged as “Deserialization exception”. AKHQ, Kafbat UI and Conduktor show you a record once you know where to look. The CLI and kcat get you the bytes, and the diagnosis is yours.

On skipping safely, the CLI, Kpow, AKHQ, Kafbat UI and Conduktor can all move one partition’s offset. The CLI previews by default and Conduktor has a preview step. Kpow schedules the skip and applies it once the group is EMPTY, so it cannot fire against running consumers.

On keeping the record, the consumer-side frameworks win, because they write the DLQ record at the moment of failure with the error attached. Among operator tools, Kpow’s Clone to topic and the produce features in AKHQ, Kafbat UI and Conduktor all let you put a copy somewhere before skipping. What to do with the copies afterwards is compared in the best tools to manage a dead letter queue.

On governance, Kpow gives the most control: role-based permissions per action, staged mutations that need an administrator’s approval, temporary policies that grant GROUP_EDIT for a fixed window, and an audit log of every mutation. AKHQ and Kafbat UI both have roles and an opt-in audit trail you read from a Kafka topic. The CLI has none of this.

F1 The two layers of poison pill handling /resources/kafka/
Inside the consumer Operator tools
When it acts Automatically, the moment a record fails After a partition has stalled and someone is paged
Examples ErrorHandlingDeserializer, DeadLetterPublishingRecoverer, Streams exception handlers, Connect errors.tolerance kafka-consumer-groups.sh, kcat, Kpow, AKHQ, Kafbat UI, Conduktor Console
What it needs Code or config shipped with every consumer Access to the cluster, and a stopped consumer group for any offset change
What it leaves behind The record on a dead letter topic, with error headers if configured An audit entry, if the tool keeps one

Each option in detail

Rank 1

56 out of 70 Total

Try Kpow in the live demo No signup needed.

Type
Kafka UI
Find
Data Inspect, Poison only mode
Enterprise
Staged mutations, audit log, bulk clone
Isolates before the loop
0 out of 10
Finds record and error
10 out of 10
Skips it safely
9 out of 10
Keeps the record
7 out of 10
Who can do it, and the record ×3 weight, this criterion counts 3 times toward the total
10 out of 10
Why these scores for Kpow
Isolates before the loop 0 out of 10
The answer is “No, it is an operator tool”, because “None of the operator tools, Kpow included, stop a pill from stalling a partition in the first place.”
Finds record and error 10 out of 10
Poison only returns only records that failed the chosen deserializer and Retain flags them with partition and offset, so “On finding the record and the error, Kpow leads”.
Skips it safely 9 out of 10
Skip offset works at partition level and is scheduled until the group is EMPTY, so “it cannot fire against running consumers”. No preview step is named, so not 10.
Keeps the record 7 out of 10
Clone to topic copies records byte for byte before the skip, but “the consumer-side frameworks win” on keeping, since they write at the moment of failure with the error attached.
Who can do it, and the record 10 out of 10
Per-action roles, staged mutations needing an administrator’s approval, temporary GROUP_EDIT policies and an audit log of every mutation mean “Kpow gives the most control”.

What it does. Data Inspect finds malformed records across topics, Skip offset moves one partition past a bad record, Clone to topic keeps a byte-level copy, and every action runs through Kpow’s RBAC and audit log.

Where it wins. Finding the bad record and governing the skip. The Poison only mode and schema metadata turn “which record is it” into a query, and staged mutations turn “who is allowed” into a policy.

Where it falls short. It does not isolate anything automatically, so it complements a consumer-side framework rather than replacing one. Staged mutations, the audit log and bulk clone are Enterprise features.

Staying patched. Kpow’s release notes name the CVEs each release remediates, and the 96.4 image built on 5 August 2026 bundles 311 dependencies of which one carries a high or critical advisory, none of them published before that release. That is not a claim to patch faster than a community project: Kpow’s own dependency remediation has run from 14 to 128 days, and the current image still ships CVE-2026-75595 in netty, a 9.1 critical public since 19 August 2026, unpatched. What a licence buys here is not a different deployment model, because Kpow is self-hosted too. It is a company contracted to ship the fix. Every dependency figure on this page was read on 24 September 2026 from the published artefacts and from nvd.nist.gov.

Rank 2

Spring Kafka error handling

docs.spring.io

38 out of 70 Total

Type
Consumer-side framework
Covers
Spring listeners, deserialization included
Dead letter topic
<originalTopic>-dlt
Isolates before the loop
10 out of 10
Finds record and error
6 out of 10
Skips it safely
7 out of 10
Keeps the record
9 out of 10
Who can do it, and the record ×3 weight, this criterion counts 3 times toward the total
2 out of 10
Why these scores for Spring Kafka error handling
Isolates before the loop 10 out of 10
The page’s summary says “Spring Kafka is the most complete framework”, because ErrorHandlingDeserializer closes the deserialization gap before poll() returns and @RetryableTopic covers processing failures.
Finds record and error 6 out of 10
The exception and raw bytes travel in headers on the DLT record, so the why is attached, but reading it still means consuming the DLT, and the page credits Kpow, not Spring, with finding.
Skips it safely 7 out of 10
The container commits past the record once it is recovered, and @RetryableTopic keeps the main partition moving, at the cost of ordering. It is automatic, but there is no preview or per-partition operator step.
Keeps the record 9 out of 10
It writes the record to -dlt, and “the consumer-side frameworks win” on keeping the record; it stops short of 10 because the -dlt resolver needs at least as many partitions as the original.
Who can do it, and the record 2 out of 10
Both rows of this page’s table give “Whatever deploys the application”, and it has no access control or audit of its own.

What it does. ErrorHandlingDeserializer catches deserialization failures, DefaultErrorHandler retries or recovers, and DeadLetterPublishingRecoverer writes the failed record to a dead letter topic.

Where it wins. It is the most complete automatic path for JVM consumers, and it handles the deserialization case that plain consumers cannot.

Where it falls short. It only protects Spring applications, and the default -dlt resolver needs the dead letter topic to have at least as many partitions as the original.

Rank 3

AKHQ and Kafbat UI

akhq.io, github.com/kafbat/kafka-ui

37 out of 70 Total

Type
Open-source Kafka UIs
Skip permission
UPDATE_OFFSET (AKHQ), RESET_OFFSETS (Kafbat UI)
Isolates before the loop
0 out of 10
Finds record and error
5 out of 10
Skips it safely
6 out of 10
Keeps the record
5 out of 10
Who can do it, and the record ×3 weight, this criterion counts 3 times toward the total
7 out of 10
Why these scores for AKHQ and Kafbat UI
Isolates before the loop 0 out of 10
Both score “No”, because operator tools act after the partition has stalled.
Finds record and error 5 out of 10
They “show you a record once you know where to look”, and finding it on a busy topic “starts from its offset”, from the consumer’s error or the CLI.
Skips it safely 6 out of 10
AKHQ gates a per-partition offset update behind UPDATE_OFFSET and Kafbat UI gates an offset reset behind RESET_OFFSETS. No preview or EMPTY scheduling is named for either.
Keeps the record 5 out of 10
Both can produce records back to a topic, which is a produce, not the byte-for-byte clone the page credits to Kpow.
Who can do it, and the record 7 out of 10
Between them, “both have roles and an opt-in audit trail you read from a Kafka topic”, and that topic is yours to read and retain.

What they do. Open-source UIs that browse topic data, change consumer group offsets and produce records, each with role-based permissions and an opt-in audit trail written to Kafka.

Where they win. Free, and enough to find a record by offset and skip it without a jumpbox.

Where they fall short. Finding the bad record on a busy topic starts from its offset, which you get from the consumer’s error or the CLI. The audit trail is a Kafka topic you have to read and retain yourself.

Staying patched. Both are Apache-2.0 and community-maintained, and the patching question is not whether either project has a CVE of its own. It is what the current release ships. AKHQ 0.28.0, cut on 6 August 2026, bundles 270 libraries of which 18 carry a high or critical advisory, 16 of them already public with fixes available on the day it shipped and the oldest now open 108 days. Kafbat UI last released v1.5.0 in April 2026, and at least 20 high or critical advisories have been published against what it bundles in the 157 days since, with no release to carry a fix; only 150 of its 266 jars could be measured, so that number is a floor and the two are not comparable on it.

Rank 4

Kafka Connect error tolerance

kafka.apache.org

32 out of 70 Total

Type
Consumer-side framework
Setup
errors.tolerance=all, configuration only
DLQ
Sink connectors only
Isolates before the loop
7 out of 10
Finds record and error
5 out of 10
Skips it safely
6 out of 10
Keeps the record
8 out of 10
Who can do it, and the record ×3 weight, this criterion counts 3 times toward the total
2 out of 10
Why these scores for Kafka Connect error tolerance
Isolates before the loop 7 out of 10
It handles converter and transform errors in sink connectors, and the page’s summary calls it “the only option that needs no code”.
Finds record and error 5 out of 10
DLQ records carry error headers only when errors.deadletterqueue.context.headers.enable is on, which defaults to false.
Skips it safely 6 out of 10
The task skips tolerated records automatically, with no operator preview or scope.
Keeps the record 8 out of 10
It keeps the record on the DLQ topic, and consumer-side frameworks “win” on keeping the record. It sits below Spring because the DLQ is sink-only and context headers are off by default.
Who can do it, and the record 2 out of 10
Control rests with “Whoever edits the connector config”, and it has nothing of its own.

What it does. Skips records that fail conversion or transformation and, for sink connectors, writes them to a DLQ topic.

Where it wins. Configuration only, no code.

Where it falls short. It covers converter and transform errors, the DLQ is sink-only, and the context headers are off unless you enable them.

Rank 5

Kafka Streams exception handlers

kafka.apache.org

25 out of 70 Total

Type
Consumer-side framework
Handlers
LogAndFail or LogAndContinue
Dead letter topic
Custom handler you write
Isolates before the loop
7 out of 10
Finds record and error
3 out of 10
Skips it safely
6 out of 10
Keeps the record
3 out of 10
Who can do it, and the record ×3 weight, this criterion counts 3 times toward the total
2 out of 10
Why these scores for Kafka Streams exception handlers
Isolates before the loop 7 out of 10
Log-and-continue or a custom handler covers deserialize, process and produce errors, but only for Streams applications.
Finds record and error 3 out of 10
It leaves you “Logs, or a quarantine topic you write to”, so nothing finds the record unless you build it.
Skips it safely 6 out of 10
Log-and-continue skips inside the app, and the page’s own prose says it “keeps a topology running through bad data”, with no operator control over the skip.
Keeps the record 3 out of 10
The page’s own prose says “Log-and-continue discards the record”, and keeping it needs a custom handler, outside Streams’ processing guarantees.
Who can do it, and the record 2 out of 10
Governance falls to “Whatever deploys the application”, and it has nothing of its own.

What it does. Chooses whether a record that fails to deserialize, process or produce stops the application or is logged and skipped.

Where it wins. It is built in, and log-and-continue keeps a topology running through bad data.

Where it falls short. Log-and-continue discards the record. Keeping it means a custom handler writing to a quarantine topic, outside Streams’ processing guarantees.

Rank 6

Share groups

kafka.apache.org

22 out of 70 Total

Type
Broker-side delivery limit
Setting
group.share.delivery.count.limit, default 5
Scope
Share group consumers only
Isolates before the loop
6 out of 10
Finds record and error
1 out of 10
Skips it safely
7 out of 10
Keeps the record
2 out of 10
Who can do it, and the record ×3 weight, this criterion counts 3 times toward the total
2 out of 10
Why these scores for Share groups
Isolates before the loop 6 out of 10
By the page’s summary, “share groups are the only broker-side answer”, but only after the delivery count limit (default 5) and only for share group consumers.
Finds record and error 1 out of 10
Records move to the Archived state, and the page names no way to see the record or its error.
Skips it safely 7 out of 10
The broker stops delivering it, so “a poison pill cannot loop forever”. That is enforced by the broker, not by client code.
Keeps the record 2 out of 10
The record is “Archived, not copied to a topic”, so it is not copied anywhere you can repair it from.
Who can do it, and the record 2 out of 10
It is governed by “Broker and group configuration”, with no per-action permission or audit described.

What it does. Counts deliveries per record and archives a record that reaches the limit.

Where it wins. The broker enforces it, so a poison pill cannot loop forever.

Where it falls short. It only applies to share group consumers, and an archived record is not copied anywhere you can repair it from.

Rank 7

Kafka CLI and kcat

kafka.apache.org, github.com/edenhill/kcat

18 out of 70 Total

Type
Command-line tools
Skip
--reset-offsets --shift-by 1
Safety net
Dry run by default
Isolates before the loop
0 out of 10
Finds record and error
4 out of 10
Skips it safely
7 out of 10
Keeps the record
4 out of 10
Who can do it, and the record ×3 weight, this criterion counts 3 times toward the total
1 out of 10
Why these scores for Kafka CLI and kcat
Isolates before the loop 0 out of 10
Both are marked “No”, because “None of the operator tools... stop a pill from stalling a partition in the first place.”
Finds record and error 4 out of 10
The page’s summary says “The CLI and kcat get you the bytes, and the diagnosis is yours”, so kcat’s hex dump helps and the error is manual.
Skips it safely 7 out of 10
It takes --shift-by 1 on topic:partition, with a dry run by default, and the group must be inactive, while kcat has no offset reset. It ranks below Kpow and Conduktor because the --topic form without a partition shifts every partition, “easy to make under pressure”.
Keeps the record 4 out of 10
The console consumer keeps it “Only if you copy the bytes yourself”, and kcat “Can re-produce what you captured”.
Who can do it, and the record 1 out of 10
Access goes to “Whoever holds CLI credentials, with no audit”, the page’s own prose adds “No record of who ran what”, and “The CLI has none of this.”

What they do. kafka-console-consumer.sh or kcat reads the record at an offset, and kafka-consumer-groups.sh --reset-offsets --shift-by 1 skips it.

Where they win. Always available, and the dry-run default on offset resets is a real safety net.

Where they fall short. No record of who ran what, and the error diagnosis is manual. The --topic <topic> form without a partition shifts every partition, a mistake that is easy to make under pressure.

Rank 8

Conduktor Console

conduktor.io

42 out of 70 Total

Type
Commercial console
Skip
Topic-partition scope, shift-by, preview
Isolates before the loop
0 out of 10
Finds record and error
5 out of 10
Skips it safely
8 out of 10
Keeps the record
5 out of 10
Who can do it, and the record ×3 weight, this criterion counts 3 times toward the total
8 out of 10
Why these scores for Conduktor Console
Isolates before the loop 0 out of 10
It scores “No”, since “Like every operator tool, it acts after a partition has stalled”.
Finds record and error 5 out of 10
It browses and consumes topic data in the UI, and shows a record “once you know where to look”.
Skips it safely 8 out of 10
Its reset is scoped to topic-partitions with shift-by and a preview, and the group must be inactive, making it “as careful as the CLI’s, in a UI”, without the CLI’s all-partitions --topic slip.
Keeps the record 5 out of 10
It can produce records back to a topic, which is a produce, not a byte-level clone.
Who can do it, and the record 8 out of 10
It has RBAC with a consumer group Reset permission, and an audit log, a clean pass, not detailed as far as Kpow’s staged approvals.

What it does. A commercial console whose offset reset takes a topic-partition scope, supports shift-by, and previews the new offsets, and which requires the group to be inactive, per Conduktor’s documentation.

Where it wins. The reset flow’s scope and preview are as careful as the CLI’s, in a UI.

Where it falls short. Like every operator tool, it acts after a partition has stalled, so it needs a consumer-side framework alongside it.

How Factor House approaches poison pills

Kpow’s Data Inspect came out of this problem. Tom built its three deserialization options around a prospect whose topics mixed several schema types in one topic, including records that conformed to no schema. Drop record is the default and matches a plain consumer. Retain record keeps failed records in the results, flagged as “Deserialization exception”, so you can see which partition and offset failed. Poison only shows nothing else. When only certain schema IDs belong on a topic, a kJQ filter that asserts those IDs surfaces every record outside them. The Data Inspect documentation covers the modes and Clone to topic, and Clone to topic for DLQs explains the replay side.

The skip itself is the Skip offset action, which “increments the current offset by 1” at the partition level and waits for the group to reach EMPTY. On a governed cluster, staged mutations put an administrator’s approval in front of it, and the audit log records the request and the policies it was checked against. Kpow Community Edition includes consumer offset management and Data Inspect, so skipping a poison pill does not require an Enterprise licence. In the live Kpow demo you can try the finding half of the job: run Data Inspect against a topic, switch the deserialization option to Retain or Poison only, and open a consumer group to see the offset actions on each partition.

Kpow live demo

Test poison pill handling on a live cluster

Open the Kpow demo to inspect records that fail deserialization and see how a group offset change is scoped and audited.

Built for platform and data engineers running Kafka in production.

Try the Kpow demo

FAQ

What is the best tool for handling poison pills in Kafka?

Use a consumer-side framework to isolate them automatically, such as Spring Kafka’s ErrorHandlingDeserializer with a dead letter recoverer or Kafka Connect’s error tolerance. Add an operator tool for the ones that get through. Kpow is strongest at finding the malformed record and governing the skip, and the Kafka CLI is enough if one engineer owns the cluster and no audit is required.

Can Kafka skip a bad message automatically?

A plain consumer cannot. Spring Kafka, Kafka Streams and Kafka Connect can be configured to skip or dead-letter a failing record, and share groups archive a record after its delivery count limit. Otherwise someone has to move the committed offset with kafka-consumer-groups.sh or a UI.

Does Kafka have a built-in dead letter queue?

Only in Kafka Connect, for sink connectors. Everywhere else a DLQ is a pattern in your consumer code or framework. Dead letter queues in Kafka: patterns and pitfalls compares the implementation paths.

Do I need to stop my consumers to skip a poison pill?

Yes, for any offset change. Kafka only accepts new committed offsets for a group with no active members, whichever tool you use. Kpow schedules the change and applies it once the group is empty.

How these tools were scored

A poison pill is a record a consumer can never process, so it fails on the same offset every poll and the partition stops. Five criteria separate the tools, and each comes from how these incidents actually unfold.

1. Does it isolate the record before the consumer loops?

The cheapest poison pill is one the consumer routes aside on its own. Deserialization failures are the hard case, because they happen inside poll(), before your code sees the record. Incremental cooperative rebalancing reduces the blast radius when a consumer fails, but a poison pill will still get a partition stuck, so isolation has to be built into the consumer or its framework.

2. Can it find the record, and say why it failed?

Kafka’s metrics do not tell you a record is malformed. They tell you one partition’s lag is climbing. A tool scores well here if it shows the specific offset, the deserialization error and the schema it was expected to match, without you writing a one-off consumer to read the bytes. This matters beyond poison pills. As Chad Harris said in his talk on Kafka operational issues, data inspection tooling is essential for handling lost-message complaints, since the large majority of the time the message was on Kafka all along. When the failure is a decode error, how to diagnose a Kafka deserialization error covers finding its cause.

3. Can it skip the record safely?

Skipping means moving one partition’s committed offset forward by one, for one consumer group. The safe version previews the change, is scoped to a single partition, and only runs when the group has no active members. That last condition comes from Kafka, not from any tool. As Derek Troy-West, Factor House’s co-founder and CEO, puts it, Kafka itself requires a consumer group to be stopped before any changes can be applied, and every tool works within what Kafka allows.

4. Does the record survive?

Skipping drops the record for that group. A tool scores well if it keeps a copy somewhere you can repair and replay it from. His view on the destination is that the steady-state goal for a dead letter queue is effectively zero messages, because every entry is a signal that something failed and you now pay an operational tax to unwind it. Where a topic has several consumers, a pattern that works well is a retry topic per topic and consumer pair, so a replay only reaches the consumer that failed. Services should be idempotent so duplicates are safe, but he has seen several multi-million dollar incidents caused by services that were not.

5. Who is allowed to do it, and is it recorded?

A change to a consumer group’s committed offset can silently drop or reprocess data if it is scoped wrong. Tom Crowley, Factor House’s founding engineer, described the usual production path in 2021, a problem now covered in break-glass access with temporary policies: incrementing one offset means a VPN, a jumpbox, and “the right combination of bash commands against the Kafka cluster”, from a jumpbox that “generally has full access to the Kafka cluster” with “no audit log recording the actions being committed”. Tools that answer this well gate the skip behind a role or an approval and log who did it. The same question across every risky operation is covered in the best tools to control destructive Kafka operations.

Every option is scored from 0 to 10 on each criterion, from the evidence and sources this page cites, and the reason for each score is on its card. The criteria are weighted: Isolates before the loop counts once, Finds record and error counts once, Skips it safely counts once, Keeps the record counts once and Who can do it, and the record counts three times, for a total out of 70. Who can do it, and the record counts three times here, because skipping a record is a decision to lose data and it is usually taken at speed during an incident. Isolating before the loop, finding the record and the error, skipping it safely and keeping the record count once. This page is published by Factor House, which makes Kpow. Every option is scored on the same rubric and the same sources: Kpow's per-criterion scores are set the same way as every other option's and are not adjusted, and the weights apply to every option alike. Kpow ranks first on its total of 56 out of 70. The other options follow by total. Conduktor Console is listed last whatever its total; on its total of 42 it would place second.

Related reading