9 ms·
Idempotency is easy until the second request is different
- stavros 5mo agoHalf of the mentioned issues are issues of atomicity, not idempotency. If I make a request, and the server crashes midway and doesn't send some crucial events, that's an issue whether or not I send a second request. From a cursory read, only the part up to "what if the second request comes while the first is running" is an idempotency problem, in which case all subsequent responses need to wait until the first one is generated. Everything else is an atomicity issue, which is fine, let's just call it what it is.
- adamvendel 5mo ago[dead]
- behaviors 5mo agoIf the atomic action is idempotent, you don't need a layer for repeating yourself. You hit the nail on the head. So much idempotency efforts are made because they never made the actions idempotent in the first place.
- asdfaoeu 5mo agoTbh the article seems to just be like "you can't solve idempotency with one idempotency-key header" and well like no shit.
- zinkem 5mo agoIdempotency is easy if you don't use mutable state in your middleware. Auth, logging, and atomicity are all isolated concerns that should not affect the domain specific user contract with your API. How you handle unique keys is going to vary by domain and tolerance-- and its probably not going to be the same in every table. It's important to design a database schema that can work independently of your middleware layer.
- ahoka 5mo agoSo idempotency is easy if your service does not do anything useful?
- mrkeen 5mo agoIt's just the horrible misapplication of the term 'stateless' to a wrapper around something very-much stateful. It's here to stay. (Though I do disagree with the original premise too. Putting on a 'stateless' boxing glove won't mean there's no difference between punching a guy once or twice)
- zinkem 5mo ago> Putting on a 'stateless' boxing glove won't mean there's no difference between punching a guy once or twice There are still side effects in the system, of course. But what your database looks like afterwards is the important part. Can you recover lost data, replay transactions, undo, etc etc?
- zinkem 5mo agoWhether or not your service does something useful is up to you. A database on it's own is enough for most business applications. If you haven't seen this yet, you're just rent seeking.
- shiandow 5mo agoThis seems to assume retrying a command should result in the same response, but I am not sure I agree. Idempotency is about state, not communication. Send the same payment twice and one of them should respond "payment already exists".
- cocoto 5mo agoIn your example, idempotency means same request + same state = same response. State becomes part of the request, that’s why it is hard.
- shiandow 5mo agoThat's just deterministic behaviour. For idempotency you literally just want f(state) = f(f(state)). Whether you achieve this by just doing the same thing twice (no external effects) or doing the thing exactly once (if you do have side effects) is not important. But if you have side effects and need something to happen exactly once it seems a lot more useful to communicate this, rather than pretending you did the thing.
- huflungdung 5mo ago[dead]
- adrianmsmith 5mo ago> But if you have side effects and need something to happen exactly once it seems a lot more useful to communicate this, rather than pretending you did the thing. I think it depends on whether the sender needs to know whether the thing was done during the request, or just needs to know that the thing was done at all. If the API is to make a purchase then maybe all the caller really needs to know is "the purchase has been done", no matter whether it was done this time or a previous time. And in terms of a caller implementing retry logic, it's easier for the caller to just retry and accept the success response the second time (no matter if it was done the second time, or actually done the first time but the response got lost triggering the retry).
- deleted 5mo ago
- chaz6 5mo agoYou keep the hash of the request so that you can reject a subsequent request with a different body. This has helped me surface bugs and data issues in other systems.
- mmillin 5mo agoThis is an excellent article, I’ve seen almost all of the issues it calls out in production for various APIs. I’ll be saving this to share with my team. I’ve seen two separate engineers implement a “generic idempotent operation” library which used separate transactions to store the idempotency details without realizing the issues it had. That was in an organization of less than 100 engineers less than 5 years apart. One other thing I would augment this with is Antithesis’ Definite vs Indefinite error definition (https://antithesis.com/docs/resources/reliability_glossary/#definite-error https://antithesis.com/docs/resources/reliability_glossary/#...). It helps to classify your failures in this way when considering replay behavior.
- villgax 5mo agoskill issue lol, it's not idempotent anymore, same key for different requests? Heard of a nonce?
- mrkeen 5mo agoThe point of idempotency is safe retries. Systems are completely fallible, all the way down to the network cables. The user wants something + the system might fail = the user must be able to try again. If the system does not try again, but instead parrots the text of the previous failure, why bother? You didn't build reliability into the system, you built a deliberately stale cache.
- mrkeen 5mo ago"Idempotency" feels like "encapsulation" all over again. Take a good principle like 'modules should keep their inner workings secret so the caller can't use it wrong', run it through the best-practise-machine, and end up with 'I hand-write getters and setters on all my classes because encapsulation'.
- xlii 5mo agoThat's why you need to separate work from actual input. It's not about trying again but about making sure you get consistent state. Imagine request for payment. You made one and timeouted. Why did it timeout? Your network or payment service error? You don't know, so you can't decide between retry and not retry. Thus practice is: make request - ack request with status request id (idempotent, same request gives same status id) - status checks might or might not be idempotent but they usually are - each request need to have unique id to validate if caller even tried to check (idenpotency requires state registration). If you want to try again you give new key and that's it. There might of course be bug in implementation (naive example: idempotency key is uint8) but proper implementation should scope keys so they don't clash. (Example implementation: idempotency keys are reusable after 48h). If same calls result in different responses (doesn't matter if you saw it or not) then API isn't idempotent.
- mrkeen 5mo ago> You don't know, so you can't decide between retry and not retry I'm well aware that the first order went through, even though the dumb system fumbled the translation of the success message and gave me a 500 back. I do retry because I wanted the outcome. I'm not giving it a new key (firstly because I'm a user clicking a form, not choosing UUIDs for my shopping cart) but more importantly, if I did supply a second key, it's now my fault for ordering two copies.
- raffael_de 5mo agoIdempotency means f(x) = f(f(x)).* Here x is interpreted as state and f an action acting on the state. State is in practice always subjected to side effects and concurrency. That's why if x is state then f can never be purely idempotent and the term has to be interpreted in a hand-wavy fashion which leads to confusions regarding attempts to handle that mismatch which again leads to rather meandering and confusing and way too long blog posts as the one we are seeing here. *: I wonder how you can write such a lengthy text and not once even mention this. If you want to understand idempotency in a meaningful way then you have to reduce the scenario to a mathematical function. If you don't then you are left with a fuzzy concept and there isn't much point about philosophizing over just accepting how something is practically implemented; like this idempotency-key.
- deleted 5mo ago[deleted]
- Hendrikto 5mo ago> That's why if x is state then f can never be purely idempotent That is simply not true. f could be, for example, “set x.variable to 7”, which is definitely idempotent.
- conradludgate 5mo agoThere's no side effects in f here, so the statement does not apply
- Hendrikto 5mo agoParent said > State is in practice always subjected to side effects and concurrency. There was never any claim or assumption regarding f. Maybe the way you interpreted it is what they meant, but it is not what was stated.
- raffael_de 5mo agoyou are oversimplifying with your set variable example. the context is complex state management as with online purchases.
- WilcoKruijer 5mo agoI really hate the POST verb for RESTish APIs because it cannot be idempotent without implementing an idempotency layer. Other verbs are naturally idempotent. Has anyone tried foregoing POST routes entirely? Theoretically you can let the client generate an ID and have it request a PUT route to create new entities. This would give you a tiny amount of extra complexity on the client, but make the server simpler as a trade-off.
- mrkeen 5mo agoIn what sense is GET naturally idempotent? The GET/POST split is the defence (even it's only advisory). GET-only means every time you hit the back button during an order flow, you might double-order.
- randallsquared 5mo agoGET is not supposed to make changes on the server. The usual idempotent verbs for making changes are PUT and DELETE. One thing that's confusing, here, is that idempotency only applies for the same request, but the article implies that idempotency is about whether the request contains a specific "idempotency key". Don't do that, and this problem evaporates.
- kaoD 5mo ago> Don't do that, and this problem evaporates. Don't do that, and you solved nothing. Either I'm missing what you mean, or half the comments here are missing the point of idempotency. Let's say your server received this request twice within one minute: { items: [ { id: 123, amount: 1 } ], creditCardInfo: { ... } } How can you tell from the server if that's a retry (think e.g. some reverse proxy crashed and the first request timed out, but the payment already went through to the user's CC)... or if the user just trying to purchase another item 123 because they forgot they needed 2? There is simply no way to make the requests idempotent without an idempotency key. The only way to tell both situations apart is to key the requests by some UID. The HTTP verb is irrelevant. Did I misunderstand what you meant?
- vanviegen 5mo ago> If you’re still in school, here’s a fact: you will learn as much or more every year of your professional life than you learned during an entire university degree—assuming you have a real engineering job. This rubs me the wrong way. It's stated as fact without any trace of evidence, it is probably false, and it seems to serve no purpose but to make struggling students feel worse (and make the author feel superior).
- riz_ 5mo agoYou're commenting on the wrong article.
- deleted 5mo ago[deleted]
- deleted 5mo ago[deleted]
- echelon 5mo agoI think it's that the things learned in school are academic (red-black trees, dynamic programming, writing toy OS and programming languages, etc.) In the real world you're faced with building five nines active-active systems that interface across various stakeholders, behaviour has to be eventually consistent, you've got a long list of requirements and deadlines, etc. It's practical, hands on, and people are there to build the thing with you at a scale that far exceeds the university undergraduate setting. It's not a bad thing, it's just different. Students shouldn't be afraid of it. Your job and coworkers, if it's a good workplace, are there to help you succeed as you succeed together. You learn and grow a lot. You also learn how to deal with people, politics, changing requirements, etc., which I would imagine is difficult or impossible to teach without just throwing yourself into the fire.
- vanviegen 5mo agoSure, it's different than gaining professional experience. It's more theorical, more foundational, broader. But that doesn't mean you're learning less, let alone 4 times less on a yearly basis. I've been a CS teacher and I found that it's terribly easy to underestimate how much there is to learn and how much effort that learning takes, when you've internalized a skill yourself a long time ago.
- syntex 5mo agoyes I always thought it's an easy thing. but I changed my mind recently when I had to deal with it. A lot little things you need to think of. For example. Client sends a request. The database is temporarily down. The server catches the exception and records the key status as FAILED. The client retries the request (as they should for a 500 error). The server sees the key exists with status FAILED and returns the error again-forever. Effectively "burned" the key on a transient error. others like: - you may have Namespace Collisions for users... (data leaks) - when not using transactions only redis locking you have different set of problem - the client needs to be implmented correctly. Like client sees timout and generates a new key, and exactly once processing is broken - you may have race conditions with resource deletes - using UUID vs keys build from object attributes (different set of issues) I mean the list can get very long with little details..
- dataflow 5mo ago> The database is temporarily down. The server catches the exception and records the key status as FAILED. This is the bug regardless of idempotency, right? It should be recording something like RESOURCE_UNAVAILABLE.
- asdfaoeu 5mo agoNone of those are really unsolvable problems. I think though the issue it seems everyone in this thread is having is you can't wrap a non idempotent function to make it idempotent no matter how hard you try you have to design your system around it.
- DarenWatson 5mo agoA couple of years ago, we experienced a silent data corruption incident in our checkout process due to this specific edge case. A user would generate the idempotency key by loading the front-end application, adding item(s) to their cart, submitting their order but timing out. The user would then navigate back to the front-end application and add another item and submit the order again. Since the user is submitting an identical idempotency key to the same transaction, our payment gateway would look up the request/transaction by idempotency key and see in its cache that there was a successful (200 OK) response to the previous request. The user now believes they purchased three items, however, our system only charged and shipped on two of the orders. Consequently, the lesson we take away from the aforementioned incident is idempotency keys are really composite keys (Client_Provided_Key + Hash(Request_Payload)). If a system receives an identical idempotency key (but with a different request payload) the idempotency key should be rejected with a 409 Conflict response with a message similar to "Idempotency key already used with different request payload". Alternatively, some teams argue it should be returned with a 400 Bad Request response. Systems should never return a failed cache response or replace old entries of data. This article explains how to unlock your flow. The final idempotent key will not be located until the first request completes, but will rather exist when the request is in progress. To safely accomplish your goal, you have to follow the following steps: 1. Acquire a distributed lock on the idempotent key. 2. Check for the existence of a key in your persistent store. 3. If an existing key is found, verify the hash of the payload against the hash for the payload type. If the hashes do not match, return a 409 error. 4. If the hashes match, look up the status of the payload. If the status shows COMPLETED in the persistent store, return the cached response. If the status shows PENDING in the persistent store, return a 429 Too Many Requests to the user or hold the connection open until the request reaches a PENDING state. 5. After processing the request, save the response to the persistent store before releasing the lock. While this may look simple on paper, creating a distributed locking state machine for a single API endpoint is typically how developers have their first aha moments with idempotency. Becoming idempotent is often an enormous architectural shift and not just a middleware header check.
- gib444 5mo agoSounds like an interesting case of incorrectly trusting user input. The idempotency key should have been viewed as the untrustworthy hint it really is. Then you can decide whether an untrustworthy hint is what you really need. At that point I'd hope someone on the team says "This is ordering - I think we need something trustworthy" > Consequently, the lesson we take away from the aforementioned incident is idempotency keys are really composite keys (Client_Provided_Key + Hash(Request_Payload)). Did the postmortem result in any other (wider) changes/actions, out of curiosity? No idea if this was anything like what happened your case, and probably going off on a tangent, but I've seen so many cases where teams are split into backend and frontend, and they stop thinking about the product as a single distributed system (or, it exacerbates that lack of that thinking from before). Frontend often suggest "Oh we can just create an idempotency key" and any concerns from backend are dismissed. If they implement it incorrectly, backend are on the wrong 'team' to provide input.
- ordu 5mo agoWell, it is "reality has a surprising amount of detail"[1] all over again. Or rather a good specific example for it. [1] http://johnsalvatier.org/blog/2017/reality-has-a-surprising-amount-of-detail http://johnsalvatier.org/blog/2017/reality-has-a-surprising-...
- pvillano 5mo agoThanks for letting me read that again. I once wrote about inherent, irreducible complexity and how we try to deal with it. The draft has sections on how complexity can be hidden, spread out, localized, passed off, or recreated from scratch. Unfortunately, people are now using LLMs to pile complexity on the simplest of tasks, and my essay isn't really worth finishing.
- ordu 5mo ago> people are now using LLMs to pile complexity on the simplest of tasks, and my essay isn't really worth finishing. Isn't the opposite true? The more people are messing with complexity, the more they could benefit from a model of a complexity? And if they generate complexity with external tools, then maybe a theoretical take on that will be the only way for them to learn? I mean, we learn these things through struggle and pain, but if all of that becomes an LLM problem, than you just stop learning? But at some point complexity will strike back, at some point there will be as much of it, that LLM will be no help. OTOH, if LLM still win, and skills of managing complexity will be lost in future generations, if we are at the peak of our skills of dealing with complexity, than shouldn't we try our best to imprint our hard won lessons into a history? Maybe for some later generations the tide will turn and they would write textbooks on complexity, and with your article you'll get your portrait in a textbook, and each bored pupil will decorate it with mustaches? You have a chance to immortalize yourself. xD Or maybe you can become someone like Ramanujan for math? Someone who honed obsolete math skills to an unimaginable level? Maybe a time will come, when students will pour over Ramanujan works, because his skills became useful again, and they try to find out how Ramanujan thought? ... Sorry, I just couldn't resist. Seriously, it is hard to predict with LLMs, maybe we will not need intellect or any intellectual skills at all after AGI.
- calmoo 5mo agoI think this article (and the author's previous articles on their blog) is quite clearly AI written. It has such a frustratingly punctuated cadence and really does not serve the reader anything valuable.
- croisillon 5mo agowhy would we read something nobody bothered to write?
- j16sdiz 5mo agoIt did give a few examples of common pitfall. Not well organized, but not zero value.
- simonkagedal 5mo agoWhat really does not serve the reader any value is this comment now appearing on nearly every single HN thread. (And neither does my comment, sorry about that.) If you like the article, upvote. If you don’t, don’t.
- calmoo 5mo agoI would usually agree, but I think we should be obligated to call out slop when we see it.
- fwip 5mo agoI appreciate when people tell me something is AI written, so I can avoid reading it.
- simonkagedal 5mo agoBut people claim that text is AI-written on the most ridiculous grounds, like using proper typography. You might be missing out on interesting stuff!
- fwip 5mo ago
- toshikatsu-oga 5mo ago[flagged]
- xlii 5mo agoDon't fix other people problems. If idempotent key was seen then send back response. Clients intention is outside the scope. If contract says "idempotency on key" the idempotent response on key. If contract says "idempotent on body hash" then response on body hash (which might or might not include extra data). APIs are contracts. Not the pinky promise of "I'll do my best guess"
- pvillano 5mo agoI would rather do more work myself to make an API as fool proof as possible, than hope everyone else is perfect, and lose data when they're not.
- jerf 5mo agoThat just leads to bigger fools. I don't just mean that as clever wordplay, but as a serious point. No matter how sloppy you make your API someone else will use it even more sloppily. Now you've got an enormous sloppy surface you can't properly contain or maintain, and people still transgress its boundaries even so. The robustness principle has its times and places but the general consensus that it should be applied everywhere to everything was a big mistake. The default should be that you are very rigid and precise and only apply the robustness principle in those times and places it applies, and I'm perfectly comfortable waiting to deploy something precise and find out that this was one of them. The vast majority of APIs is not the time and place for the robustness principle. It's the time and place for careful precision on exactly what is provided, and detailed and description error messages, logging, and metrics for when the boundaries are transgressed.
- cookiengineer 5mo ago> APIs are contracts. Not the pinky promise of "I'll do my best guess" You have never had to work with PHP backends, have you? JSON in PHP is a flustercluck. Undefined, null, "" or "null", that is always the question. If you use a typed Go/Rust client and schemas, you usually end up with "look ahead schemas" that try to detect the actual types behind the scenes, either with custom marshallers or with some v1/v2/v3 etc schema structs. It's so painful to deal with ducktyped languages ... that's something I wouldn't wish on anyone.
- transkey 5mo ago[flagged]
- javier2 5mo agoi dont disagree with the problem, but this sort of Idempotency-Key header is kind of outsourcing the de-duplication to the client. If the client sends a different request with same Idempotency-Key header its the user's (client's) fault. Its also circumventing the fact that its the effect that should apply to give the same state, you could design the API itself to be idempotent wrt to some other property such as the transaction id. The designs I have seen using an explicit Idempotency-Key header has usually been added on after launch.
- deleted 5mo ago[deleted]
- randallsquared 5mo agoIf the second request is different, then idempotency doesn't apply.
- deleted 5mo ago[deleted]
- zarzavat 5mo agoHow would you even know the second request is different? Hash every request? That's a waste of resources. The only sensible policy is to trust the key.
- randallsquared 5mo agoNo, the sensible policy is to have the code operate idempotently for every request with an idempotent method. This is a design decision, not something you slap on top afterward with a special key.
- zarzavat 5mo agoI believe you need to read the article. The article is about the Idempotency-Key header. https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Idempotency-Key https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/...
- randallsquared 5mo agoI skimmed the article earlier, but going back and looking, it doesn't appear that the article mentions the spec at all, or links to it. In fact, the first paragraph is literally "People talk about..." Some help for others to understand the history of this (which apparently Stripe, Paypal, Dwolla, and others use): https://github.com/mdn/content/issues/41497 https://github.com/mdn/content/issues/41497 There are links to the RFC and prior art. That aside, my first impulse is to say that the server should specify that the key includes a hash of the important parts of the request, checked on receipt, so that only the key itself need be stored. However, FF's implementation apparently(?) adds the header automatically to POST and PATCH if it's not already present, which means that it's not able to comply with such a decision, and the RFC (currently expired) recommends using a UUID, so. I'm guessing the original motivation of this is "Browser JS might not be able to send a PUT, or proxies may not handle a PUT correctly".
- doginasuit 5mo agoThis article seems to be missing an example use-case for this functionality, it is very unclear to me that this is a good idea. Your job is hopefully to build an API with the simplest and most reliable contract to meet the needs of the client. Sometimes that involves saying, "human technology does not have a reliable way to support this expectation, but here's what else could work."
- ggyanie 5mo ago[flagged]
- jasonlotito 5mo ago> Maybe the first request called a payment provider, the provider accepted it, and your process died before recording the result. Now your database cannot infer whether money moved. This entire example is bad design. It's bad, bad design. I'm sorry, but if this is your example, you are doing it wrong in every way. There are ways to handle these sorts of things, well-known and well-established patterns. You are using none of these here. I get it, it's an example, but it's a poor example. You should change it before someone assumes what you are talking about is sensible or reasonable in a production environment. Or at least put a warning.
- stickfigure 5mo agoThis is all way too much. If you see a duplicate idempotency key, skip the replay and always return 409. This becomes a client problem. Clients already need to help enforce idempotent contracts; "check for conflict response" is not an onerous imposition. I've built multiple ecommerce APIs with this approach and they work great. No heroic measures required. You can often satisfy this contract with a unique constraint; if not, a simple presence check in redis. No hashing or worrying about PII. My rant about this: https://github.com/stickfigure/blog/wiki/How-to-%28and-how-not-to%29-design-REST-APIs#rule-11-do-provide-idempotence-mechanisms https://github.com/stickfigure/blog/wiki/How-to-%28and-how-n...
- Pxtl 5mo ago[dead]
- halestock 5mo agoBut that's not idempotent? If I'm a client and I don't know if the original request went through, getting a 409 on any subsequent requests tells me nothing about whether the original request was successful or not.
- onionisafruit 5mo agoThe 409 should come with an id or a url the client can use to find the original result.
- stickfigure 5mo ago...and if you're using the approach of "let the client pick ids", you don't even need that. The client has everything it needs.
- deleted 5mo ago[deleted]
- stickfigure 5mo ago
- throwaway7783 5mo agoThe article mixes transaction semantics (distributed or otherwise) with idempotency. Idempotency or not, many points in the articles are are about atomic transactions.
- NovemberWhiskey 5mo agoThe real problem is that sticking an idempotency key onto an operation doesn’t make it idempotent. It may improve efficiency where a protocol doesn’t assure exactly-once delivery of messages, but it cannot help you with problems other than deduplication of identical messages. Creating a payment is not an idempotent operation. If the economics of the operation can differ when the “idempotency” key remains the same then you’ve just created a foot-gun in your API. You can document that you’re going to ignore “duplicate” requests that share an idempotency key but that’s just user-hostile. The system as a whole is broken as designed.
- kkyktkrkekk 5mo agoJust do what azure’s api is doing. Just return http/500 on all valid calls. Problem solved.
- nekusar 5mo agoSigh. What this article is badly saying is that they really don't understand the difference between a *transaction* versus idempotency. You want a rebuildable environment after testing blows it up? Idempotent build scripts. You want to sell crap from a web interface? Thats a transaction. If you do 'repeat a sale', thats a new transaction, with new goods, with newer date. Forcing 1 paradigm on a different one always results in gnashing of teeth and sadness. But I guess it gets the blog hits for that dopamine rush.
- amluto 5mo agoI will add: if you have an operation that adds a record to a database (like a payment in the OP example), don’t forget to have some field that the client specifies that can be used to find and query the status of that record later. This field can be the idempotency key itself or another field. Or you can completely forget this feature and make it really awkward for the client to reconcile their view of the world with yours and/or to check in the request later. cough Mercury cough. It is, just barely, acceptable to generate the identifier server side and return it to the client.
- f33d5173 5mo agoWhy does a second request need to replay the response? It seems to solve a ton of issues to just send back "request key already used" regardless of whether the request is the same or whether the previous request succeeded or failed. Is there a common situation where the replay is needed? I think of idempotency being important to deal with caching and the like, not something you should build your client around.
- fallingfrog 5mo agoIdempotency is just the next generation realizing that goto and global variables are still antipatterns. And then some lazy birdbrain will come up with some new way to either jump to a random place in the code without guardrails on program state, or referencing data that other code or threads could have touched, and they'll call it a time saving feature. And then we will all learn the hard way that those annoying restrictions were in place for a reason. This is the great circle of life and death and rebirth
- jrm4 5mo agoUm, is the headline a joke? Like, I thought the entire definition had to do with "the exact same thing twice."
- mwkaufma 5mo ago"An operation is idempotent if applying it once or many times has the same intended effect." No -- Idempotent means _no_ side-effects.
- mbrumlow 5mo ago> “Put an Idempotency-Key on the request. Store the response. Replay it on retry.” Is this the new normal? Assert something, that id clearly broken as the correct, then write a blog fixing their broken logic? You don’t replay it on retry. You signal it is a success on first try, and subsequent request with the same key return 409. Anything else and you are doing it wrong.
- c-fe 5mo ago> Maybe it arrives while the first request is still running. Now your idempotency layer is part of your concurrency control. I recently designed a system where this had to be taken into consideration. I find my solution very elegant: When the request arrives, I put the pending request into a map, keyed by the idempotenceId. This whole operation is executed in one step. Now the event loop may process other requests. If one of them has the same key, it will await the same response object from the store. And then, once i have the response, I resolve both promises with it.
- perkovsky 5mo ago[flagged]
- ever_same_4 5mo ago[flagged]
- rglover 5mo agoA queue with a pre-flight check can assist with this quite well. Requests are queued and executed ASAP and you use a checker function to verify whether future requests/jobs can run. Just check that idempotency key and if it's already in the queue/db, skip it (and if need be, log the double attempt for future forensics).
- jiveturkey 5mo agoWhy isn't github in the list of self-hosted options?
- eezing 5mo agoAn idempotency key enables exactly-once semantics in a distributed system.
- OhMeadhbh 5mo agoI'm not sure this word "idempotent" means what you think it means.
- dickywad 5mo ago[flagged]
- inopinatus 5mo ago> Is it a client bug? Yes.
- viduus 5mo ago[flagged]
- girafffe_i 5mo agoI think you could condense this to a test plan (serious). I think if you come up with the cases in order these are solves problems and yes it’s part of your concurrency control, idempotency is part in parcel of distributed systems, otherwise you’re in your monolith with a wondrous central ACID interface. I would argue sequencing is part of the hard part of idempotency, your business context would decide “when” to apply sequencing is good enough (recall monopoly “bank error collect $$$”). Set and setting is also relevant, most places don’t deal with money or disastrous concurrency scenarios. Now if you want to argue for a paradigm shift for why we shouldn’t be here to begin with and offer a way to get back to scalable centralized db system we’re all hears.