Skip to content

Simplify update semantics to do whole object replace #1011

Closed

Description

The way we do updates today is using AIP's field masks. Each Update<Resource>Request message has a google.protobuf.FieldMask update_mask field to specify the paths of fields to merge.

Considering that merge semantics have proven to be hard to get right (Kubernetes went through many iterations to get it right, with strategic merge patch, JSON patch, JSON merge patch, SSA) and that AIP-161 is vague on how to deal with things like non-scalar values (maps and repeated fields), I'm worried we won't get it right either, even more so if we rush it.

This task proposes we start with whole-object updates. This would remove the update_mask field completely and leave the resource field as the only field in the Update<Resource>Request message. Clients will be able to fence the update on either version or UID in the same way they do it today to prevent clients from overwriting each other (i.e. blind updates).

Note that this decision doesn't preclude us from adding some form of patch updates in the future. For example, we could add the update_mask field and let the default (no mask) be whole-object replacement. On the other hand, getting the merge semantics wrong would put us in a bad place where we have to support that forever.

Activity

  1. thockin commented on Aug 18, 2026

    @thockin
    Collaborator

    Clients will be able to fence the update on either version or UID in the same way they do it today to prevent clients from overwriting each other (i.e. blind updates).

    Clarify - are you proposing that clients MAY or MUST specify version and uid preconditions for updates?

    On the other hand, getting the merge semantics wrong would put us in a bad place where we have to support that forever.

    As the author of and repeated triager of several such bugs in k8s, I appreciate the sentiment :)

    I'm OK with this.

  2. jpbetz commented on Aug 18, 2026

    @jpbetz
    Contributor

    I support this.

    The combination of whole object update, with required preconditions for optimistic concurrency, and with preserved fields on the client side, is safe and defensible (and is skew safe!).

    Considering that merge semantics have proven to be hard to get right (Kubernetes went through many iterations to get it right

    This is too generous, actually. Only JSON patch is able to perform all possible patch operations, and it still requires the use of optimistic read/modify/write loops to manage conflicts safely.. SSA has capability gaps that we have not been able to fix. And there is client-side apply hidden there too, to the grand total is 5 patch mechanisms, none of which fully achieve both soundness and fire-and-forget.

    Note that this decision doesn't preclude us from adding some form of patch updates in the future

    For posterity, my current thinking on this is:

    • Even if you have a sound patch mechanism, the only way other to get conflict safety other than concurrently optimistic writes (read/modify/write with preconditions) is to pair a patch mechanism with field ownership tracking on the server.. In k8s this line of reasoning let to SSA. I think the complexity of this solution has proved to not be worth the cost.
    • If you accept that you're not investing on server side field ownership tracking. Then the choices are down to: (a) full object read/modify/write with preconditions, or (b) a patch operation using read/modify/write with preconditions. I don't see update_mask adding much value to the client for (b)...
  3. juli4n commented on Aug 18, 2026

    @juli4n
    CollaboratorAuthor

    Clarify - are you proposing that clients MAY or MUST specify version and uid preconditions for updates?

    I was considering making it a MUST.

  4. laoj2 commented on Aug 18, 2026

    @laoj2
    Collaborator

    Clarify - are you proposing that clients MAY or MUST specify version and uid preconditions for updates?

    I was considering making it a MUST.

    Also related to this: #954

  5. laoj2 commented on Aug 25, 2026

    @laoj2
    Collaborator

    Updates are already doing whole object replace + rejecting update requests containing unknown fields, so I'm closing this issue.

    However, as discussed on the ate upgrade proposal and in #954, the server still needs to clear unknown fields on READ operations. But, we'll track that separately

    cc Haven Xia (@HavenXia) to link the issue

  6. HavenXia commented on Aug 25, 2026

    @HavenXia
    Member

    Thank you! tracked that in #1205

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

area/apiUser-facing API changesarea/api-machinerykind/cleanupSmall fixes that are not bugs, for example a typo in a code comment

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions