Please. Don't Patch Like An Idiot.

UPDATE — 2016-08-06 — Since I wrote this blog post, RFC 7396, introducing the JSON Merge Patch format, has been created. It can be seen as the “just send what you need” format. Therefore, it is valid to only send what you need to update as the [description of changes] as far as it complies with the JSON Merge Patch format.

On an unrelated note, I do apologize for the misuse of the word “idiot”. I did not want to be rude. The exact same word in French is less “strong” than in English.

Modifying HTTP resources is not a new topic. Most of the existing HTTP or REST APIs provide a way to modify resources. They often provide such a feature by using the PUT method on the resource, asking clients to send the entire resource with the updated values, but that requires a recent GET on its resource, and a way to not miss updates between this GET call, and the PUT one. Indeed, one may update values before you, and it can lead to bad side effects. Moreover, sending a complete resource representation utilizes more bandwidth, and sometimes it must be taken into account. Also, most of the time you want to update one or two values in a resource, not everything, so the PUT method is probably not the right solution for partial update, which is the term used to describe such a use case.

Another solution is to expose the resource’s properties you want to make editable, and use the PUT method to send an updated value. In the example below, the email property of user 123 is exposed:

PUT /users/123/email

[email protected]

While it makes things clear, and it looks like a nice way to decide what to expose and what not to expose, this solution introduces a lot of complexity into your API (more actions in the controllers, routing definition, documentation, etc.). However, it is REST compliant, and a not-so-bad solution, but there is a better alternative: PATCH.

PATCH is an HTTP method (a.k.a. verb) which has been described in RFC 5789. The initial idea was to propose a new way to modify existing HTTP resources. The biggest issue with this method is that people misunderstand its usage. No! PATCH is not **strictly about sending an updated value, rather than the entire resource** as described in the first paragraph of this article. Please, stop doing this right now! This is not correct:

PATCH /users/123

{ "email": "[email protected]" }

And, this is not correct either:

PATCH [email protected]

The PATCH method requests that a set of changes, described in the request entity, must be applied to the resource identified by the request’s URI. This set contains instructions describing how a resource currently residing on the origin server should be modified to produce a new version. You can think of this as a diff:

PATCH /users/123

[description of changes]

The entire set of changes must be applied atomically, and the API must never provide a partially modified representation by the way. It is worth mentioning that the request entity to PATCH is of a different content-type than the resource that is being modified. You have to use a media type that defines semantics for PATCH, otherwise you lose the advantage of this method, and you can use either PUT or POST. From the RFC:

The difference between the PUT and PATCH requests is reflected in the way the server processes the enclosed entity to modify the resource identified by the Request-URI. In a PUT request, the enclosed entity is considered to be a modified version of the resource stored on the origin server, and the client is requesting that the stored version be replaced. With PATCH, however, the enclosed entity contains a set of instructions describing how a resource currently residing on the origin server should be modified to produce a new version. The PATCH method affects the resource identified by the Request-URI, and it also MAY have side effects on other resources; i.e., new resources may be created, or existing ones modified, by the application of a PATCH.

You can use whatever format you want as [description of changes], as far as its semantics is well-defined. That is why using PATCH to send updated values only is not suitable.

RFC 6902 defines a JSON document structure for expressing a sequence of operations to apply to a JSON document, suitable for use with the PATCH method. Here is how it looks like:

    { "op": "test", "path": "/a/b/c", "value": "foo" },
    { "op": "remove", "path": "/a/b/c" },
    { "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] },
    { "op": "replace", "path": "/a/b/c", "value": 42 },
    { "op": "move", "from": "/a/b/c", "path": "/a/b/d" },
    { "op": "copy", "from": "/a/b/d", "path": "/a/b/e" }

It relies on JSON Pointers, described in RFC 6901, to identify specific values in a JSON document, i.e. in a HTTP resource representation.

Modifying the email of the user 123 by applying the PATCH method to its JSON representation looks like this:

PATCH /users/123

    { "op": "replace", "path": "/email", "value": "[email protected]" }

So readable, and expressive! Wonderful ♥ This is how the PATCH method MUST be used. If it succeeds, you get a 200 response.

For XML aficionados, RFC 5261 describes an XML patch framework utilizing XML Path language (XPath) selectors to update an existing XML document.

As of late 2014 (that is, after the publication of this article), a new RFC introducing the JSON Merge Patch format and describing another way to send a set of changes has been proposed. It is very similar to the idea of sending only what needs to be updated, but it is explicit thanks to the application/merge-patch+json content type.

To sum up, the PATCH method is not a replacement for the POST or PUT methods. It applies a delta (diff) rather than replacing the entire resource. The request entity to PATCH is of a different content-type than the resource that is being modified. Instead of being an entire resource representation, it is a resource that describes changes to apply on a resource.

Now, please, either don’t use the PATCH method, or use it the right way!

It is worth mentioning that PATCH is not really designed for truly REST APIs, as Fielding’s dissertation does not define any way to partially modify resources. But, Roy Fielding himself said that PATCH was something [he] created for the initial HTTP/1.1 proposal because partial PUT is never RESTful. Sure you are not transferring a complete representation, but REST does not require representations to be complete anyway.

By the way, if you found a typo, please fork and edit this post. Thank you so much! This post is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.

If you like this post or if you use one of the Open Source projects I maintain, say hello by email. There is also my Amazon Wish List. Thank you ♥


Fork me on GitHub