One of the important aspects of REST (or at least HTTP) is the concept that some operations (verbs) are idempotent. As Gregor Roth said several years ago:
The PUT method is idempotent. An idempotent method means that the result of a successful performed request is independent of the number of times it is executed.
Idempotency is also something discussed in the SOA Design Patterns. Over the years there has been a lot said about REST and its perceived benefits over other approaches, with idempotency just one aspect that is often assumed to be understood yet typically not investigated fully. However, a recent posting on the Service Oriented Architecture mailing list has brought a lot of discussion around a concept that many had appeared to assume was fairly straightforward. The inital post starts with:
Currently I am looking at Idempotency of our services and coming up with a prescriptive guide for the enterprise in creating cases you create idempotent services. The question is do does all services need to be idempotent ? Is it realistic ?
It references another blog entry, where that author makes the following assertions:
Of course, implementing idempotency can be complex for the service provider. And complexity costs money. That's probably the real reason why idempotent services are so rare. [...] But once a service is made idempotent, it is foolproof, and can guarantee data consistency across integration boundaries. Services should be made idempotent. It should be an architectural and service design principle. Especially so for services which are used by many service consumers. You can't really push out your own complexity of keeping data consistent to your consumers, can you? The consumers are your customers, you should treat them as such. You gain more customers if you make it easy for them.
This initial posting has generated a lot of responses, including from Cap Gemini's Steve Jones who has this to say:
Idempotent is one of the great rubbish phrases of IT, what it means is 'idempotent in memory'. If you have a comment service with an update capability then clearly from the perspective of the invoker the service has to maintain and manage state. What you mean is can it be horizontally scaled in memory. If you update state, including within a database, then you cannot be idempotent. Idempotent is where you call the same function with the same value and the result is exactly the same, that is the mathematically definition. If you ever update state then you are not idempotent, that its 'a database update' doesn't change anything.
Mark Baker, who has posted a lot on REST in the past, responds to Steve:
There are non-idempotent state updates, like your comment example, and there are idempotent updates that set some datum to some specific value... since obviously if you do that multiple times with the same input, the result will be the same.
Steve agrees with Mark to a point: an operation is mathematically idempotent if it changes nothing with the same input value. However, if there is an update to any state caused by the operation, e.g., it reocrds the latest time of the request, then it is not idempotent.
I've been quite 'impressed' at how people misuse the term these days in IT, I've seen several occasions where people claimed something was 'idempotent' because it wasn't stateful in-memory, even though its consumer effect was recording transactions.
Mark agrees with Steve's strict definition, but believes it does not apply in the context of the original request: idempotency in distributed systems:
[...] the word can only meaningfully refer to the interface and not to the implementation. So if I define an operation, say "set", and define it to be idempotent, then that's all that matters to clients, even if a logentry is generated as part of an implementation of that interface.
Another respondant, Ashaf Galal, makes the assertion that all "reading services" are idempotent since the service is only returning data. However, as Steve points out, this is too simplistic a view and whilst an operation may appear idempotent its implementation may be anything but idempotent (again raising the question about whether this distinction is important):
[...] reading capabilities don't have to be idempotent. 'getNextIterator()' is a reading capability that isn't idempotent as it would increment the iterator. A banking request for a balance wouldn't be idempotent as the request would create an audit log. The returned result might be the same for two subsequent calls (if not changes have happened) but the log entry would be different.
Ashaf responds to Steve by stating that idempotence is a property of the service and not its interface.
The client need to get a proper response from the servcie and he doesn't care if the servcie is idempotence or not, logging or not.
So what do others think? Is there still a misunderstanding with what idempotency means? Does it matter if an operation that is supposed to be idempotent actually makes changes to some state, such as updating a log as Steve mentions?