5

HTTP has safe and idempotent HTTP-methods.

Idempotence in HTTP is not exactly the same as idempotence in mathematics, the definition states:

Methods can also have the property of "idempotence" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request. The methods GET, HEAD, PUT and DELETE share this property. Also, the methods OPTIONS and TRACE SHOULD NOT have side effects, and so are inherently idempotent.

(Note the 'idempotence' is in quotes.)

There is a big potential of confusing safe and idempotent. Safe means, that a request SHOULD NOT have the significance of taking an action other than retrieval.

So, in other words, it should not change anything on the backend.

But if that means it is safe, what exactly does 'side-effect' mean, for idempotent HTTP-methods?

All safe HTTP-methods are also idempotent.

I assume that safe and idempotent are not identical, interchangeable. But many people I have talked with told me, that idempotence means that an idempotent HTTP request shouldn't change anything on the backend. But that actually means that it is safe.

4 Answers 4

9

Safe means no side effects. Idempotent means any side effects must be the same, and therefore that it doesn't matter if they are repeated.

Say I ask my daughter to check if the oven is preheated. That's a safe operation because it has no side effects. She is just looking.

If I ask her to preheat the oven, that's an idempotent operation. If it's already preheating, she is just going to check and leave it in the same state. I can ask her 10 times to preheat the oven, and she will roll her eyes at my terrible memory, but the oven always ends up in the on state.

If I ask her to flip the switch on the oven, that is not idempotent. Whether the oven ends up preheating depends on if it was already preheating.

7
  • Idempotence is just about what the one request changes. You're only guaranteed idempotence if you only stick to idempotent requests. Jun 17, 2020 at 15:24
  • I don't understand the source of your confusion. Idempotence only says that the GET won't change anything. It says nothing either way about what other requests or processes will do. Jun 17, 2020 at 15:38
  • Not only GET requests, but HEAD, PUT and DELETE too. And the request sent should not change the idempotency property at all. To reuse the example in this answer, asking to flip the switch of the oven can not be idempotent, since sending the same request will not always result in the same state. Instead, you can request to turn the oven on, or off. That’ll be idempotent. Turning the oven on 200 times will still result in the oven being on. Jun 18, 2020 at 22:24
  • If you had an operation "DELETE NEXT RECORD" that wouldn't be idempotent, because doing it twice deletes two records. That's why you wouldn't have it in a REST interface.
    – gnasher729
    Jun 18, 2020 at 23:21
  • I cam across this while looking for a reference for another answer and because you are such a highly trusted person here, I feel like I should point out that the first sentence is not correct. As noted in the RFC: "Like the definition of safe, the idempotent property only applies to what has been requested by the user; a server is free to log each request separately, retain a revision control history, or implement other non-idempotent side effects for each idempotent request."
    – JimmyJames
    Jun 28, 2021 at 19:04
8

But many people I have talked with told me, that idempotence means that an idempotent HTTP request shouldn't change anything on the backend.

Those people are wrong.

A PUT or DELETE method is absolutely allowed to change the backend state; what is required for idempotence is that if we start from an initial state S, the final state S' is the same no matter whether the PUT/DELETE request is made 1, 2, 10 or any other number of times (above zero obviously).

Source: the bit of RFC2616 you've quoted.

9
  • 3
    That definition of idempotence applies only if there are no other processes interacting with (the relevant bit of) the state of the system. If the system is in a state S'', different from both S and S', when the request is received, there is no requirement for the repeated request to transition to the state S'. Jun 17, 2020 at 9:47
  • 1
    @MartinFürholz: To "between the second and the 10th DELETE request?" - the RFC talks about subsequent requests. I.e. in this time there are no other requests. If some other requests happen, then such case says cannot be used to decide if it is idempotent or not.
    – mentallurg
    Jun 17, 2020 at 11:37
  • 1
    @MartinFürholz the RFC makes it clear that a sequence can be non-idempotent if something else is modifying the state of the system: "a sequence is non-idempotent if its result depends on a value that is later modified in the same sequence." Jun 17, 2020 at 12:03
  • 2
    @MartinFürholz: You right that RFC does not defines that clearly. You cited RFC 2616. The RFC 7231 gives better definition (also not perfect): if the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request. It still has room for interpretation. But in my opinion it implicitly separates different calls.....
    – mentallurg
    Jun 17, 2020 at 13:19
  • 1
    @MartinFürholz: ... If we apply this definition to your example with 10th DELETE: The purpose is to delete an object with particular ID. 1) If other methods created objects with other IDs, we ignore them because they are not the intended effect for particular DELETE request. 2) If a new object was created with the same ID, 10th call of DELETE will delete this newly created object. The intended effect (an object with given ID should not exist any more) is again reached. Thus, despite other calls in the meanwhile, DELETE is idempotent according to the given definition. What you think?
    – mentallurg
    Jun 17, 2020 at 13:23
1

Idempotence in HTTP is not exactly the same as idempotence in mathematics

No. The meaning is exactly the same.

In the mathematics a function is idempotent if f(f(x)) = f(x).

Let's define f(123) as "DELETE /users/123". Then f(f(123)) means 2 subsequent calls of "DELETE /users/123". If the 1st call deleted a user with ID = 123, then the 2nd call will not find anything to delete and the system state will be the same as after the 1st call. Means, f(f(123)) = f(123), which means it is idempotent.

Important assumption is that the implementation of HTTP methods follows RFC. Because technically you can implement the service in such way that it changes significant data via GET. This would be bad architectural style. But nevertheless we should not forget that this may happen and we should check if particular application really follows RFC recommendations.

what exactly does 'side-effect' mean

To some extent it depends on the context, on the definition.

Example 1. There is a database. Method "GET /users/123" returns data of the user with ID 123 and does not change anything in the database. This is usually considered as "no side effects". Such call may produce log entries on proxy servers on its way, in the application logs, etc. But usually this is ignored.

Example 2. Method "GET /users/123" returns data of the user with ID 123. But application has a specific log table in the database, and every GET call creates a log entry in this database. Many developers will say that significant data don't change in such case. But some may consider it as a significant data change.

Briefly: It makes sense to first talk to your team and define the terms for particular context (project, application), so that everyone in the team understands the words in the same way. Put such definitions to a glossary and make available to all relevant persons.

There is a big potential of confusing safe and idempotent.

It depends on the person. Some may find it confusing, the others don't.

A method is safe if it doesn't change significant data.

But idempotent method may change significant data. What matters is the system state after subsequent calls: Do they produce the same result as the 1st request or not? If the state is the same, then the method is idempotent. For instance, "DELETE /users/123" deletes a user with ID = 123 and thus performs a significant change of data. The 2nd and subsequent calls of "DELETE /users/123" will not change anything more. Thus the state after the 2nd call is the same as after the 1st call. That's why such method is idempotent. Same with PUT or PATCH. The can change data once. But subsequent calls don't change the system state any more and thus are idempotent.

So, the methods DELETE, PUT, PATCH are not safe (in the sense of RFC), because the can change significant data. But they are idempotent.

Consequence: If a method is safe, it is also idempotent. If method is idempotent, it doesn't necessarily mean that it is safe.

10
  • "does not change anything in the database." This is the definition for a safe http-method. Not an idempotent method. Jun 17, 2020 at 11:25
  • @MartinFürholz: If we are talking about database, then this is exactly what RFC says: if the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request. Effect = database change in this case. Side effects (e.g. database changes) are important for definition of both - definition of "safe" and definition of "idempotent".
    – mentallurg
    Jun 17, 2020 at 11:34
  • 1
    The definition of idempotence may be the same between mathematics and programming, but there are some differences in application due to the possibility of side effects in programming. Whereas f(x);f(x) is trivially idempotent in mathematics, it may or may not be idempotent in a programming language. And f(f(x)) may be idempotent in programming while f(x);f(x) is not, or vice versa.
    – 8bittree
    Jun 17, 2020 at 16:28
  • @8bittree: I don't understand with what part you don't agree. The statement f(f(x)) may be idempotent is not a definition. Definition is following: if f(f(x)) = f(x) holds for any x from X then 'f' is idempotent. Example: function f(x) = round(x). In web applications 2 identical requests sent one after another mean namely f(f(x)). Sure, the results can be different. If 'f' means POST and 'x' means the current system state, then f(f(x)) != f(x). If 'f' means GET, then of course f(f(x)) = f(x).
    – mentallurg
    Jun 17, 2020 at 18:32
  • @8bittree: ... To be precise: "f(x)" means not necessarily the actual result after HTTP method was called, but the intended result, exactly as RFC chapter 4.2.2 defines: A request method is considered "idempotent" if the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request.
    – mentallurg
    Jun 17, 2020 at 18:45
0

Taking a quote from the linked definition (emphasis mine):

The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI.

PUT in this context is a method explicitly meant for updating existing resources. But the definition allows for the side-effect of creating the resource, if it does not yet exist.

However, because a valid PUT request requires a resource URI, repeating the request should never result in the creation of multiple resources. After all, while the first request may have the side-effect of creating the resource, subsequent calls should always modify the - now existing - resource instead.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.