TIL: a finalizer doesn't mean 'important' — it means 'don't delete me yet'
I used to treat finalizers as a vague ’this object matters’ flag. They’re not. They’re a deletion lock: the API server will mark the object for deletion, but it won’t actually remove it from etcd until every finalizer is gone.
When you kubectl delete something with finalizers, what you usually see
is metadata.deletionTimestamp get set. From that point the object is
terminating. Controllers watching for that timestamp are supposed to do
their cleanup, then patch the object to remove their finalizer from
metadata.finalizers. Only when the list is empty does the API server
finish the delete.
That’s why a Namespace or a custom resource can sit in Terminating
forever — something still has a finalizer registered and nobody cleared
it (controller crashed, CRD gone, webhook dead, operator uninstalled
wrong).
metadata:
name: stuck-thing
deletionTimestamp: "2026-09-02T12:00:00Z"
finalizers:
- example.com/cleanup
So when something won’t die, don’t start with ‘Kubernetes is broken’.
Look at deletionTimestamp and finalizers first. The gap between
‘I asked to delete it’ and ‘it’s gone’ is exactly those strings.