Skip to content

CORE-15436 delete topic enable#29365

Merged
michael-redpanda merged 5 commits into
redpanda-data:devfrom
michael-redpanda:kafka/CORE-15436-delete-topic-enable
Feb 5, 2026
Merged

CORE-15436 delete topic enable#29365
michael-redpanda merged 5 commits into
redpanda-data:devfrom
michael-redpanda:kafka/CORE-15436-delete-topic-enable

Conversation

@michael-redpanda
Copy link
Copy Markdown
Contributor

Add delete_topic_enable cluster configuration

This PR implements a new cluster configuration property delete_topic_enable that allows administrators to globally disable topic deletion via the Kafka DeleteTopics API, similar to Apache Kafka's delete.topic.enable broker configuration.

Motivation: Customers have requested the ability to prevent accidental topic deletion in production environments. While kafka_nodelete_topics protects specific topics, there was no way to globally disable topic deletion as a safety measure.

Implementation:

  • Added delete_topic_enable as a dynamic boolean cluster config (default: true for backward compatibility)
  • When set to false, all DeleteTopics requests are rejected with error code 73 (TOPIC_DELETION_DISABLED) for API v3+, or INVALID_REQUEST for older clients
  • The check happens before authorization, ensuring consistent behavior regardless of topic existence or permissions
  • This is a safety setting that cannot be overridden by superusers

Fixes #29347

Backports Required

  • none - not a bug fix

Release Notes

Features

  • Added delete_topic_enable cluster configuration property to globally enable or disable topic deletion via the Kafka API. When set to false, all topic deletion requests are rejected with error code TOPIC_DELETION_DISABLED (73). Default is true for backward compatibility. This setting works independently of kafka_nodelete_topics, which continues to protect specific topics regardless of this setting.

@michael-redpanda michael-redpanda self-assigned this Jan 22, 2026
@michael-redpanda michael-redpanda requested a review from a team as a code owner January 22, 2026 17:11
Copilot AI review requested due to automatic review settings January 22, 2026 17:11
@michael-redpanda michael-redpanda requested review from a team, dotnwat and pgellert and removed request for a team January 22, 2026 17:11
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements the delete_topic_enable cluster configuration property to provide a global safety mechanism for preventing topic deletion via the Kafka DeleteTopics API, similar to Apache Kafka's delete.topic.enable broker configuration.

Changes:

  • Added a new boolean cluster configuration property delete_topic_enable (default: true) that globally controls topic deletion
  • Implemented early rejection of DeleteTopics requests when the setting is disabled, returning TOPIC_DELETION_DISABLED (error 73) for API v3+ or INVALID_REQUEST for older API versions
  • Added comprehensive test coverage in both C++ unit tests and Python integration tests to verify the feature works correctly

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/v/config/configuration.h Declares the new delete_topic_enable property field in the configuration structure
src/v/config/configuration.cc Defines the delete_topic_enable property with documentation, default value, and metadata
src/v/kafka/server/server.cc Implements the early-rejection logic in the DeleteTopics handler to check the configuration and return appropriate error codes
src/v/kafka/server/tests/delete_topics_test.cc Adds C++ unit tests verifying behavior with the setting disabled, for different API versions, and when re-enabled
tests/rptest/tests/delete_topic_enable_test.py Adds Python integration tests covering disabled state, default behavior, interaction with kafka_nodelete_topics, and multiple topic deletion attempts

@michael-redpanda michael-redpanda force-pushed the kafka/CORE-15436-delete-topic-enable branch from 5f865ff to 6d4a767 Compare January 22, 2026 17:12
@michael-redpanda
Copy link
Copy Markdown
Contributor Author

Force push:

  • Fixed python lint issue

@michael-redpanda michael-redpanda changed the title ORE-15436 delete topic enable CORE-15436 delete topic enable Jan 22, 2026
@michael-redpanda michael-redpanda force-pushed the kafka/CORE-15436-delete-topic-enable branch 2 times, most recently from 18f3bdc to d1bb385 Compare January 22, 2026 17:41
@michael-redpanda
Copy link
Copy Markdown
Contributor Author

Force push:

  • Fixed type checking in ducktape test

@vbotbuildovich
Copy link
Copy Markdown
Collaborator

CI test results

test results on build#79504
test_class test_method test_arguments test_kind job_url test_status passed reason test_history
Datalake3rdPartyMaintenanceTest test_e2e_basic {"catalog_type": "nessie", "cloud_storage_type": 1, "query_engine": "trino"} integration https://buildkite.com/redpanda/redpanda/builds/79504#019be6d5-4329-4905-93b5-58ca0b2ac95e FLAKY 10/11 Test PASSES after retries.No significant increase in flaky rate(baseline=0.0000, p0=1.0000, reject_threshold=0.0100. adj_baseline=0.1000, p1=0.3487, trust_threshold=0.5000) https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=Datalake3rdPartyMaintenanceTest&test_method=test_e2e_basic
PartitionForceReconfigurationTest test_basic_reconfiguration {"acks": 1, "controller_snapshots": false, "restart": true} integration https://buildkite.com/redpanda/redpanda/builds/79504#019be6d5-4331-413d-8f2a-b413c7bc8300 FLAKY 10/11 Test PASSES after retries.No significant increase in flaky rate(baseline=0.0000, p0=1.0000, reject_threshold=0.0100. adj_baseline=0.1000, p1=0.3487, trust_threshold=0.5000) https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=PartitionForceReconfigurationTest&test_method=test_basic_reconfiguration

Copy link
Copy Markdown
Contributor

@IoannisRP IoannisRP left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

Add a new cluster configuration property `delete_topic_enable` that
allows administrators to globally disable topic deletion via the Kafka
DeleteTopics API, similar to Apache Kafka's `delete.topic.enable`.

When set to false, all topic deletion requests are rejected with error
code 73 (TOPIC_DELETION_DISABLED). This is a safety setting that cannot
be overridden by superusers. Default is true for backward compatibility.

Refs: CORE-15346

Signed-off-by: Michael Boquard <michael@redpanda.com>
Add topic_deletion_disabled to the license_required_feature enum and
report it when delete_topic_enable is disabled. This allows license
enforcement for clusters that have topic deletion disabled.
Check the delete_topic_enable config at the start of the DeleteTopics
handler. When disabled, reject all deletion requests with error code 73
(TOPIC_DELETION_DISABLED) for API v3+, or INVALID_REQUEST for older
clients that don't understand error 73.

The check is placed before any validation or authorization to ensure
fast rejection and consistent behavior regardless of topic existence
or permissions.

Also adds unit tests verifying:
- Error code 73 returned for modern API versions
- INVALID_REQUEST returned for old API versions (< v3)
- Dynamic config toggle works correctly

Refs: CORE-15346

Signed-off-by: Michael Boquard <michael@redpanda.com>
Add ducktape integration tests verifying the delete_topic_enable
cluster configuration:

- test_delete_topic_enable_disabled: Topics cannot be deleted when
  config is false, returns TOPIC_DELETION_DISABLED error
- test_delete_topic_enable_default: Default value (true) allows
  deletion for backward compatibility
- test_nodelete_topics_still_protected: kafka_nodelete_topics is still
  honored when delete_topic_enable is true
- test_delete_topic_enable_multiple_topics: All topics rejected when
  config is false

Refs: CORE-15346

Signed-off-by: Michael Boquard <michael@redpanda.com>
Add topic_deletion_disabled feature to the enterprise features license
test. The feature is enabled when delete_topic_enable is set to false.
@michael-redpanda michael-redpanda force-pushed the kafka/CORE-15436-delete-topic-enable branch from d1bb385 to b71750e Compare February 2, 2026 20:45
@michael-redpanda
Copy link
Copy Markdown
Contributor Author

Force push:

  • Converted to enterprise property

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

1_MiB)
, delete_topic_enable(
*this,
false,
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The delete_topic_enable property is initialized with false as the second parameter to the constructor, but according to the PR description and line 1768, the default value should be true for backward compatibility. The second parameter appears to be the enterprise license requirement flag (not the default value), and the actual default value true is passed as the last parameter on line 1768. However, passing false for the license requirement means this feature does NOT require an enterprise license to use. According to the enterprise feature tracking in feature_manager.cc (lines 281-283) and the test enterprise_features_license_test.py, this feature should require an enterprise license when DISABLED (when set to false). The license requirement flag should be true to indicate that disabling topic deletion is an enterprise feature.

Suggested change
false,
true,

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the second parameter is the restricted value. All good here.

const auto ec = (ctx.header().version >= api_version(3))
? error_code::topic_deletion_disabled
: error_code::invalid_request;
const auto err_msg = "Topic deletion is disabled.";
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message is constructed as a const auto and captured by value in the lambda expressions below. This results in the string literal being copied multiple times for each topic in the request. Consider using std::string_view or moving the message construction inside the response building logic to avoid unnecessary copies, or capture by reference if the lifetime is guaranteed.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is just a const char* so copilot is wrong. However, why it a const char* instead of const char[] is... very c++...

I would argue that auto should be replaced with an explicit type (probs string_view as the comment says... but for very different reasons)

Copy link
Copy Markdown
Contributor

@IoannisRP IoannisRP left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good 👍

Comment on lines +281 to +283
report.set(
features::license_required_feature::topic_deletion_disabled,
!cfg.delete_topic_enable());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, an extra inversion won't confuse anyone... it's fine 😅

(i see why it needs to be like that, but i had to call it out 🙄)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah... i struggled with this one for that reason...

const auto ec = (ctx.header().version >= api_version(3))
? error_code::topic_deletion_disabled
: error_code::invalid_request;
const auto err_msg = "Topic deletion is disabled.";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is just a const char* so copilot is wrong. However, why it a const char* instead of const char[] is... very c++...

I would argue that auto should be replaced with an explicit type (probs string_view as the comment says... but for very different reasons)

1_MiB)
, delete_topic_enable(
*this,
false,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the second parameter is the restricted value. All good here.

@michael-redpanda michael-redpanda merged commit 9adc7e2 into redpanda-data:dev Feb 5, 2026
21 of 29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support delete.topic.enable similar to Kafka

4 participants