70

I was wondering about this.

Suppose I have a user resource with id and name fields. If I want to update a field I could just do a PATCH request to the resource like this

PATCH /users/42
{"name": "john doe"} 

And then the application will update user 42 name.

But why if I repeat this request the outcome would be different?

According to RFC 5789

PATCH is neither safe nor idempotent

seldon
  • 952
  • 1
  • 7
  • 13
  • @gnat doesn't a similar argument hold also for the PUT method which is instead considered idempotent? (see http://goo.gl/t24ZSJ) – seldon Oct 24 '14 at 09:16
  • "PUT has idempotent semantics and thus can be safely used for absolute updates ( ie we send entire state of the resource to the server ), but *not also for relative updates ( ie we send just changes to the resource state )*, since that would violate its semantics..." ([POST and PUT requests – is it just the convention?](http://programmers.stackexchange.com/q/242911/31260)) – gnat Oct 24 '14 at 09:22
  • 1
    Obviously... But you could say PUT is not idempotent because between two equal requests a second client could make a third request in-between the two But since we don't care about previous data, that's not a problem. The same argument holds for PATCH requests. – seldon Oct 24 '14 at 09:26
  • 2
    I took the liberty of adding a reference to the relevant specification, as I believe that is highly relevant in the context of this question. – Pete Oct 24 '14 at 09:52
  • Could be, that PATCH execution relies on the client's threads count and may be affected while clicking 'refresh page' during call? – Michael Cheremuhin Oct 24 '14 at 10:43
  • I don't think so. See the approved answer. – seldon Oct 24 '14 at 10:50
  • Related: https://stackoverflow.com/questions/41390997/why-patch-is-neither-safe-nor-idempotent – Ciro Santilli OurBigBook.com May 04 '18 at 07:42
  • The point is whether or not _your_ `PATCH` is `idempotent` depends on what your `PATCH` does. – Thomas Junk Sep 19 '22 at 13:44

4 Answers4

53

A PATCH request can be idempotent, but it isn't required to be. That is the reason it is characterized as non-idempotent.

Whether PATCH can be idempotent or not depends strongly on how the required changes are communicated.

For example, if the patch format is in the form of {change: 'Stock' add: -1}, then any PATCH request after the first one would have a different effect than the first request, i.e. a further decrease in the assumed stock of the product.

Another reason for non-idempotency can be that applying the modification on something else than the original resource can render the resource invalid. This would then also be the case if you apply the change multiple times.

Robert Harvey
  • 198,589
  • 55
  • 464
  • 673
Bart van Ingen Schenau
  • 71,712
  • 20
  • 110
  • 179
  • 5
    I don't understand the last paragraph, can you give an example of how "applying the modification on something else than the original resource can render the resource invalid", and how this relates to applying a change multiple times to the same resource? – Robin Green Aug 12 '15 at 10:44
  • 3
    @RobinGreen: Assume that the resource is represented in XML with the requirement that there is at most one `` element. If the PATCH adds a `` element to a resource the originally didn't contain one, then applying the PATCH twice (or applying it to a resource that already contains a ``) makes the resource invalid, because it would suddenly contain two `` elements which is not allowed for such resources. – Bart van Ingen Schenau Aug 12 '15 at 11:41
  • 24
    The first example you gave isn't relevant IMHO as it is idempotent. Example with DELETE which is idempotent, first request: resource existed but has been deleted (returns 2xx), second request: resource doesn't exist and still doesn't exist after the request, returns 4xx. The server state hasn't changed, thus the idempotency. In your example, first request: PATCH from BenFra to JohDoe, resource name was BenFra but now is JohDoe (returns 2xx), second request: PATCH from BenFra to JohDoe, resource name was JohDoe and still is JohDoe (returns 4xx). So this doesn't show PATCH can be nonidempotent. – sp00m Nov 18 '16 at 11:05
  • More details here: http://stackoverflow.com/q/4088350/1225328 – sp00m Nov 18 '16 at 11:16
  • I agree with sp00m, the server response has nothing to do with idempotency; the change in server state is all that matters. I'm yet to find a good example as why patch is not idempotent. Mozilla puts it this way, but I'm not convinced yet: For example if an auto-incrementing counter field is an integral part of the resource, then a PUT will naturally overwrite it (since it overwrites everything), but not necessarily so for PATCH. From: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH – Igor Donin May 01 '22 at 12:44
  • It's awful that this is the accepted answer, only the first sentence is actually correct. A PATCH can be non idempotent e.g. if it's applying a mathematical operation on part of a resource, so every identical request results in the resource being different. The response code has nothing to do with it!! – jamheadart Sep 19 '22 at 00:46
  • 3
    @jamheadart, I have updated the example to use a calculation. – Bart van Ingen Schenau Sep 19 '22 at 08:46
  • I think, this is no good example of `PATCH` being non idempotent - because it is a nonsensical implementation of something RPC-like "add" which leads to side-effects. – Thomas Junk Sep 19 '22 at 13:21
25

PATCH requests describe a set of operations to be applied to a resource, if you apply the same set of operations twice to the same resource, the result may not be the same. This is because defining the operations is up to you. In other words you have to define the merging rules.

Remember a PATCH request could be used for patching resources in many different formats, not just JSON.

So a PATCH request can be idempotent if you define the merging rules to be idempotent.

Idempotent example:

// Original resource
{
  name: 'Tito',
  age: 32
}

// PATCH request
{
  age: 33
}

// New resource
{
  name: 'Tito',
  age: 33
}

Non-idempotent example:

// Original resource
{
  name: 'Tito',
  age: 32
}

// PATCH request
{
  $increment: 'age'
}

// New resource
{
  name: 'Tito',
  age: 33
}

In the second example I used a "Mongo like" syntax I made up for incrementing an attribute. Clearly this is not idempotent, as sending the same request multiple times would result in different results each time.

Now you may be wondering if using such a made up syntax is valid. According to standards, it is:

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.

And you may also be wondering whether it is restful to use PATCH requests this way, and many people consider it is not, here's a good answer with lots of comments about the issue.

So, according to standards, it is not idempotent (unless you want it to be). Making it idempotent is definitely restful. Whether it is restful keeping it not idempotent that's debatable.

broAhmed
  • 5
  • 2
Jbm
  • 417
  • 4
  • 6
18

I think clear answer when PATCH in not idempotent is this paragraph from RFC 5789:

There are also cases where patch formats do not need to operate from a known base-point (e.g., appending text lines to log files, or non- colliding rows to database tables), in which case the same care in client requests is not needed.

As RFC specifies that patch contains some "general changes" to the resource, we should look beyond just typical field replacement. If resource is for a counter, then patch can request it's increment, which is clearly not idempotet.

Ivan
  • 281
  • 2
  • 2
0

GET is supposed to be idempotent. If I implement it on the server, and you rely on it being idempotent, but my implementation isn’t, it’s my fault.

PATCH is not guaranteed to be idempotent. So in the exact same situation, it’s your fault. Of course if I write the client code then I can publish that some specific operations are idempotent, and it would be useful to explain how other operations are not.

gnasher729
  • 42,090
  • 4
  • 59
  • 119