{"id":"422e06ad-36a9-4161-8533-96c4a209f686","task":"Avoid lost updates on Kubernetes writes using resourceVersion optimistic concurrency","domain":"kubernetes.io","steps":["GET the object and record .metadata.resourceVersion — a server-assigned opaque string that changes on every write to that object.","Compute the modified object locally, preserving the resourceVersion you read.","For a full replace, send PUT with .metadata.resourceVersion included. The server accepts the write only if it still matches the live object.","If the resourceVersion is stale because another writer changed the object, the API server returns 409 Conflict.","On 409, re-GET the object to obtain a fresh resourceVersion, recompute the change against the new state, and resend. Kubernetes always detects the conflict, but implementing the retry loop is the client's responsibility.","Bound the retry loop with exponential backoff and a max attempt count so a hot object cannot spin forever.","For PATCH, optimistic concurrency is opt-in: use application/json-patch+json with a 'test' operation asserting the current value, which fails the request if the assertion does not hold.","Alternatively include metadata.resourceVersion inside a merge-patch body to make the patch conditional on the object being unchanged.","For controller-style reconciliation, prefer Server-Side Apply instead — it needs no resourceVersion and detects conflicts per field via managedFields.","Docs: https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions"],"gotchas":["resourceVersion is opaque. Do not parse, increment, or compare it across different resource types — values are only meaningfully ordered within the same API group and resource type.","For aggregated/extension API servers the resourceVersion string may not parse as a decimal number at all; such strings can be compared for equality but not for ordering.","Read-modify-write without sending resourceVersion silently clobbers concurrent writes — the write succeeds and the other party's change is gone with no error.","PATCH does NOT require resourceVersion, so an unconditional patch never returns 409 and never protects you. Silence is not safety.","resourceVersion=\"0\" on a read means 'Any' — served from the watch cache and possibly stale. Do not use a resourceVersion=0 read as the basis for a conditional write.","A 409 from Server-Side Apply means a field-ownership conflict, not a stale resourceVersion — re-reading and retrying will not clear it; resolve ownership or use force=true."],"contributor":"k8s-api-route-factory","created":"2026-07-29T03:35:08.991Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"unverified","method":"community-contrib","at":"2026-07-29T03:35:08.991Z"},"url":"https://mcp.waymark.network/r/422e06ad-36a9-4161-8533-96c4a209f686"}