Kubernetes v1.37: Tracking When a PersistentVolumeClaim Was Last Used (Beta)

Kubernetes v1.37 promotes the PersistentVolumeClaimUnusedSinceTime feature gate to Beta (enabled by

default). With this feature, the PersistentVolumeClaim (PVC) protection controller adds an Unused

condition to each PVC, telling you whether any running pod currently references it — no custom

tooling or cross-referencing required.

For the API definition of PVC conditions, see the

PersistentVolumeClaim API reference.

Read on to learn how the Unused condition works and how to use it.

In large-scale Kubernetes clusters, it is common for users to create PVCs and then delete the associated pods without cleaning up the storage, because Kubernetes does not automatically delete PVCs when their pods are removed (to protect against accidental data loss). Over time, these orphaned PVCs may accumulate, silently consuming storage capacity and driving up cloud costs.

Before Kubernetes v1.37, it was easy to identify an unused PersistentVolume, but much harder to determine whether a PVC was still being used. Doing so required cross-referencing pods, PersistentVolumes, and PVCs over a potentially large window of time. Administrators often resorted to custom monitoring pipelines or scripts to answer a seemingly simple question: "Is anything actually using this volume?"

The PersistentVolumeClaimUnusedSinceTime feature solves this by making the answer available

natively in the PVC status. Once the feature is enabled, every PVC gets an Unused condition managed

by the PVC protection controller.

- Storage administrator: "I want to know which PVCs in my cluster are not being used by any pod so I can safely identify orphaned volumes and schedule them for deletion."

- DevOps engineer: "I want to list PVCs that have the Unusedcondition set toTrueso I can automate cleanup in development environments."

The PVC protection controller — which already watches pods to enforce the

storage object in use protection

— now also manages a new Unused condition on PVCs.

The condition works as follows:

A few details worth noting:

- Terminated pods don't count: A pod that has completed (phase SucceededorFailed) does not keep the PVC marked as in use. This means batch jobs withrestartPolicy: Neverwon't prevent the PVC from becomingUnused=Trueafter they finish.

- Pending pods do count: Even an unschedulable pod (for example, one with an impossible node selector) still counts as using the PVC. The intent to use the volume is enough.

- Multiple pods: If several pods reference the same PVC, the condition transitions to

Unused=Trueonly after the *last" non-terminated pod is removed or terminates.

Like every Kubernetes condition, the Unused condition carries a standard lastTransitionTime

field. This means you get a useful bonus for free: when the condition transitions from False to

True, the lastTransitionTime records exactly when the PVC became idle. You can use this

timestamp to answer questions like "how long has this PVC been sitting unused?" — for example,

to find PVCs that have been idle for more than 30 days (see the

example query below).

Kubernetes v1.36 introduced this feature as Alpha, where you had to enable the

PersistentVolumeClaimUnusedSinceTime feature gate explicitly. For Beta in v1.37, the feature gate

is enabled by default, and the feature has full end-to-end test coverage.

Since the feature is Beta and enabled by default in Kubernetes v1.37, the Unused condition will

appear on PVCs automatically. Here is a walkthrough to see it in action:

- Create a PVC: - apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-data spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi

- After a short time, inspect the PVC conditions: - kubectl get pvc my-data -o jsonpath='{.status.conditions[*]}' | jq .- You should see an - Unusedcondition with status- Trueand reason- NoPodsUsingPVC:- { "lastProbeTime": null, "lastTransitionTime": "2026-09-14T12:03:11Z", "message": "No pods are currently referencing this PVC", "reason": "NoPodsUsingPVC", "status": "True", "type": "Unused" }

- Create a pod that uses the PVC: - apiVersion: v1 kind: Pod metadata: name: my-app spec: containers: - name: app image: busybox command: ["sleep", "3600"] volumeMounts: - name: data mountPath: /data volumes: - name: data persistentVolumeClaim: claimName: my-data

- Check the condition again — it should now show - Unused=False:- kubectl get pvc my-data -o jsonpath='{.status.conditions[?(@.type=="Unused")].status}'- Output: - False

- Delete the pod and wait for the condition to transition back to - Unused=True:- kubectl delete pod my-app kubectl get pvc my-data -o jsonpath='{.status.conditions[?(@.type=="Unused")]}'- The condition should show - Unused=Truewith reason- NoPodsUsingPVCagain.

To list all PVCs that have been unused for more than 30 days, you can use a command like:

kubectl get pvc -A -o json | jq -r '

.items[]

| select(.status.conditions[]? | select(.type=="Unused" and .status=="True"))

| select(

(.status.conditions[] | select(.type=="Unused") | .lastTransitionTime) as $t

| (now - ($t | fromdateiso8601)) > (30 * 86400)

)

| "\(.metadata.namespace)/\(.metadata.name) unused since \(.status.conditions[] | select(.type=="Unused") | .lastTransitionTime)"

'

Depending on feedback and adoption, the Kubernetes project intends to graduate this feature to General Availability (GA) in a future release. If you have feedback on this feature, please open an issue in the kubernetes/kubernetes repository.

To learn more about this enhancement, refer to KEP-5541: PersistentVolumeClaim last used time.

The Kubernetes project always welcomes new contributors. If you would like to get involved, you can join us at SIG Storage.

If you would like to share feedback, you can do so on our public Slack channel (visit https://slack.k8s.io/ for an invitation if you need one).

Special thanks to the contributors who helped design and implement this feature (alphabetical order):

- Arvind Parekh (ArvindParekh)

- Hemant Kumar (gnufied)

- Jan Šafránek (jsafrane)

- Kevin Hannon (kannon92)

- Roman Bednář (RomanBednar)