Skip to content

storage: use max_ts for retention_ms#27383

Merged
WillemKauf merged 3 commits intoredpanda-data:devfrom
WillemKauf:min_time_based_retention
Sep 24, 2025
Merged

storage: use max_ts for retention_ms#27383
WillemKauf merged 3 commits intoredpanda-data:devfrom
WillemKauf:min_time_based_retention

Conversation

@WillemKauf
Copy link
Copy Markdown
Contributor

@WillemKauf WillemKauf commented Aug 26, 2025

The motivating case for broker_time_based_retention was the fact that records with bad timestamps produced in the future could lead to time-based retention being stuck indefinitely [1].

However, using the broker_ts can lead to unexpected behavior when e.g. replicating data from an existing cluster using MM2, as the timestamps of the Kafka records themselves are correctly preserved, but internally, redpanda data structures are not.

To avoid the potentially curious behavior of a divergence in retention enforcement, go back to using the max_timestamp for batches whose timestamps have been validated and unconditionally set in the produce path (see: v/kafka/server/handlers/produce_validation.cc) as of v25.3.1.

All of the changes described here are featured gated by the flag min_broker_batch_time_based_retention. This flag will only be default activated for new clusters created with minimum version v25.3.1. Older clusters can still opt into its behavior via the admin API, e.g.

curl  --request PUT http://localhost:9644/v1/features/validated_batch_timestamps -d '{"state":"active"}'

[1]:

Backports Required

  • none - not a bug fix
  • none - this is a backport
  • none - issue does not exist in previous branches
  • none - papercut/not impactful enough to backport
  • v25.2.x
  • v25.1.x
  • v24.3.x

Release Notes

Improvements

  • Respect existing record timestamps in the past even if broker_time_based_retention is enabled for enforcement of time-based local retention in the storage layer.

@vbotbuildovich
Copy link
Copy Markdown
Collaborator

vbotbuildovich commented Aug 26, 2025

CI test results

test results on build#71406
test_class test_method test_arguments test_kind job_url test_status passed reason
CloudStorageScrubberTest test_scrubber {"cloud_storage_type": 1} integration https://buildkite.com/redpanda/redpanda/builds/71406#0198e769-5dcd-4d24-a362-975405a4b1bc FLAKY 20/21 upstream reliability is '99.45799457994579'. current run reliability is '95.23809523809523'. drift is 4.2199 and the allowed drift is set to 50. The test should PASS
TimeQueryTest test_timequery_with_local_gc null integration https://buildkite.com/redpanda/redpanda/builds/71406#0198e76a-38a9-4db8-9781-0075d386a5d4 FLAKY 20/21 upstream reliability is '100.0'. current run reliability is '95.23809523809523'. drift is 4.7619 and the allowed drift is set to 50. The test should PASS
test results on build#71531
test_class test_method test_arguments test_kind job_url test_status passed reason
RandomNodeOperationsTest test_node_operations {"cloud_storage_type": 2, "compaction_mode": "sliding_window", "enable_failures": false, "mixed_versions": true, "with_iceberg": false} integration https://buildkite.com/redpanda/redpanda/builds/71531#0198f194-e693-4b15-baeb-b53216400f96 FLAKY 20/21 upstream reliability is '100.0'. current run reliability is '95.23809523809523'. drift is 4.7619 and the allowed drift is set to 50. The test should PASS
test results on build#72100
test_class test_method test_arguments test_kind job_url test_status passed reason
PartitionBalancerTest test_recovery_mode_rebalance_finish null integration https://buildkite.com/redpanda/redpanda/builds/72100#01993a31-a3a1-4b00-9e84-7e7c69a37fbd FLAKY 16/21 upstream reliability is '96.5909090909091'. current run reliability is '76.19047619047619'. drift is 20.40043 and the allowed drift is set to 50. The test should PASS
test results on build#72607
test_class test_method test_arguments test_kind job_url test_status passed reason test_history
ClusterRateQuotaTest test_client_response_throttle_mechanism null integration https://buildkite.com/redpanda/redpanda/builds/72607#0199639e-3245-445a-9f0d-58b84afa5b04 FLAKY 15/21 upstream reliability is '97.51243781094527'. current run reliability is '71.42857142857143'. drift is 26.08387 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=ClusterRateQuotaTest&test_method=test_client_response_throttle_mechanism
ClusterRateQuotaTest test_client_response_throttle_mechanism_applies_to_next_request null integration https://buildkite.com/redpanda/redpanda/builds/72607#0199639e-3246-4c9e-9855-cecee307f557 FLAKY 12/21 upstream reliability is '100.0'. current run reliability is '57.14285714285714'. drift is 42.85714 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=ClusterRateQuotaTest&test_method=test_client_response_throttle_mechanism_applies_to_next_request
ClusterRateQuotaTest test_client_response_throttle_mechanism_applies_to_next_request null integration https://buildkite.com/redpanda/redpanda/builds/72607#019963a4-5a99-4e1e-937f-08f9147064d6 FLAKY 13/21 upstream reliability is '100.0'. current run reliability is '61.904761904761905'. drift is 38.09524 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=ClusterRateQuotaTest&test_method=test_client_response_throttle_mechanism_applies_to_next_request
DatalakeE2ETests test_avro_schema {"catalog_type": "rest_hadoop", "cloud_storage_type": 1, "query_engine": "trino"} integration https://buildkite.com/redpanda/redpanda/builds/72607#0199639e-3247-4182-8de9-03ce68fa954d FLAKY 20/21 upstream reliability is '99.50617283950616'. current run reliability is '95.23809523809523'. drift is 4.26808 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=DatalakeE2ETests&test_method=test_avro_schema
NodeWiseRecoveryTest test_recovery_local_data_missing {"wait_for_final_manifest_uploads": true} integration https://buildkite.com/redpanda/redpanda/builds/72607#0199639e-3248-439b-b952-8b7b2800395b FLAKY 10/21 upstream reliability is '96.56862745098039'. current run reliability is '47.61904761904761'. drift is 48.94958 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=NodeWiseRecoveryTest&test_method=test_recovery_local_data_missing
BogusTimestampTest test_bogus_timestamps {"mixed_timestamps": false, "use_broker_timestamps": false} integration https://buildkite.com/redpanda/redpanda/builds/72607#0199639e-3248-439b-b952-8b7b2800395b FAIL 0/21 The test has failed across all retries https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=BogusTimestampTest&test_method=test_bogus_timestamps
BogusTimestampTest test_bogus_timestamps {"mixed_timestamps": false, "use_broker_timestamps": false} integration https://buildkite.com/redpanda/redpanda/builds/72607#019963a4-5a9b-4fac-a3b0-cb56a9986d16 FAIL 0/21 The test has failed across all retries https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=BogusTimestampTest&test_method=test_bogus_timestamps
BogusTimestampTest test_bogus_timestamps {"mixed_timestamps": false, "use_broker_timestamps": true} integration https://buildkite.com/redpanda/redpanda/builds/72607#0199639e-3249-4c18-a71a-46de2b9ee147 FAIL 0/21 The test has failed across all retries https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=BogusTimestampTest&test_method=test_bogus_timestamps
BogusTimestampTest test_bogus_timestamps {"mixed_timestamps": false, "use_broker_timestamps": true} integration https://buildkite.com/redpanda/redpanda/builds/72607#019963a4-5a9c-42b9-9897-4a92026b2662 FAIL 0/21 The test has failed across all retries https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=BogusTimestampTest&test_method=test_bogus_timestamps
BogusTimestampTest test_bogus_timestamps {"mixed_timestamps": true, "use_broker_timestamps": false} integration https://buildkite.com/redpanda/redpanda/builds/72607#0199639e-3249-4f62-ac62-a7fca749c55d FAIL 0/21 The test has failed across all retries https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=BogusTimestampTest&test_method=test_bogus_timestamps
BogusTimestampTest test_bogus_timestamps {"mixed_timestamps": true, "use_broker_timestamps": false} integration https://buildkite.com/redpanda/redpanda/builds/72607#019963a4-5a9d-4876-b82b-8830810b1efc FAIL 0/21 The test has failed across all retries https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=BogusTimestampTest&test_method=test_bogus_timestamps
BogusTimestampTest test_bogus_timestamps {"mixed_timestamps": true, "use_broker_timestamps": true} integration https://buildkite.com/redpanda/redpanda/builds/72607#0199639e-324a-401e-898a-5b298798d70d FAIL 0/21 The test has failed across all retries https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=BogusTimestampTest&test_method=test_bogus_timestamps
BogusTimestampTest test_bogus_timestamps {"mixed_timestamps": true, "use_broker_timestamps": true} integration https://buildkite.com/redpanda/redpanda/builds/72607#019963a4-5a9f-49c2-83eb-c2977ec4ccd3 FAIL 0/21 The test has failed across all retries https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=BogusTimestampTest&test_method=test_bogus_timestamps
WriteCachingFailureInjectionE2ETest test_crash_all {"use_transactions": false} integration https://buildkite.com/redpanda/redpanda/builds/72607#0199639e-3249-4c18-a71a-46de2b9ee147 FLAKY 18/21 upstream reliability is '100.0'. current run reliability is '85.71428571428571'. drift is 14.28571 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=WriteCachingFailureInjectionE2ETest&test_method=test_crash_all
test results on build#72631
test_class test_method test_arguments test_kind job_url test_status passed reason test_history
MasterTestSuite test_upload_segments_leadership_transfer unit https://buildkite.com/redpanda/redpanda/builds/72631#019967e3-49f0-4907-8397-1f8283dacdda FAIL 0/1
ClusterRateQuotaTest test_client_response_throttle_mechanism_applies_to_next_request null integration https://buildkite.com/redpanda/redpanda/builds/72631#01996809-5566-4735-bd3d-d98fb9cc737c FLAKY 14/21 upstream reliability is '98.44155844155844'. current run reliability is '66.66666666666666'. drift is 31.77489 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=ClusterRateQuotaTest&test_method=test_client_response_throttle_mechanism_applies_to_next_request
NodeWiseRecoveryTest test_recovery_local_data_missing {"wait_for_final_manifest_uploads": false} integration https://buildkite.com/redpanda/redpanda/builds/72631#01996809-5562-4b6c-8283-a49ffc266cd5 FLAKY 15/21 upstream reliability is '98.96373056994818'. current run reliability is '71.42857142857143'. drift is 27.53516 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=NodeWiseRecoveryTest&test_method=test_recovery_local_data_missing
NodeWiseRecoveryTest test_recovery_local_data_missing {"wait_for_final_manifest_uploads": true} integration https://buildkite.com/redpanda/redpanda/builds/72631#01996809-5563-47bf-a426-6bf04e5eb303 FLAKY 15/21 upstream reliability is '95.77464788732394'. current run reliability is '71.42857142857143'. drift is 24.34608 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=NodeWiseRecoveryTest&test_method=test_recovery_local_data_missing
test results on build#72703
test_class test_method test_arguments test_kind job_url test_status passed reason test_history
EndToEndCloudTopicsTest test_write null integration https://buildkite.com/redpanda/redpanda/builds/72703#0199747f-c325-4db3-9f1c-4a5d983a12ca FLAKY 12/21 upstream reliability is '98.93162393162393'. current run reliability is '57.14285714285714'. drift is 41.78877 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=EndToEndCloudTopicsTest&test_method=test_write
ClusterRateQuotaTest test_client_group_consume_rate_throttle_mechanism null integration https://buildkite.com/redpanda/redpanda/builds/72703#01997496-5d2c-4b40-b516-7bb15ead6944 FLAKY 13/21 upstream reliability is '89.75265017667844'. current run reliability is '61.904761904761905'. drift is 27.84789 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=ClusterRateQuotaTest&test_method=test_client_group_consume_rate_throttle_mechanism
ClusterRateQuotaTest test_client_group_produce_rate_throttle_mechanism null integration https://buildkite.com/redpanda/redpanda/builds/72703#0199747f-c319-4fef-94ec-96fa6249c346 FLAKY 12/21 upstream reliability is '91.71483622350675'. current run reliability is '57.14285714285714'. drift is 34.57198 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=ClusterRateQuotaTest&test_method=test_client_group_produce_rate_throttle_mechanism
ClusterRateQuotaTest test_client_group_produce_rate_throttle_mechanism null integration https://buildkite.com/redpanda/redpanda/builds/72703#01997496-5d22-4e63-9806-bb1918bb1404 FLAKY 17/21 upstream reliability is '91.71483622350675'. current run reliability is '80.95238095238095'. drift is 10.76246 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=ClusterRateQuotaTest&test_method=test_client_group_produce_rate_throttle_mechanism
DatalakeE2ETests test_avro_schema {"catalog_type": "rest_hadoop", "cloud_storage_type": 1, "query_engine": "trino"} integration https://buildkite.com/redpanda/redpanda/builds/72703#01997496-5d28-4dc0-80b9-3d54d3b42b5a FLAKY 20/21 upstream reliability is '99.5049504950495'. current run reliability is '95.23809523809523'. drift is 4.26686 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=DatalakeE2ETests&test_method=test_avro_schema
SchemaEvolutionE2ETests test_reorder_columns {"catalog_type": "rest_hadoop", "cloud_storage_type": 1, "produce_mode": "avro", "query_engine": "trino"} integration https://buildkite.com/redpanda/redpanda/builds/72703#0199747f-c31c-4a8a-b883-646ddfeb2eb7 FLAKY 20/21 upstream reliability is '98.61111111111111'. current run reliability is '95.23809523809523'. drift is 3.37302 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=SchemaEvolutionE2ETests&test_method=test_reorder_columns
BogusTimestampTest test_bogus_timestamps {"mixed_timestamps": false, "use_broker_timestamps": false} integration https://buildkite.com/redpanda/redpanda/builds/72703#0199747f-c31a-48a5-9650-333406475b6f FAIL 0/21 The test has failed across all retries https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=BogusTimestampTest&test_method=test_bogus_timestamps
BogusTimestampTest test_bogus_timestamps {"mixed_timestamps": false, "use_broker_timestamps": false} integration https://buildkite.com/redpanda/redpanda/builds/72703#01997496-5d23-4e2c-81f4-6f63fc090810 FAIL 0/21 The test has failed across all retries https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=BogusTimestampTest&test_method=test_bogus_timestamps
BogusTimestampTest test_bogus_timestamps {"mixed_timestamps": false, "use_broker_timestamps": true} integration https://buildkite.com/redpanda/redpanda/builds/72703#0199747f-c31c-4a8a-b883-646ddfeb2eb7 FAIL 0/21 The test has failed across all retries https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=BogusTimestampTest&test_method=test_bogus_timestamps
BogusTimestampTest test_bogus_timestamps {"mixed_timestamps": false, "use_broker_timestamps": true} integration https://buildkite.com/redpanda/redpanda/builds/72703#01997496-5d24-44f1-b807-e8160acab58d FAIL 0/21 The test has failed across all retries https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=BogusTimestampTest&test_method=test_bogus_timestamps
BogusTimestampTest test_bogus_timestamps {"mixed_timestamps": true, "use_broker_timestamps": false} integration https://buildkite.com/redpanda/redpanda/builds/72703#0199747f-c31d-44de-9414-7ab722e3a084 FAIL 0/21 The test has failed across all retries https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=BogusTimestampTest&test_method=test_bogus_timestamps
BogusTimestampTest test_bogus_timestamps {"mixed_timestamps": true, "use_broker_timestamps": false} integration https://buildkite.com/redpanda/redpanda/builds/72703#01997496-5d26-44d4-9033-b80c3dede12f FAIL 0/21 The test has failed across all retries https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=BogusTimestampTest&test_method=test_bogus_timestamps
BogusTimestampTest test_bogus_timestamps {"mixed_timestamps": true, "use_broker_timestamps": true} integration https://buildkite.com/redpanda/redpanda/builds/72703#0199747f-c31e-47e9-abb4-f20fc9cd52e0 FAIL 0/21 The test has failed across all retries https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=BogusTimestampTest&test_method=test_bogus_timestamps
BogusTimestampTest test_bogus_timestamps {"mixed_timestamps": true, "use_broker_timestamps": true} integration https://buildkite.com/redpanda/redpanda/builds/72703#01997496-5d27-48b2-9db5-45aadcb4beec FAIL 0/21 The test has failed across all retries https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=BogusTimestampTest&test_method=test_bogus_timestamps
TimeQueryTest test_timequery_with_local_gc null integration https://buildkite.com/redpanda/redpanda/builds/72703#0199747f-c322-46f3-8d4e-7dca5411dee5 FLAKY 20/21 upstream reliability is '100.0'. current run reliability is '95.23809523809523'. drift is 4.7619 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=TimeQueryTest&test_method=test_timequery_with_local_gc
test results on build#72731
test_class test_method test_arguments test_kind job_url test_status passed reason test_history
EndToEndCloudTopicsTest test_write null integration https://buildkite.com/redpanda/redpanda/builds/72731#019976dd-22d7-4f34-8cdd-de72a674b567 FLAKY 11/21 upstream reliability is '90.84745762711864'. current run reliability is '52.38095238095239'. drift is 38.46651 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=EndToEndCloudTopicsTest&test_method=test_write
ClusterRateQuotaTest test_client_group_produce_rate_throttle_mechanism null integration https://buildkite.com/redpanda/redpanda/builds/72731#019976dc-0283-4dc9-9c6b-ecfcd9bf3274 FLAKY 14/21 upstream reliability is '88.6762360446571'. current run reliability is '66.66666666666666'. drift is 22.00957 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=ClusterRateQuotaTest&test_method=test_client_group_produce_rate_throttle_mechanism
ClusterRateQuotaTest test_client_response_throttle_mechanism null integration https://buildkite.com/redpanda/redpanda/builds/72731#019976dc-0286-434b-989b-30135eefc07f FLAKY 13/21 upstream reliability is '85.02857142857142'. current run reliability is '61.904761904761905'. drift is 23.12381 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=ClusterRateQuotaTest&test_method=test_client_response_throttle_mechanism
ClusterRateQuotaTest test_client_response_throttle_mechanism_applies_to_next_request null integration https://buildkite.com/redpanda/redpanda/builds/72731#019976dd-22d2-44b7-bf7c-4b7a851610c9 FLAKY 14/21 upstream reliability is '87.66140602582496'. current run reliability is '66.66666666666666'. drift is 20.99474 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=ClusterRateQuotaTest&test_method=test_client_response_throttle_mechanism_applies_to_next_request
SchemaEvolutionE2ETests test_old_schema_writer {"catalog_type": "rest_hadoop", "cloud_storage_type": 1, "produce_mode": "avro", "query_engine": "trino", "test_case": "drop_column"} integration https://buildkite.com/redpanda/redpanda/builds/72731#019976dc-0289-4773-ac81-04d7f8ff4de7 FLAKY 20/21 upstream reliability is '99.74025974025975'. current run reliability is '95.23809523809523'. drift is 4.50216 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=SchemaEvolutionE2ETests&test_method=test_old_schema_writer
PartitionMovementUpgradeTest test_basic_upgrade null integration https://buildkite.com/redpanda/redpanda/builds/72731#019976dd-22d0-4408-9379-b1da186585fe FLAKY 20/21 upstream reliability is '98.87640449438202'. current run reliability is '95.23809523809523'. drift is 3.63831 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=PartitionMovementUpgradeTest&test_method=test_basic_upgrade
DisablingPartitionsTest test_disable null integration https://buildkite.com/redpanda/redpanda/builds/72731#019976dc-028a-4aa4-bc8c-56c4542d6955 FLAKY 9/21 upstream reliability is '86.28930817610063'. current run reliability is '42.857142857142854'. drift is 43.43217 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=DisablingPartitionsTest&test_method=test_disable
TimeQueryTest test_timequery_with_local_gc null integration https://buildkite.com/redpanda/redpanda/builds/72731#019976dd-22d5-4686-8cc3-163d711f3044 FLAKY 20/21 upstream reliability is '100.0'. current run reliability is '95.23809523809523'. drift is 4.7619 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=TimeQueryTest&test_method=test_timequery_with_local_gc
WriteCachingFailureInjectionTest test_unavoidable_data_loss null integration https://buildkite.com/redpanda/redpanda/builds/72731#019976dd-22d7-4ee3-833c-05b654706b2b FLAKY 17/21 upstream reliability is '95.80952380952381'. current run reliability is '80.95238095238095'. drift is 14.85714 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=WriteCachingFailureInjectionTest&test_method=test_unavoidable_data_loss
test results on build#72804
test_class test_method test_arguments test_kind job_url test_status passed reason test_history
ClusterRateQuotaTest test_client_group_produce_rate_throttle_mechanism null integration https://buildkite.com/redpanda/redpanda/builds/72804#019979d5-1a53-42db-9c6c-5f32b2a9297f FLAKY 15/21 upstream reliability is '87.36842105263159'. current run reliability is '71.42857142857143'. drift is 15.93985 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=ClusterRateQuotaTest&test_method=test_client_group_produce_rate_throttle_mechanism
ClusterRateQuotaTest test_client_group_produce_rate_throttle_mechanism null integration https://buildkite.com/redpanda/redpanda/builds/72804#019979da-aa1b-450f-b33c-df5b46bec031 FLAKY 12/21 upstream reliability is '87.36842105263159'. current run reliability is '57.14285714285714'. drift is 30.22556 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=ClusterRateQuotaTest&test_method=test_client_group_produce_rate_throttle_mechanism
ClusterRateQuotaTest test_client_response_and_produce_throttle_mechanism null integration https://buildkite.com/redpanda/redpanda/builds/72804#019979da-aa1c-4e0e-a5bf-2940a456733e FLAKY 12/21 upstream reliability is '82.72425249169434'. current run reliability is '57.14285714285714'. drift is 25.5814 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=ClusterRateQuotaTest&test_method=test_client_response_and_produce_throttle_mechanism
ClusterRateQuotaTest test_client_response_throttle_mechanism null integration https://buildkite.com/redpanda/redpanda/builds/72804#019979d5-1a56-45aa-b574-6931fe1c32d7 FLAKY 16/21 upstream reliability is '93.14285714285714'. current run reliability is '76.19047619047619'. drift is 16.95238 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=ClusterRateQuotaTest&test_method=test_client_response_throttle_mechanism
ClusterRateQuotaTest test_client_response_throttle_mechanism null integration https://buildkite.com/redpanda/redpanda/builds/72804#019979da-aa1c-4a04-84c3-69c827df3597 FLAKY 15/21 upstream reliability is '83.9340885684861'. current run reliability is '71.42857142857143'. drift is 12.50552 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=ClusterRateQuotaTest&test_method=test_client_response_throttle_mechanism
ClusterRateQuotaTest test_client_response_throttle_mechanism_applies_to_next_request null integration https://buildkite.com/redpanda/redpanda/builds/72804#019979d5-1a57-47f3-8eef-836175ed3f9e FLAKY 13/21 upstream reliability is '94.42896935933148'. current run reliability is '61.904761904761905'. drift is 32.52421 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=ClusterRateQuotaTest&test_method=test_client_response_throttle_mechanism_applies_to_next_request
test results on build#72838
test_class test_method test_arguments test_kind job_url test_status passed reason test_history
EndToEndCloudTopicsTest test_delete_records null integration https://buildkite.com/redpanda/redpanda/builds/72838#01997bfa-7306-4e56-bb7f-d31454e24c41 FLAKY 7/21 upstream reliability is '76.98412698412699'. current run reliability is '33.33333333333333'. drift is 43.65079 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=EndToEndCloudTopicsTest&test_method=test_delete_records
EndToEndCloudTopicsTxTest test_write null integration https://buildkite.com/redpanda/redpanda/builds/72838#01997bfa-72fd-4957-934f-b40fa06e8753 FLAKY 13/21 upstream reliability is '83.17422434367542'. current run reliability is '61.904761904761905'. drift is 21.26946 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=EndToEndCloudTopicsTxTest&test_method=test_write
ClusterRateQuotaTest test_client_group_consume_rate_throttle_mechanism null integration https://buildkite.com/redpanda/redpanda/builds/72838#01997bfa-72ff-4eaa-9ae7-b6dbc4243ab1 FLAKY 15/21 upstream reliability is '82.92433537832311'. current run reliability is '71.42857142857143'. drift is 11.49576 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=ClusterRateQuotaTest&test_method=test_client_group_consume_rate_throttle_mechanism
ClusterRateQuotaTest test_client_response_throttle_mechanism null integration https://buildkite.com/redpanda/redpanda/builds/72838#01997bfa-7303-4302-a454-80db89f3e6f6 FLAKY 14/21 upstream reliability is '82.72642390289448'. current run reliability is '66.66666666666666'. drift is 16.05976 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=ClusterRateQuotaTest&test_method=test_client_response_throttle_mechanism
ClusterRateQuotaTest test_client_response_throttle_mechanism_applies_to_next_request null integration https://buildkite.com/redpanda/redpanda/builds/72838#01997bfa-7304-4229-95d2-710251de2479 FLAKY 13/21 upstream reliability is '84.8'. current run reliability is '61.904761904761905'. drift is 22.89524 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=ClusterRateQuotaTest&test_method=test_client_response_throttle_mechanism_applies_to_next_request
RandomNodeOperationsTest test_node_operations {"cloud_storage_type": 2, "compaction_mode": "sliding_window", "enable_failures": true, "mixed_versions": true, "with_iceberg": false} integration https://buildkite.com/redpanda/redpanda/builds/72838#01997bfa-7305-4a39-929a-184486e8f46d FLAKY 20/21 upstream reliability is '98.18731117824774'. current run reliability is '95.23809523809523'. drift is 2.94922 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=RandomNodeOperationsTest&test_method=test_node_operations
DisablingPartitionsTest test_disable null integration https://buildkite.com/redpanda/redpanda/builds/72838#01997bfa-7307-4494-9f6d-863c29e442f6 FLAKY 14/21 upstream reliability is '84.25925925925925'. current run reliability is '66.66666666666666'. drift is 17.59259 and the allowed drift is set to 50. The test should PASS https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=DisablingPartitionsTest&test_method=test_disable

@WillemKauf WillemKauf force-pushed the min_time_based_retention branch from 045ea4d to 79cd8d5 Compare August 26, 2025 19:33
bharathv
bharathv previously approved these changes Aug 27, 2025
Copy link
Copy Markdown
Contributor

@bharathv bharathv left a comment

Choose a reason for hiding this comment

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

fix makes sense to me, thanks for the PR.

Would prefer a 👍 from one of the storage experts incase I missed something.

@tmgstevens
Copy link
Copy Markdown

I like what we've done here but we should cross reference: https://cwiki.apache.org/confluence/display/KAFKA/KIP-937%3A+Improve+Message+Timestamp+Validation which is introduced in Kafka 3.6.0. Right now, as far as I'm aware, Redpanda does not reject messages based on timestamp validation, which I'm probably happy with, but we could consider rejecting messages with a future value of > some threshold.

@WillemKauf
Copy link
Copy Markdown
Contributor Author

Right now, as far as I'm aware, Redpanda does not reject messages based on timestamp validation, which I'm probably happy with, but we could consider rejecting messages with a future value of > some threshold.

Yes, I think implementing log.message.timestamp.before.max.ms and log.message.timestamp.after.max.ms is a good idea.

rockwotj
rockwotj previously approved these changes Aug 27, 2025
@michael-redpanda
Copy link
Copy Markdown
Contributor

I'm wondering if we need some sort of config to maintain the old behavior on old clusters and default to the updated behavior on new clusters.

@rockwotj
Copy link
Copy Markdown
Contributor

we already have some configs that should honestly be cleaned up. If we want to invest in configs we should just support the kafka properties IMO

@WillemKauf
Copy link
Copy Markdown
Contributor Author

From talking with @michael-redpanda, it would be nice to have another feature flag (grumble grumble) for this change that is on by default for new clusters and opt in for old ones.

@WillemKauf
Copy link
Copy Markdown
Contributor Author

We could also feature flag enforcement of log.message.timestamp.before.max.ms and log.message.timestamp.after.max.ms if we wanted to implement those.

@WillemKauf WillemKauf dismissed stale reviews from rockwotj and bharathv via ba1bbef August 28, 2025 15:21
@WillemKauf WillemKauf force-pushed the min_time_based_retention branch from 79cd8d5 to ba1bbef Compare August 28, 2025 15:21
@WillemKauf
Copy link
Copy Markdown
Contributor Author

Force push to:

  • Add feature flag min_broker_batch_time_based_retention. The changes described in this PR will only be active for new clusters created with minimum version v25.3.1, and for those clusters that opt into its behavior via the admin API.
  • Rebase to upstream/dev

@WillemKauf WillemKauf requested a review from rockwotj August 28, 2025 16:42
release_version::v25_3_1,
"min_broker_batch_time_based_retention",
feature::min_broker_batch_time_based_retention,
feature_spec::available_policy::new_clusters_only,
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.

Do we really want this for new clusters only? Or do we want it for everyone and optionally folks can turn it off if it causes issues. I personally see it as you really always want this behavior and we should eventually remove this feature flag.

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.

I guess I can live with this for new clusters only but I don't see why we want to keep the old behavior as opt-in.

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.

Do we really want this for new clusters only?

I don't have any clear idea of how many clusters have old batch timestamps whether that's due to badly produced messages or as intended- if we did have clusters like that though, they would see a lot of data vanish quickly without this feature being gated to new clusters only.

I personally see it as you really always want this behavior

Then we wouldn't need a feature flag at all, which would be nice. I'm open to this but I think we need buy-in from other members as well.

cc: @dotnwat

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.

but I don't see why we want to keep the old behavior as opt-in

broker_time_based_retention should be retired or subsumed by this new behavior, I agree.

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.

Not for this PR, and maybe the feature table isn't the right place to do this, but now that #27419 has landed, it'd be nice if we could tell new clusters to trust batch timestamps (because they're validated on the produce path) and stop having to track broker timestamps (which isn't consistent anyway, since tiered storage doesn't honor broker timestamp for retention)

rockwotj
rockwotj previously approved these changes Aug 28, 2025
release_version::v25_3_1,
"min_broker_batch_time_based_retention",
feature::min_broker_batch_time_based_retention,
feature_spec::available_policy::new_clusters_only,
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.

I guess I can live with this for new clusters only but I don't see why we want to keep the old behavior as opt-in.

@WillemKauf
Copy link
Copy Markdown
Contributor Author

I like what we've done here but we should cross reference...

@tmgstevens this was merged! 👍 #27419

@dotnwat
Copy link
Copy Markdown
Member

dotnwat commented Sep 9, 2025

needs a rebase to fix conflicts

@WillemKauf
Copy link
Copy Markdown
Contributor Author

needs a rebase to fix conflicts

Thanks, rebased and pushed.

@WillemKauf WillemKauf force-pushed the min_time_based_retention branch 2 times, most recently from eb96e9e to 6326452 Compare September 11, 2025 18:11
@vbotbuildovich
Copy link
Copy Markdown
Collaborator

vbotbuildovich commented Sep 19, 2025

Retry command for Build#72607

please wait until all jobs are finished before running the slash command

/ci-repeat 1
tests/rptest/tests/retention_policy_test.py::BogusTimestampTest.test_bogus_timestamps@{"mixed_timestamps":true,"use_broker_timestamps":false}
tests/rptest/tests/retention_policy_test.py::BogusTimestampTest.test_bogus_timestamps@{"mixed_timestamps":true,"use_broker_timestamps":true}
tests/rptest/tests/retention_policy_test.py::BogusTimestampTest.test_bogus_timestamps@{"mixed_timestamps":false,"use_broker_timestamps":true}
tests/rptest/tests/retention_policy_test.py::BogusTimestampTest.test_bogus_timestamps@{"mixed_timestamps":false,"use_broker_timestamps":false}

@WillemKauf
Copy link
Copy Markdown
Contributor Author

Oops. There's more to deprecate here (mostly in the storage layer).

I will come back to this soon.

andrwng
andrwng previously approved these changes Sep 23, 2025
Copy link
Copy Markdown
Contributor

@andrwng andrwng left a comment

Choose a reason for hiding this comment

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

LGTM

Comment on lines 836 to -847
@cluster(num_nodes=2)
@matrix(mixed_timestamps=[True, False], use_broker_timestamps=[True, False])
def test_bogus_timestamps(
self, mixed_timestamps: bool, use_broker_timestamps: bool
):
def test_future_timestamps(self):
"""
:param mixed_timestamps: if true, test with a mixture of valid and invalid
timestamps in the same segment (i.e. timestamp adjustment should use the
valid timestamps rather than falling back to mtime)
Ensure record timestamps in the future are respected by retention enforcement.
"""

# broker_time_based_retention fixes this test case for new segments. (disable it to simulate a legacy condition)
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.

WDYT about keeping this test around as an upgrade test? That is, start on v25.2, and then upgrade to v25.3 -- the workings of this test from before wouldn't change, even after the upgrade

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 sure why not. will push soon-ish

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.

Pushed

@vbotbuildovich
Copy link
Copy Markdown
Collaborator

vbotbuildovich commented Sep 23, 2025

Retry command for Build#72703

please wait until all jobs are finished before running the slash command

/ci-repeat 1
tests/rptest/tests/retention_policy_test.py::BogusTimestampTest.test_bogus_timestamps@{"mixed_timestamps":true,"use_broker_timestamps":false}
tests/rptest/tests/retention_policy_test.py::BogusTimestampTest.test_bogus_timestamps@{"mixed_timestamps":true,"use_broker_timestamps":true}
tests/rptest/tests/retention_policy_test.py::BogusTimestampTest.test_bogus_timestamps@{"mixed_timestamps":false,"use_broker_timestamps":true}
tests/rptest/tests/retention_policy_test.py::BogusTimestampTest.test_bogus_timestamps@{"mixed_timestamps":false,"use_broker_timestamps":false}

@WillemKauf WillemKauf force-pushed the min_time_based_retention branch from aee838f to e3bf527 Compare September 23, 2025 13:20
andrwng
andrwng previously approved these changes Sep 24, 2025
rockwotj
rockwotj previously approved these changes Sep 24, 2025
Copy link
Copy Markdown
Contributor

@rockwotj rockwotj left a comment

Choose a reason for hiding this comment

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

LGTM, some nits on the comments

s->index().broker_timestamp(),
s);
if (!validated_timestamps) {
// Deprecated code path for >= v25.3.1.
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 confusing to me. This code path is deprecated, but we take it for version less than our next one.

Suggested change
// Deprecated code path for >= v25.3.1.
// This legacy behavior is only needed in older clusters that didn't validate timestamps.

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.

Altered.

auto validated_timestamps = _feature_table.local().is_active(
features::feature::validated_batch_timestamps);
if (validated_timestamps) {
// Deprecated code path for >= v25.3.1.
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.

Well the return path isn't deprecated right? Just the else?

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.

Altered comment.

Copilot AI review requested due to automatic review settings September 24, 2025 02:49
@WillemKauf WillemKauf dismissed stale reviews from rockwotj and andrwng via fcabb56 September 24, 2025 02:49
@WillemKauf WillemKauf force-pushed the min_time_based_retention branch from e3bf527 to fcabb56 Compare September 24, 2025 02:49
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 modifies the storage layer's time-based retention to use max_timestamp instead of broker_timestamp when the validated_batch_timestamps feature flag is active. The change addresses unexpected behavior when using broker_time_based_retention with data from external sources (e.g., Mirror Maker 2) where original record timestamps should be preserved for retention enforcement.

  • Introduces a new feature flag validated_batch_timestamps that controls whether to use validated max timestamps for retention
  • Updates time-based retention logic to prioritize max_timestamp when timestamp validation is enabled
  • Adds comprehensive tests to verify retention behavior with both past and future timestamps

Reviewed Changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/rptest/tests/retention_policy_test.py Adds new test class TimestampDriftRetentionTest with tests for future/past timestamp retention behavior, refactors existing BogusTimestampTest to use versioned upgrades
src/v/storage/segment_index.h Updates truth table and logic to prioritize max_timestamp when validated_batch_timestamps is active, adds new configuration field
src/v/storage/disk_log_impl.cc Modifies GC logic to skip bogus timestamp warnings and retention timestamp adjustments when using validated timestamps
src/v/features/feature_table.h Defines new validated_batch_timestamps feature flag with new_clusters_only availability policy
src/v/features/feature_table.cc Adds string representation for the new feature flag
src/v/storage/tests/*.cc Updates test fixtures to provide explicit timestamp parameters and handle new retention behavior
src/v/cluster/archival/tests/*.cc Updates archival tests to provide default timestamps for segment descriptors

log->housekeeping(ccfg).get();

auto offset = last_evicted_offset.get_future().get();
std::ignore = last_evicted_offset.get_future().get();
Copy link

Copilot AI Sep 24, 2025

Choose a reason for hiding this comment

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

[nitpick] Using std::ignore suggests this return value was previously used but is now discarded. Consider removing the assignment entirely or adding a comment explaining why the future result is intentionally ignored.

Suggested change
std::ignore = last_evicted_offset.get_future().get();
last_evicted_offset.get_future().get();

Copilot uses AI. Check for mistakes.
@WillemKauf
Copy link
Copy Markdown
Contributor Author

@rockwotj feel free to force merge, latest force push is just correcting comments.

@WillemKauf WillemKauf requested a review from rockwotj September 24, 2025 02:54
To be used in future commit for adjusting time-based retention enforcement
behavior in local storage. The behavior will only be enabled for new clusters
created `>= v25.3.1`, but can be opted into via the admin API.

`validated_batch_timestamps` ensures that the `max_timestamp` of a batch
produced to `redpanda` has been validated by properties
`message.timestamp.{before/after}.max.ms` and unconditionally set in the
produce path (see: `v/kafka/server/handlers/produce_validation.cc`) and are valid
for retention enforcement.
The motivating case for `broker_time_based_retention` was the
fact that records with bad timestamps produced in the future
could lead to time-based retention being stuck indefinitely [1].

However, using the `broker_ts` can lead to unexpected
behavior when e.g. replicating data from an existing cluster
using MM2, as the timestamps of the Kafka records themselves are
correctly preserved, but internally, `redpanda` data structures
are not.

To avoid the potentially curious behavior of a divergence in
retention enforcement, go back to using the `max_timestamp`
for batches whose timestamps have been validated and unconditionally
set in the produce path (see: `v/kafka/server/handlers/produce_validation.cc`)
as of `v25.3.1`.

[1]:
* redpanda-data#9820
* redpanda-data#12991
This stuff is all deprecated since we have timestamp validation in
the produce path, and is actually quite undesirable behavior now.

The cluster property `storage_ignore_timestamps_in_future_sec` should
be eventually deprecated after enough time has passed (at the same time,
we should set the `available_policy` of `validated_batch_timestamps`
from `new_clusters_only` to `always`).
@WillemKauf WillemKauf force-pushed the min_time_based_retention branch from fcabb56 to b489566 Compare September 24, 2025 12:41
@WillemKauf
Copy link
Copy Markdown
Contributor Author

Force push to rebase to upstream/dev to fix merge conflict.

@WillemKauf WillemKauf merged commit 7128be1 into redpanda-data:dev Sep 24, 2025
19 checks passed
WillemKauf added a commit to WillemKauf/redpanda that referenced this pull request Oct 15, 2025
This test intended to disable local retention, but did not consider the
property `retention.local.target.ms` for a tiered storage enabled topic.

Previously, local retention would be enforced by broker time, but after PR
redpanda-data#27383, the test became flakey
due to the now "active" retention enforcement.

Set `retention.local-target.ms=-1` to disable time-based retention for
tiered storage enabled topics for this test.
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.

9 participants