I have a REST API endpoint in node.js that handles monetary transactions. I want to implement something similar to stripe's idempotence key to ensure that the same transaction isn't carried out twice in the event of a network failure. How can I implement something like that in Node.js?
2 Answers
You will want each client transaction to generate a UID that it sends with the request. Then, if the client got in any sort of retry scenario, as long as it stays with the same UID, you server could detect a request that was a duplicate of what it had already seen.
There are tons of ways to generate this type of UID. You could literally just stringify the Date.now()
time and then add a random set of digits from Math.random()
onto the end. That gives you time element plus a random element which gives you a good unique token string.
There are also some standards around these types of UID strings. You can read the various answers here: Create GUID / UUID in JavaScript? for both some libraries and some create your own solutions that follow RFC 4122.
Then, your server needs to keep track of a set of incoming UID tokens so it can detect if a request arrives for a token that has already been processed.

- 683,504
- 96
- 985
- 979
-
I get the client side part. But how do I implement idempotency in the server side, ie, how to compare two consecutive requests to detect that the same UUID has been sent? – Subhasis Das Feb 16 '20 at 05:52
-
@SubhasisDas - If you have a server-side session for a "logged-in" client, then you could just keep track of the last N UIDs from that client in the session. Put them in a `Set` object in the session and at each incoming transaction just check the UID to see if it's already in the Set in the session or not. – jfriend00 Feb 16 '20 at 05:54
-
The problem is I'm not using sessions. I use JWT authentication. – Subhasis Das Feb 16 '20 at 05:55
-
@SubhasisDas - Then, you will need to create some sort of server-side state to keep track of recently used UIDs. You can do it either globally since the UIDs should be unique across all clients or you can create a per-client lookup (the same way you'd do per-client rate limiting) based on either client IP or the client JWT. I'd probably just create a global `Set` for all the UIDs. You also have to design a scheme to age out the older UIDs so they don't accumulate forever. I can think of a few schemes for that. – jfriend00 Feb 16 '20 at 05:59
-
Thank you. Will try this out! – Subhasis Das Feb 16 '20 at 06:02
-
@SubhasisDas - For aging out the older ones, one simple way is to create two Set objects. If you want to keep checking for duplicates for 10 minutes, then you put 10 minutes worth of arriving UIDs in the first Set. At that point, you move it to the back burner and start a new Set. Incoming requests are then checked against both the back burner Set and the new one and new UIDs are added to the new Set. After another 10 minutes, you throw away the back burner set, move the current one to back burner and start a new one again. This way, there's no time consuming process aging process. – jfriend00 Feb 16 '20 at 06:05
In your case, as the call is non idempotent, you can call it only once. In case of failure, best is to be contacted directly as a human to check the transaction status and manually fix it.
For identification, use uuid for each call. You can generate it on the client side or on the server side. On the server side is recommended, but the response may never reach the client, so they will not have the id. Other option is to generate it on the client side and accept it as a parameter on the server side. This implies lower trust in those ids, but still useful for easier identification.

- 7,256
- 6
- 38
- 67
-
How can I compare two consecutive requests on the server to know that the same UUID was sent? – Subhasis Das Feb 16 '20 at 05:54
-
How about a pre-approval API call which will generate a payment id? That will be used for the actual payment – Horatiu Jeflea Feb 16 '20 at 06:38
-
I don't think increasing the number of API calls is a good option, especially when the client is an Android device. – Subhasis Das Feb 16 '20 at 06:39
-
This is how card transactions work for example. First you get an approval and only after that there is the settlement. Android does not have any constraints on the number of calls. – Horatiu Jeflea Feb 16 '20 at 06:41