What happened?
We noticed that there are a large number of no-change update watch events happening in deployments that contain a large number of Object resources.
We are seeing two watch events for every Object in every reconciliation cycle, even when there are no changes
being applied to the objects. The first watch event is triggered by a status update from the provider:
{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"Metadata","auditID":"3b346756-ad1f-42f5-ae0f-62d273f40402","stage":"ResponseComplete","requestURI":"/apis/kubernetes.crossplane.io/v1alpha2/objects/bobncom-ngsjm-8f6f35d00355/status","verb":"update","user":{"username":"system:serviceaccount:crossplane-system:provider-kubernetes","uid":"b81295bd-4f57-4fae-9c8e-a280ae7145ae","groups":["system:serviceaccounts","system:serviceaccounts:crossplane-system","system:authenticated"],"extra":{"authentication.kubernetes.io/credential-id":["JTI=3a085658-fd97-41df-8c4b-e0a1ee20edda"],"authentication.kubernetes.io/node-name":["ip-10-254-0-45.ec2.internal"],"authentication.kubernetes.io/node-uid":["8a56b5dc-c208-477f-8ae4-422bbfd832e4"],"authentication.kubernetes.io/pod-name":["provider-kubernetes-75f7657d8d-pdpcr"],"authentication.kubernetes.io/pod-uid":["b715f9ea-5c3a-4b7a-9d3f-a23003a7bf26"]}},"sourceIPs":["10.254.14.242"],"userAgent":"crossplane-kubernetes-provider/v0.0.0 (linux/amd64) kubernetes/$Format","objectRef":{"resource":"objects","name":"bobncom-ngsjm-8f6f35d00355","uid":"b6b2664a-925d-495c-934f-9daa7930e180","apiGroup":"kubernetes.crossplane.io","apiVersion":"v1alpha2","resourceVersion":"4345770","subresource":"status"},"responseStatus":{"metadata":{},"code":200},"requestReceivedTimestamp":"2026-01-12T23:43:02.299010Z","stageTimestamp":"2026-01-12T23:43:02.324430Z","annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":"RBAC: allowed by ClusterRoleBinding \"crossplane:provider:provider-kubernetes-4da041ccd79c:system\" of ClusterRole \"crossplane:provider:provider-kubernetes-4da041ccd79c:system\" to ServiceAccount \"provider-kubernetes/crossplane-system\""}}
This status update triggers a large number of updates to the composite, on the order of 300 log messages:
2026-01-13T01:39:31Z DEBUG crossplane Mapping composite resource because composed resource changed {"controller": "defined/compositeresourcedefinition.apiextensions.crossplane.io", "namespace": "", "name": "bobncom-ngsjm-dd9bef04aa26", "cdGVK": "kubernetes.crossplane.io/v1alpha1, Kind=Object", "cdName": "bobncom-ngsjm-8f6f35d00355"}
and the second event occurs a few seconds later in response to the status update:
{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"Metadata","auditID":"372aa3e6-761f-4f5e-abe0-7ea31ea7d09b","stage":"ResponseComplete","requestURI":"/apis/kubernetes.crossplane.io/v1alpha1/objects/bobncom-ngsjm-8f6f35d00355?fieldManager=apiextensions.crossplane.io%2Fcomposed%2F52fe4d13cf623b18c3bb78b1db3201ab61f3c8c2b3891864e5a9a91a371f5a72\u0026force=true","verb":"patch","user":{"username":"system:serviceaccount:crossplane-system:crossplane","uid":"4ac000ef-5307-4b24-acb9-15cd33d24535","groups":["system:serviceaccounts","system:serviceaccounts:crossplane-system","system:authenticated"],"extra":{"authentication.kubernetes.io/credential-id":["JTI=59f1b291-552d-437e-b526-0af05ea32b07"],"authentication.kubernetes.io/node-name":["ip-10-254-5-117.ec2.internal"],"authentication.kubernetes.io/node-uid":["c66fda7a-55a8-43d3-a6b8-18788e5a037f"],"authentication.kubernetes.io/pod-name":["crossplane-66cdfd8f66-4ld89"],"authentication.kubernetes.io/pod-uid":["4fdc0811-26ee-4b0f-96d4-e61d07224cb3"]}},"sourceIPs":["10.254.14.190"],"userAgent":"crossplane/v0.0.0 (linux/amd64) kubernetes/$Format","objectRef":{"resource":"objects","name":"bobncom-ngsjm-8f6f35d00355","apiGroup":"kubernetes.crossplane.io","apiVersion":"v1alpha1"},"responseStatus":{"metadata":{},"code":200},"requestReceivedTimestamp":"2026-01-12T23:43:02.137843Z","stageTimestamp":"2026-01-12T23:43:02.183072Z","annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":"RBAC: allowed by ClusterRoleBinding \"crossplane\" of ClusterRole \"crossplane\" to ServiceAccount \"crossplane/crossplane-system\"","k8s.io/deprecated":"true"}}
This cycling of updates only happens when the Object is deployed via a Composition, so the two reconcilers are continuously making no-change updates to the same resource and triggering watch events.
The metadata.resourceVersion changes on every watch event but no other fields are changed.
How can we reproduce it?
Deploy Objects using a composition, start a watch on the Object and observe the events on every reconciliation cycle but no changes to the Object.
What environment did it happen in?
Crossplane version: 2.1.3
EKS 1.33
What happened?
We noticed that there are a large number of no-change update watch events happening in deployments that contain a large number of Object resources.
We are seeing two watch events for every Object in every reconciliation cycle, even when there are no changes
being applied to the objects. The first watch event is triggered by a status update from the provider:
{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"Metadata","auditID":"3b346756-ad1f-42f5-ae0f-62d273f40402","stage":"ResponseComplete","requestURI":"/apis/kubernetes.crossplane.io/v1alpha2/objects/bobncom-ngsjm-8f6f35d00355/status","verb":"update","user":{"username":"system:serviceaccount:crossplane-system:provider-kubernetes","uid":"b81295bd-4f57-4fae-9c8e-a280ae7145ae","groups":["system:serviceaccounts","system:serviceaccounts:crossplane-system","system:authenticated"],"extra":{"authentication.kubernetes.io/credential-id":["JTI=3a085658-fd97-41df-8c4b-e0a1ee20edda"],"authentication.kubernetes.io/node-name":["ip-10-254-0-45.ec2.internal"],"authentication.kubernetes.io/node-uid":["8a56b5dc-c208-477f-8ae4-422bbfd832e4"],"authentication.kubernetes.io/pod-name":["provider-kubernetes-75f7657d8d-pdpcr"],"authentication.kubernetes.io/pod-uid":["b715f9ea-5c3a-4b7a-9d3f-a23003a7bf26"]}},"sourceIPs":["10.254.14.242"],"userAgent":"crossplane-kubernetes-provider/v0.0.0 (linux/amd64) kubernetes/$Format","objectRef":{"resource":"objects","name":"bobncom-ngsjm-8f6f35d00355","uid":"b6b2664a-925d-495c-934f-9daa7930e180","apiGroup":"kubernetes.crossplane.io","apiVersion":"v1alpha2","resourceVersion":"4345770","subresource":"status"},"responseStatus":{"metadata":{},"code":200},"requestReceivedTimestamp":"2026-01-12T23:43:02.299010Z","stageTimestamp":"2026-01-12T23:43:02.324430Z","annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":"RBAC: allowed by ClusterRoleBinding \"crossplane:provider:provider-kubernetes-4da041ccd79c:system\" of ClusterRole \"crossplane:provider:provider-kubernetes-4da041ccd79c:system\" to ServiceAccount \"provider-kubernetes/crossplane-system\""}}This status update triggers a large number of updates to the composite, on the order of 300 log messages:
and the second event occurs a few seconds later in response to the status update:
{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"Metadata","auditID":"372aa3e6-761f-4f5e-abe0-7ea31ea7d09b","stage":"ResponseComplete","requestURI":"/apis/kubernetes.crossplane.io/v1alpha1/objects/bobncom-ngsjm-8f6f35d00355?fieldManager=apiextensions.crossplane.io%2Fcomposed%2F52fe4d13cf623b18c3bb78b1db3201ab61f3c8c2b3891864e5a9a91a371f5a72\u0026force=true","verb":"patch","user":{"username":"system:serviceaccount:crossplane-system:crossplane","uid":"4ac000ef-5307-4b24-acb9-15cd33d24535","groups":["system:serviceaccounts","system:serviceaccounts:crossplane-system","system:authenticated"],"extra":{"authentication.kubernetes.io/credential-id":["JTI=59f1b291-552d-437e-b526-0af05ea32b07"],"authentication.kubernetes.io/node-name":["ip-10-254-5-117.ec2.internal"],"authentication.kubernetes.io/node-uid":["c66fda7a-55a8-43d3-a6b8-18788e5a037f"],"authentication.kubernetes.io/pod-name":["crossplane-66cdfd8f66-4ld89"],"authentication.kubernetes.io/pod-uid":["4fdc0811-26ee-4b0f-96d4-e61d07224cb3"]}},"sourceIPs":["10.254.14.190"],"userAgent":"crossplane/v0.0.0 (linux/amd64) kubernetes/$Format","objectRef":{"resource":"objects","name":"bobncom-ngsjm-8f6f35d00355","apiGroup":"kubernetes.crossplane.io","apiVersion":"v1alpha1"},"responseStatus":{"metadata":{},"code":200},"requestReceivedTimestamp":"2026-01-12T23:43:02.137843Z","stageTimestamp":"2026-01-12T23:43:02.183072Z","annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":"RBAC: allowed by ClusterRoleBinding \"crossplane\" of ClusterRole \"crossplane\" to ServiceAccount \"crossplane/crossplane-system\"","k8s.io/deprecated":"true"}}This cycling of updates only happens when the Object is deployed via a Composition, so the two reconcilers are continuously making no-change updates to the same resource and triggering watch events.
The
metadata.resourceVersionchanges on every watch event but no other fields are changed.How can we reproduce it?
Deploy Objects using a composition, start a watch on the Object and observe the events on every reconciliation cycle but no changes to the Object.
What environment did it happen in?
Crossplane version: 2.1.3
EKS 1.33