#__molson - Idempotency
1 messages · Page 1 of 1 (latest)
Hello! It sounds like you want to specify a different idempotency key since you're performing a different operation.
Idempotency keys should only be the same when you're trying to do exactly the same thing. If you're making a second attempt (i.e., not the first attempt, but an explicit second attempt) you should be using a different idempotency key.
I guess my confusion is that from the request perspective it is the exact same thing. Same payload and everything. The only change was on the debit card
Right, but the operation you're performing is a different one.
You made a first attempt, it failed. That's done, that's one operation. You want to make a second attempt. That's a totally different operation, a second attempt, so it should be a new idempotency key.
The main reason idempotency keys exist are to allow you to safely retry dangerous operations. For example, if you make a request to take payment and a network glitch prevents you from getting the response... did the payment work or not? If you retried without idempotency and the first payment worked you'd double charge the customer. With idempotency you get exactly the same response back as the first attempt because you're telling Stripe that you're retrying exactly the same thing, not a new thing.
that doens't seem to make sense. If we regenerate a new key on every request, why even use an idempotency key to begin with? We don't have control over the subsequent requests because they are via connected accounts
right now our idempotency keys are a hash of the request parameters. This prevents the same request from being process multiple times in Stripe, causing double charges for the same transaction
if we regenerate a new key on every subsequent requests, but don't change the request parameters, wouldn't the same customer get charged on every request?
That's not how idempotency is designed to work. The idea is that your system attempts a request... if a response doesn't come back due to something like a network error your system should retry that request with the same idempotency key to get back the response that you didn't get the first time.
Idempotency keys should not be based on request parameters because, as you're seeing with this situation, there are reasons to make multiple requests with the same parameters that do not use the same idempotency keys.
chewing on it a bit i think I see what you're saying. We maybe be overextending what the idempotency key was meant to do
from what you're saying, it sounds like we should only be using it if we don't get a response from Stripe--so for retry logic. But we shouldn't be using parts of the request body in the idempotency key as a failsafe against double charging
That's correct.
You can read more about idempotency here and use it as a reference as you're making adjustments to your idempotency logic: https://stripe.com/docs/idempotency
Also, Stripe's official server libraries implement idempotency if you want to see a reference implemention.
Thanks @livid inlet !
What is the use case of the second bullet point in that doc: "Derive the key from a user-attached object like the ID of a shopping cart. This provides a relatively straightforward way to protect against double submissions."
Seems similar to what we were trying to do
That means if someone has, for example, a shopping cart full of stuff you only want them to pay for it once. If you have a unique ID for that cart full of stuff you can use a value derived from that as the idempotency key to make sure they only pay for that specific cart full of stuff once.
we have a system where users charge other users for appointments. We want the user to only be charged once. Would it make sense to use the appointment_id as the idempotency key?
Yeah, or more likely something derived from it that's unique to each API request. Maybe the appointment ID combined with an identifier for the specific operation you're performing, for example.
Like payment-intent-confirm-<appointment_id> or something like that.
okay so that's exactly what we have right now
Sorry, I should have been more clear with my example and said distinct-operation-<appointment_id>.
In the case you described above you would use something like payment-attempt-one-<appointment_id> and payment-attempt-two-<appointment_id> for example.
Apologies for the confusion there.
so basically we shouldn't be using the idempotency key to protect against double charges?
Another way to think about it is potentially-dangerous-operation-that-should-never-happen-twice-<appointment_id>
You should, that's why idempotency keys exist.
But you're making two separate charge attempts.
You don't want any distinct charge attempt to happen twice, but in this case the first charge attempt failed so you want to make a new, distinct, second charge attempt.
okay, so since we make one request that fails with insufficient_funds we can consider that request complete. Then if the user reloads their debit card and retries the request again, this should be considered a new operation/request, and the idempotency key should be different?
Yep, exactly!
Hi @livid inlet , I'm a colleague of __molson's. I'm having trouble with the insufficient_funds example above because I don't think there is any way to know when a user reloads their debit card.
I actually have to run, but @woven patio should be able to help you out further!
OK thank you so much for your help
Appreciate your help @livid inlet !
Hi @woven patio to quickly catch you up- We have idempotency keys based on unique cart IDs. The use-case we are trying to solve for is an insufficient_funds response. We'd prefer to not wait for the keys to expire before being able to retry again. Is there any way around this edge case?
for example, if a customer topped up their debit card and was then ready to retry the charge 10 min after a failed attempt
To make sure we are on the same page, why can't you just retry within the same key?
it will return an idempotency error
unique cart id and request params are unchanged from the first request
And how about firing another request with different key?
doesnt that defeat the purpose of having the key in the first place?
meaning, how do i know it isn't an accidental double submission
The first request has failed with the insufficient_fund error already right? So it's considered as a separated operation. Like my colleague say
You made a first attempt, it failed. That's done, that's one operation. You want to make a second attempt. That's a totally different operation, a second attempt, so it should be a new idempotency key.
They key is meant to be used to dangerous/abnormal case. In this particular use case, I think it's good enough to create a new request and consider them separately
OK I think I understand. The part that feels maybe slightly hacky to me is that that would require me to store on my side that I have already attempted this exact request before. But, is that a common solve?
I think so, yes
ok thank you for your help