Akshay Upadhyay
12/29/2025, 9:35 AMrelease-1.3.0 deployed in k8s, now we recently faced an issue after cluster rotation/server restart where we got duplicate rows for our primary keys even for same segment docs, and this was not solved even after few hours of server rotation. We had to reload segments to solve this.
We even replicated the issue in our dev cluster, where we got different results in same queries which eventually resolved after 4-5 hrs.
Sharing the table config, schema, queries, results in the thread.
Can someone please help in this, thanks.Akshay Upadhyay
12/29/2025, 9:38 AM"segmentsConfig": {
"replication": "3",
"retentionTimeUnit": "DAYS",
"retentionTimeValue": "31",
"replicasPerPartition": "3",
"timeColumnName": "insert_timestamp",
"segmentPushType": "APPEND",
"segmentAssignmentStrategy": "BalanceNumSegmentAssignmentStrategy",
"minimizeDataMovement": false
},
"taskTypeConfigsMap": {
"UpsertCompactionTask": {
"schedule": "0 */5 * ? * *",
"bufferTimePeriod": "1d",
"invalidRecordsThresholdPercent": "30"
}
}
},
"routing": {
"segmentPrunerTypes": [
"partition",
"time"
],
"instanceSelectorType": "strictReplicaGroup"
},
"query": {
"timeoutMs": 10000
},
"instanceAssignmentConfigMap": {
"CONSUMING": {
"tagPoolConfig": {
"tag": "DefaultTenant_REALTIME",
"poolBased": false,
"numPools": 0
},
"replicaGroupPartitionConfig": {
"replicaGroupBased": true,
"numInstances": 5,
"numReplicaGroups": 1,
"numInstancesPerReplicaGroup": 5,
"numPartitions": 1,
"numInstancesPerPartition": 5,
"minimizeDataMovement": false,
"partitionColumn": "id"
},
"partitionSelector": "INSTANCE_REPLICA_GROUP_PARTITION_SELECTOR",
"minimizeDataMovement": false
}
},
"upsertConfig": {
"mode": "FULL",
"consistencyMode": "NONE",
"comparisonColumns": [
"update_timestamp"
],
"metadataTTL": 86400000,
"dropOutOfOrderRecord": false,
"enableDeletedKeysCompactionConsistency": false,
"enablePreload": true,
"deletedKeysTTL": 0,
"enableSnapshot": true,
"newSegmentTrackingTimeMs": 10000,
"hashFunction": "MURMUR3",
"defaultPartialUpsertStrategy": "OVERWRITE",
"upsertViewRefreshIntervalMs": 3000,
"allowPartialUpsertConsumptionDuringCommit": false
},
PK -> id
"primaryKeyColumns": [
"id"
]Akshay Upadhyay
12/29/2025, 9:41 AMselect count(*), id from fact_test_table
where
order_date = '2025-12-27'
group by 2
having count(*) > 1
order by 1 desc
limit 1000
sometimes returned 2 rows, sometimes 493 rows
------------------------------------------------------------------
------------------------------------------------------------------
when checked for a particular id whose data was getting replicated
select current_status, $docId, $segmentName, update_timestamp, insert_timestamp from fact_test_table
where
id = 1602849389
limit 100
sometimes 2 rows
current_status $docId $segmentName update_timestamp insert_timestamp
APPROVED 14199 fact_test_table__12__11184__20251226T1830Z 1766775016000 1766775016000
DELIVERED 21035 fact_test_table__12__11184__20251226T1830Z 1766775666000 1766775016000
sometimes 1 row
current_status $docId $segmentName update_timestamp insert_timestamp
DELIVERED 21035 fact_test_table__12__11184__20251226T1830Z 1766775666000 1766775016000Mayank
Akshay Upadhyay
12/29/2025, 3:45 PMAkshay Upadhyay
12/29/2025, 3:46 PMselect current_status, $docId, $segmentName, update_timestamp, $hostName insert_timestamp from fact_test_table
where
id = 1605595765
limit 100
server 0 and 1 are returning this:
-- current_status $docId $segmentName update_timestamp insert_timestamp
-- DELIVERED 37766 fact_test_table__7__11279__20251228T1518Z 1766859143000 pinot-preprod-server-0.pinot-preprod-server-headless.pinot-preprod-lb.svc.cluster.local
and server 2 is returning this:
-- current_status $docId $segmentName update_timestamp insert_timestamp
-- DELIVERED 66460 fact_test_table__7__11275__20251227T1113Z 1766859143000 pinot-preprod-server-2.pinot-preprod-server-headless.pinot-preprod-lb.svc.cluster.local
-- DELIVERED 37766 fact_test_table__7__11279__20251228T1518Z 1766859143000 pinot-preprod-server-2.pinot-preprod-server-headless.pinot-preprod-lb.svc.cluster.localMayank
Mayank
Mayank
Akshay Upadhyay
12/29/2025, 4:58 PMAkshay Upadhyay
12/29/2025, 4:58 PMrelease-1.3.0Akshay Upadhyay
12/29/2025, 5:02 PMMayank
we added a tag due to which all components rotated once
Mayank
Akshay Upadhyay
12/29/2025, 5:13 PMThis does not lead to rolling restartnot tag, template metadata annotation
Akshay Upadhyay
12/29/2025, 5:15 PMTry restarting the server-2, see if that fixes the metadatadid a segment reload, now it returns 1 row for all the 3 servers for the earlier query
Mayank
Akshay Upadhyay
12/29/2025, 5:16 PM"consistencyMode": "NONE", cause this?Mayank
Akshay Upadhyay
12/29/2025, 5:22 PMMayank
Akshay Upadhyay
12/29/2025, 6:07 PMselect count(*), id from fact_test_table
where
order_date = '2025-12-27'
group by 2
having count(*) > 1
order by 1 desc
limit 1000
sometimes returns 0 rows, sometimes 1 row
the one row returned sometimes was -> 1605595765
select current_status, $docId, $segmentName, update_timestamp, $hostName insert_timestamp from fact_test_table
where
id = 1605595765
limit 100
result1
current_status $docId $segmentName update_timestamp insert_timestamp
DELIVERED 37766 fact_test_table__7__11279__20251228T1518Z 1766859143000 pinot-preprod-server-1.pinot-preprod-server-headless.pinot-preprod-lb.svc.cluster.local
result2 (server 2 seems to have corrupted data)
current_status $docId $segmentName update_timestamp insert_timestamp
DELIVERED 66460 fact_test_table__7__11275__20251227T1113Z 1766859143000 pinot-preprod-server-2.pinot-preprod-server-headless.pinot-preprod-lb.svc.cluster.local
DELIVERED 37766 fact_test_table__7__11279__20251228T1518Z 1766859143000 pinot-preprod-server-2.pinot-preprod-server-headless.pinot-preprod-lb.svc.cluster.local
------------------------------------------------------------------
------------------------------------------------------------------
Query2 (order_date = ‘2025-12-26’)
select count(*), id from fact_test_table
where
order_date = '2025-12-26'
group by 2
having count(*) > 1
order by 1 desc
limit 1000
sometimes 1 row, sometimes 2 rows
the different row returned sometimes was -> 1600163850
select current_status, $docId, $segmentName, update_timestamp, $hostName insert_timestamp from fact_test_table
where
id = 1600163850
limit 100
result1
current_status $docId $segmentName update_timestamp insert_timestamp
DELIVERED 4641 fact_test_table__11__11179__20251226T1730Z 1766696574000 pinot-preprod-server-1.pinot-preprod-server-headless.pinot-preprod-lb.svc.cluster.local
result2 (server 0 seems to have corrupted data now)
current_status $docId $segmentName update_timestamp insert_timestamp
DELIVERED 4641 fact_test_table__11__11179__20251226T1730Z 1766696574000 pinot-preprod-server-0.pinot-preprod-server-headless.pinot-preprod-lb.svc.cluster.local
DELIVERED 33148 fact_test_table__11__11177__20251225T1512Z 1766696574000 pinot-preprod-server-0.pinot-preprod-server-headless.pinot-preprod-lb.svc.cluster.local
So for different ids, different servers are having corrupted data + server rollout restart is causing the issuesMayank
// For Upsert tables when some of the records get dropped when dropOutOfOrderRecord is enabled, we donot
// store the original record location when keys are not replaced, this can potentially cause inconsistencies
// leading to some rows not getting dropped when reconsumed. This can be caused when a consuming segment
// that is consumed from a different server is replaced with the existing segment which consumed rows ahead
// of the other serverAkshay Upadhyay
12/29/2025, 6:53 PMdropOutOfOrderRecord is false and the affected segments are not consuming as they are few days oldMayank
Akshay Upadhyay
12/29/2025, 6:59 PMAkshay Upadhyay
12/29/2025, 7:01 PM2025/12/29 17:38:50.500 WARN [fact_order_details_v6_test_dr_v4_drtest1_REALTIME-7-ConcurrentMapPartitionUpsertMetadataManager] [HelixTaskExecutor-message_handle_thread_10] Failed to find validDocIds snapshot to add segment: ffact_order_details_v6_test_dr_v4_drtest1__7__11275__20251227T1113Z out of TTL, treating all docs as valid
actual table name is fact_order_details_v6_test_dr_v4_drtest1Mayank
Akshay Upadhyay
12/29/2025, 7:02 PMAkshay Upadhyay
12/29/2025, 7:10 PMMayank
Mayank
Akshay Upadhyay
12/29/2025, 7:13 PMAkshay Upadhyay
12/29/2025, 7:13 PMMayank
Mayank
Akshay Upadhyay
12/29/2025, 8:10 PM"Persisted validDocIds for segment" |= "fact_order_details_v6_test_dr_v4_drtest1__7__11275__20251227T1113Z"
I see 2 instances when snapshot is persisted: (server 0 and server 1, not server 2)
2025-12-29 14:25:31
2025/12/29 08:55:31.630 INFO [ImmutableSegmentImpl] [fact_order_details_v6_test_dr_v4_drtest1__7__11280__20251229T0855Z] Persisted validDocIds for segment: fact_order_details_v6_test_dr_v4_drtest1__7__11275__20251227T1113Z with: 84997 valid docs
2025-12-29 14:25:31
2025/12/29 08:55:31.694 INFO [ImmutableSegmentImpl] [fact_order_details_v6_test_dr_v4_drtest1__7__11280__20251229T0855Z] Persisted validDocIds for segment: fact_order_details_v6_test_dr_v4_drtest1__7__11275__20251227T1113Z with: 84997 valid docs
in the server 2, I see this:
2025-12-29 14:25:31
2025/12/29 08:55:31.581 WARN [fact_order_details_v6_test_dr_v4_drtest1_REALTIME-7-ConcurrentMapPartitionUpsertMetadataManager] [fact_order_details_v6_test_dr_v4_drtest1__7__11280__20251229T0855Z] Could not get segmentLock to take snapshot for segment: fact_order_details_v6_test_dr_v4_drtest1__7__11279__20251228T1518Z, skipping
2025-12-29 14:25:31
2025/12/29 08:55:31.608 WARN [fact_order_details_v6_test_dr_v4_drtest1_REALTIME-7-ConcurrentMapPartitionUpsertMetadataManager] [fact_order_details_v6_test_dr_v4_drtest1__7__11280__20251229T0855Z] Missed taking snapshot for 5 immutable segmentsAkshay Upadhyay
12/29/2025, 8:18 PM2025-12-29 23:04:17
2025/12/29 17:34:17.962 INFO [fact_order_details_v6_test_dr_v4_drtest1_REALTIME-7-ConcurrentMapPartitionUpsertMetadataManager] [pool-35-thread-2] Skip removing segment: fact_order_details_v6_test_dr_v4_drtest1__7__11275__20251227T1113Z because metadata manager is already stopped
2025-12-29 23:04:47
2025/12/29 17:34:47.182 INFO [fact_order_details_v6_test_dr_v4_drtest1_REALTIME-7-ConcurrentMapPartitionUpsertMetadataManager] [pool-39-thread-5] Skip removing segment: fact_order_details_v6_test_dr_v4_drtest1__7__11275__20251227T1113Z because metadata manager is already stopped
2025-12-29 23:05:20
2025/12/29 17:35:20.930 INFO [fact_order_details_v6_test_dr_v4_drtest1_REALTIME-7-ConcurrentMapPartitionUpsertMetadataManager] [pool-41-thread-4] Skip removing segment: fact_order_details_v6_test_dr_v4_drtest1__7__11275__20251227T1113Z because metadata manager is already stoppedChaitanya Deepthi Chadalavada
01/01/2026, 8:54 PMupdate_timestamp seems to be same in both rows in different segments. By any chance, did the validDoc id snapshot was deleted from any of the sever. This is stored in the segment path. It seems like from your logs, one server didn't persist the valid docids but the other servers were able to do that..
current_status $docId $segmentName update_timestamp insert_timestamp
DELIVERED 4641 fact_test_table__11__11179__20251226T1730Z 1766696574000 pinot-preprod-server-0.pinot-preprod-server-headless.pinot-preprod-lb.svc.cluster.local
DELIVERED 33148 fact_test_table__11__11177__20251225T1512Z 1766696574000 pinot-preprod-server-0.pinot-preprod-server-headless.pinot-preprod-lb.svc.cluster.localAkshay Upadhyay
01/02/2026, 5:56 AMsame pk and same timestamp or occuring with diff timecol values as welloccurring with diff as well as share here
I see that thehave seen this in diff as well where both APPROVED and DELIVERED states exists with different timestampsseems to be same in both rows in different segmentsupdate_timestamp
By any chance, did the validDoc id snapshot was deleted from any of the severno we didn’t manually deleted anything
It seems like from your logs, one server didn’t persist the valid docids but the other servers were able to do that..As per the logs shared here , server2 failed to persist validDocs due to this
2025-12-29 14:25:31
2025/12/29 08:55:31.581 WARN [fact_order_details_v6_test_dr_v4_drtest1_REALTIME-7-ConcurrentMapPartitionUpsertMetadataManager] [fact_order_details_v6_test_dr_v4_drtest1__7__11280__20251229T0855Z] Could not get segmentLock to take snapshot for segment: fact_order_details_v6_test_dr_v4_drtest1__7__11279__20251228T1518Z, skipping
2025-12-29 14:25:31
2025/12/29 08:55:31.608 WARN [fact_order_details_v6_test_dr_v4_drtest1_REALTIME-7-ConcurrentMapPartitionUpsertMetadataManager] [fact_order_details_v6_test_dr_v4_drtest1__7__11280__20251229T0855Z] Missed taking snapshot for 5 immutable segmentsAkshay Upadhyay
10/12/2026, 11:37 AMChaitanya Deepthi Chadalavada
10/12/2026, 7:35 PMAkshay Upadhyay
10/12/2026, 8:20 PM// Persist TTL watermark after taking snapshots if TTL is enabled, so that segments out of TTL can be loaded with
// updated validDocIds bitmaps. If the TTL watermark is persisted first, segments out of TTL may get loaded with
// stale bitmaps or even no bitmap snapshots to use.
Do lmk if any changes/modifications needed hereChaitanya Deepthi Chadalavada
10/13/2026, 9:29 PMAkshay Upadhyay
10/14/2026, 4:14 AMChaitanya Deepthi Chadalavada
10/14/2026, 7:44 AM_persistedWatermark , compaction and cleanup will be looking at same watermark from snapshots. When replacement happens we might still see the doc coming back. But when a segment commits, it should eventually be fine!Akshay Upadhyay
10/15/2026, 12:54 AMChaitanya Deepthi Chadalavada
10/15/2026, 6:52 PMAkshay Upadhyay
10/15/2026, 8:49 PMgetPersistedWatermark() in the latest commit
On the deletedKeysTTL point, I want to check if I understand the case. Example with metadataTTL 7 days and deletedKeysTTL 1 day
1. Key K is inserted with ts 100 in segment S1.
2. K is deleted with ts 200 in segment S2.
3. A day later the sweep forgets K: it's removed from the map and the delete record's bit is cleared.
4. A new record for K arrives with ts 150. K isn't in the map anymore, so it's accepted and K is visible.
5. The server restarts. S1 and S2 are still within metadataTTL, so they're added normally, not skipped.
6. The delete record (ts 200) is read again and wins over the ts 150 record, so K now shows as deleted on this replica. Replicas that didn't restart still show K.
Without preload, step 6 always happens, since the regular add reads every row. With preload, it happens if S2's snapshot from after step 3 isn't on disk yet.
Is this the case you meant? If so, expiring against the persisted watermark would delay it but not close it. I think this will need a separate design to fix?Chaitanya Deepthi Chadalavada
10/15/2026, 9:02 PMAkshay Upadhyay
10/15/2026, 9:25 PMAkshay Upadhyay
10/16/2026, 4:40 PM