2026-07-16
Every REST developer has typed PATCH /users/42 without pausing to wonder why HTTP needed a whole RFC — thirteen years after HTTP/1.1 shipped — to add a verb that seems obvious. The history is quirkier than you'd think.
The problem. HTTP/1.1 (RFC 2616) gave us PUT for full replacement and POST for "everything else." If you had a 5 MB resource and wanted to change one field, your options were:
POST /users/42/rename, POST /users/42?_method=update, or the notorious X-HTTP-Method-Override: PATCH header. Every API invented its own dialect.Interestingly, PATCH had appeared in an early HTTP/1.1 draft and was removed before publication. WebDAV in the late 1990s reintroduced the need — partial updates to documents and calendar objects were awkward with PUT — and Lisa Dusseault (a WebDAV veteran) and James Snell (from Atom/AtomPub) finally shepherded a clean spec through the IETF.
The key design decisions. RFC 5789 is only 16 pages, but every choice matters:
Content-Type header tells the server whether you're sending JSON Patch (RFC 6902), JSON Merge Patch (RFC 7396), XML patch, or a diff. RFC 5789 defines the verb, not the language.If-Match and an ETag — the RFC explicitly recommends this for concurrent-edit safety.409 Conflict when the patch can't apply to current state, 415 Unsupported Media Type when the server doesn't grok your patch format, 422 Unprocessable Entity when the document is well-formed but semantically broken.Why it matters today. PATCH is now the backbone of Kubernetes' strategic merge patch, JSON:API's update semantics, GraphQL mutations' pragmatic HTTP counterpart, and virtually every "edit user profile" endpoint in production. Kubernetes actually supports three distinct PATCH content types on the same endpoint — a direct exploitation of RFC 5789's "verb without format" split.
The subtler modern relevance: PATCH is where optimistic concurrency lives on the modern web. If-Match: "etag-value" plus PATCH is how collaborative editors, config-as-code systems, and reconciliation loops avoid lost updates without needing distributed locks. If you've ever seen a 412 Precondition Failed from a cloud API, that's RFC 5789 (plus RFC 7232) protecting you from clobbering somebody else's write.
The gotcha nobody teaches. A shocking number of "PATCH" endpoints in the wild just do a shallow merge of the JSON body onto the resource — which is JSON Merge Patch semantics — but advertise Content-Type: application/json instead of application/merge-patch+json. Technically non-conformant, universally accepted.
