Designing Idempotent API Endpoints for Payments at Stripe

Поділитися
Вставка
  • Опубліковано 22 гру 2024

КОМЕНТАРІ • 90

  • @krum.00
    @krum.00 Рік тому +27

    The idea of Idempotentency for APIs means that clients can retry the request without changing the state of the system. Whether the server processes the request multiple times or once(as in this case) is an internal detail. Informative video nonetheless!

  • @saikatmukherjee8683
    @saikatmukherjee8683 Рік тому +6

    You said when the operation is successful, the server will delete the key from Redis. Wondering how would the server know that operation was successful if a retry comes in with same key? Server should not delete the key but rather should keep it in the key-store till the time the payment url is valid and then delete it based on ttl

  • @ankk98
    @ankk98 11 місяців тому +2

    Idempotency is a very important concept in software development.
    We have developed our apis in such a way that the values are always overwritten instead of some other operation like increment operation. We can do this as we are sure that there will always be a singular api call.

  • @sahilguleria5505
    @sahilguleria5505 Рік тому +7

    Great video, had some queries
    1. Is the idempotence key unique to each transaction?
    2. What if the client crashes looses the idempotency key and when it resumes it retries with different idempotency key. That will be treated as a new transaction and same operation is done twice?

    • @harendraprasad6209
      @harendraprasad6209 Рік тому +1

      I had the same concern, and addition to that if on one failure cant it request a new key and then tries with it again ?

    • @lbirkert
      @lbirkert Рік тому

      @@harendraprasad6209 what you could try is to just put the key somewhere where it is stored even after a page refreshes like as an URL parameter or in the localStorage. There will still be a chance that the client looses its key. If this happens you could implement a protection, which diffs the transaction (amount, user that the payment is directed to) and then notify the user that a similar transaction has already been made and ask for his approval to send this money twice.

    • @shilpakini2034
      @shilpakini2034 4 місяці тому

      I was also wondering how does the client persist the idempotent key

  • @lknockoutl
    @lknockoutl Рік тому +6

    If the server crashes right after hitting the Payments DB you will not have updated the Redis. The client will call the API again and hit the Payments DB once again.
    How do you handle that scenario?

    • @cowabunga2597
      @cowabunga2597 Рік тому +1

      I wont

    • @anuragdas1978
      @anuragdas1978 7 місяців тому +1

      make it atomic, so it can rollback

    • @InvincibleMan99
      @InvincibleMan99 5 місяців тому

      As far as i understand, it should be in some transaction, so it will rollback

  • @abhikumar310
    @abhikumar310 Рік тому +2

    Thanks for the helpful video.
    One thing, this will have possibility of race-around condition if one request with idempotent key is under-process and the other request could come-up.
    How to handle these situations?

  • @johnrush607
    @johnrush607 11 місяців тому +2

    Does the idempotency key have to be generated on the server side? Seems like the client could generate the unique identity instead, collisions should be minimal?

    • @AsliEngineering
      @AsliEngineering  11 місяців тому +1

      Server should generate it. If done on client side then people can spoof the flow.

  • @karanyadav5549
    @karanyadav5549 4 місяці тому +1

    where can i get your notes?

  • @gauravraj2604
    @gauravraj2604 Рік тому +3

    Hi Arpit,
    Thank you for such informative video. I really admire you putting your continuous efforts towards "Real Engineering".
    Can you please tell me if my approach is correct or not:
    1. Client requests idempotency-key from server. Server generates one, save it in a key-value store and return it.
    2. Client sends idempotency-key as header along with other parameters in its request.
    3. Case a: If due to network failure request did not reach the server, then client retries along with same idempotency-key.
    4. Server processes the request, deletes the idempotency-key from the store and return response to client.
    5. Case b: If request reaches the server and the server starts processing but in between it got failed, in this case as well idempotency-key remains intact, and client can send retry request.
    6. Case c: On retry request, say it got successful and idempotency-key got deleted but client did not receive the response.
    7. Client will retry with same idempotency-key. Since server could not find idempotency-key, there can be two possibilities which are either this request was already processed, or idempotency-key is invalid.

  • @rajatiitr
    @rajatiitr Рік тому +2

    Hi Arpit,
    Hope you're doing well.
    I joined Adobe last month. I would like to thank you for providing the best quality content on design [not just for interviews but beyond that] on your channel. It helped me a lot
    Thanks!!

    • @AsliEngineering
      @AsliEngineering  Рік тому

      Congratulations 🎉🎉 keep soaring 🚀

    • @gmmkeshav
      @gmmkeshav Рік тому

      writting bhi bahut payari hai sir ki may be a font I guess

    • @AsliEngineering
      @AsliEngineering  Рік тому +1

      @@gmmkeshav not a font. That's my handwriting.

    • @gmmkeshav
      @gmmkeshav Рік тому

      @@AsliEngineering 🙏🙏🙏

    • @rajeshgopidi7842
      @rajeshgopidi7842 Рік тому

      @@AsliEngineering can you please share name of the app that you are using for white boarding?

  • @kapilchoudhary2922
    @kapilchoudhary2922 Рік тому

    Simply amazing, nothing else!! Thank you so much for making these kind of educational videos which help the dev community.

  • @sachinjindal4921
    @sachinjindal4921 Рік тому +1

    I really like your way of explaining. The way you put a blog into simple understandable language.
    Thanks Arpit for bringing such kind of content.
    Keep inspiring us 🙂

  • @sheikhsaifuddinahmed7375
    @sheikhsaifuddinahmed7375 Рік тому +3

    At 12:35 if the server is deleting the key after the request is handled, that means after the response is send, now let's say the response could not reach the client because of network issue, the client will retry, but the server has already delete the key, so it would consider the retry request as a new request so how to handle that

    • @koteshwarraomaripudi1080
      @koteshwarraomaripudi1080 Рік тому +2

      If we don't have the idempotent key in the DB that means, it is processed. If its a new request it should have obtained the key from the key generator and it will be present in the DB

    • @shashankagrawal1902
      @shashankagrawal1902 Рік тому +2

      "Keys are eligible to be removed from the system automatically after they're at least 24 hours old": stripe doc. They don't immediate delete it, to handle cases mentioned by you.

  • @ajaysaini6934
    @ajaysaini6934 Рік тому +1

    I was wondering about it's optimisation further. Will it makes sense to batch GET the keys, in order to avoid two trips to downstream service for every request.
    Absolutely incredible technique. Thanks for bringing up such informative content consistently.

  • @tarunkishore9508
    @tarunkishore9508 10 місяців тому +1

    Thanks for the video, my question is why should'd we store that idmpotent key on the primary db itself this will help us take leverage of db transactions, because there could be a case where the payment transacition is successful but while deleting the idempotent key from redis an error occurred and key didn't gets deleted.

    • @InvincibleMan99
      @InvincibleMan99 5 місяців тому

      +1, Agree with you. Also we will have the history of api's (transactions)

  • @SentryProductions1
    @SentryProductions1 9 місяців тому

    Nice video - we use this in open-banking for retrieving a request/consentToken prior to making a payment (we can build on top of OIDC and OAuth)

  • @koteshwarraomaripudi1080
    @koteshwarraomaripudi1080 Рік тому +3

    How do we handle the following scenario,
    money is successfully transferred from A to B but we have failed to delete the idempotent key from DB (maybe because of a DB issue). Now if the client retries we will process it again right. How do we handle this kind of scenario?

    • @akashshirale1927
      @akashshirale1927 Рік тому

      Good question...Ans: Store the idempotent key with TTL of milliseconds in Redis, that will solve this issue.

    • @koteshwarraomaripudi1080
      @koteshwarraomaripudi1080 Рік тому

      @@akashshirale1927 Thanks. let's say we failed to process the request because of any xyz reason in that case key should not be deleted that means we have to increase ttl of that key. Now what if we failed to increase the ttl? Then the key would be deleted and we would consider request as processed even though it is not processed

    • @akashshirale1927
      @akashshirale1927 Рік тому +2

      @@koteshwarraomaripudi1080 You might hear arpit saying a lot of this...Simple systems scale...complicated systems don't scale. So here we would just fail the request if the key is not present And just tell the user to retry his operation and give him a new idempotent key.

    • @koteshwarraomaripudi1080
      @koteshwarraomaripudi1080 Рік тому +1

      @@akashshirale1927 Thats true. I guess it's better off to fail off the request by guaranteeing idempotent. Thanks a lot Akash

    • @sandeepsahani1439
      @sandeepsahani1439 2 місяці тому

      @@akashshirale1927 Also if the server has failed to process the request, it should not persist the key in cache, it should be a transactional flow, no? And yes, in this case just fail everything and start a new transaction.

  • @ashwanidu-mca5935
    @ashwanidu-mca5935 Рік тому

    Hi Arpit, I want to task 1 thing. Which all tools do you use to create the content, how your video is coming along with notes being shared ?

  • @shashankagrawal1902
    @shashankagrawal1902 Рік тому +1

    Hey Arpit, great stuff.
    Quick question: 8:25 you mentioned client talking to server to generate a random id,
    but instead of talking twice to the server, it can generate an idempotence key and share it along the payload with the server in a single step.
    And if server is seeing it for the first time it can store it, right?

    • @AsliEngineering
      @AsliEngineering  Рік тому

      It defeats the purpose. You cannot guarantee idempotency through this. Easily hackable

    • @adityasheth
      @adityasheth Рік тому

      @@AsliEngineering Hi Arpit, I had the same question. Can you please explain how it's easily hackable?
      I read the blog of stripe and they are generating random idempotence key at client-end itself.

    • @AsliEngineering
      @AsliEngineering  Рік тому +1

      @@adityasheth if end user/ frontend is responsible for generating idempotent keys and sending it to backend. What stops then to generate a new key every time and not adhere to the protocol of reusing.

    • @adityasheth
      @adityasheth Рік тому +1

      @@AsliEngineering That makes sense.
      In that case, even a mistake of API call with a new idempotent key from the end-user can make double transactions that way.

    • @JohnMcclaned
      @JohnMcclaned Рік тому +2

      @@AsliEngineering You are conflating security with Idempotency. Idempotency covers the case when a client request is left in a situation where it doesn't know if the request was executed or not. The client needs a reliable way to send the SAME request to the server and have it be recognised as a duplicate send. It can generate a uuid. The server can make the decision to ignore or execute.
      If a "hacker" maliciously double executes requests, it doesn't matter (they transfer money twice), it doesn't hurt anything. Your goal is trying to prevent normal users accidentally double submitting, not malicious users poking around and losing their money twice.

  • @arpanghoshal2579
    @arpanghoshal2579 Рік тому

    Consider this scenario
    Server gets a payment request with a idempotency key and beings processing the request, mean while due to some network error the client reties the same request with the same idempotency key. At this point the server is still processing the initial request so the idempotency key is still marked as unused. What happens here?
    Even if the server marks the idempotency key as "used" immediately when it starts processing the request still we might end up with this problem in some rare scenarios due to race conditions. The only way to the solve this that I can think of is some kind of locking or transactions on the DB layer.

  • @shishirchaurasiya7374
    @shishirchaurasiya7374 Рік тому

    When you say na at the end Hope you found it interesting there at that point I just wanna shout and say its very very very interesting

  • @arhamcodes
    @arhamcodes Рік тому +2

    Great tutorial!! Have some doubts:
    What if you have a microservice architecture and you have multiple APIs in the backend?
    Each of those APIs would be storing the idempotent key? and what if request is failed somewhere between whole APIs?

    • @rajeshdansena
      @rajeshdansena Рік тому +1

      I think in this case, you must need a distributed system which should maintain the idempotent keys and status of it. If there are many APIs which needs this key and need to update the status then you may consider any data structure/a way to store multiple status and have a final status.

    • @akashshirale1927
      @akashshirale1927 Рік тому

      True…you can store keys in redis cache and each api will request a key from a redis key pool

  • @adityasoni1207
    @adityasoni1207 Рік тому

    Thanks for an amazing video! Have we discussed about fencing tokens? Thanks

  • @nabhavlogs371
    @nabhavlogs371 Рік тому

    How to handle cases when the request is partially processed? In this case, neither i can save the idempotent response, nor I want my system to reprocess the work that has already been done.

    • @AsliEngineering
      @AsliEngineering  Рік тому

      Depends on the usecase. Not everything is resumable.

  • @abhishekvishwakarma9045
    @abhishekvishwakarma9045 Рік тому

    Thanks arpit sir, great explanation🔥 easy to understand 😎

  • @barebears289
    @barebears289 Рік тому

    I want to buy your pre recorded cohort videos, but why are they from your June cohort not the latest one?

    • @AsliEngineering
      @AsliEngineering  Рік тому +1

      Because June 2022 is the best till date, also after June only 2 more have happened. I give the best till date in recordings.

    • @barebears289
      @barebears289 Рік тому

      @@AsliEngineering 🙏

  • @rohitsrivastava3768
    @rohitsrivastava3768 Рік тому

    Sorry if I missed out but curious to know what will happen to case 3 with Idempotency key where the server has completed the execution but somehow there was network issue while sending the response back to the client.

    • @ayush_walia
      @ayush_walia Рік тому

      Well server knows it has processed the transaction with that idompotent key. client doesn't get the response so it retries with same idompotent key. This time hopefully response doesn't fail again so client gets the success response.

    • @rohitsrivastava3768
      @rohitsrivastava3768 Рік тому

      So question still stays the same, if the client does a retry, server will know it has marked that request with the same Idempotency key as completed, so won't it throw error or ignore the request?

    • @ayush_walia
      @ayush_walia Рік тому

      @@rohitsrivastava3768 why ignore? Just respond as ALREADY_PROCCESSED or something

    • @barebears289
      @barebears289 Рік тому

      @@rohitsrivastava3768 next time the client will know with server responds with already done.

    • @hemanthaugust7217
      @hemanthaugust7217 Рік тому

      @@ayush_walia How long can we keep the key in server? I think we can delete these keys older than a few minutes, right? As old keys anyway don't make sense.

  • @SiddharthAgrawal-u2l
    @SiddharthAgrawal-u2l Рік тому

    Why can't the client generate the idempotency key on its own? Why does it need to ask server to generate it?

  • @rahulpanjwani1887
    @rahulpanjwani1887 Рік тому

    Any idea on how to make api calls idempotent in case a new request is submitted within a matter of milliseconds by a user by mistake? Here in this case the new request will have a new idempotent key and hence it will be treated seperately by the server, right?

    • @AsliEngineering
      @AsliEngineering  Рік тому

      Transactions solve this.

    • @gauravraj2604
      @gauravraj2604 Рік тому

      @@AsliEngineering I did not get it Arpit. Can you please explain a bit more?

  • @soodankit1993
    @soodankit1993 Рік тому

    Hi Arpit,
    I think there is an edge case here but I might be mistaken. Consider a scenario where the idempotence key was sent and application tried to do the operation. Once operation is successful, we will commit the same to our key value store. But there is a possibility that our key value store is down or application went down before making that call.
    In this case, consumer will send the request again and application will still do the reprocessing. Is there a way to handle this gracefully.

    • @kaykay-d9y
      @kaykay-d9y Рік тому

      You'd typically store this information in your backend as well, and could check for the same transaction there. (If it exists, ignore/return success or error)

    • @AsliEngineering
      @AsliEngineering  Рік тому +2

      Why commit to KV store. Should be modelled as a transaction.

    • @gauravraj2604
      @gauravraj2604 Рік тому +1

      @@AsliEngineering If I am correct, you are saying that doing the operation and storing the idempotency key into key-value store should be under single transaction boundary. That means in case, storing fails all changes done till now will rollback.

    • @charan775
      @charan775 Рік тому

      ​@@gauravraj2604 not possible in case of money transfer APIs though. you have to create refund.

    • @charan775
      @charan775 Рік тому

      but I would generally if the operation is creating some entry in DB, better to store reference key there.

  • @nasirmushtaq6056
    @nasirmushtaq6056 Рік тому

    Thanks for making videos public

  • @abcd-sf5ur
    @abcd-sf5ur Рік тому

    I am having 4 months experience as SDE-1. Can I join your course? is it beginner friendly?

    • @AsliEngineering
      @AsliEngineering  Рік тому +1

      My course is not beginner friendly. It is meant for 2+ years of work ex. The detailed curriculum is listed on my website.

  • @OffRoadEngineerVlogs
    @OffRoadEngineerVlogs Рік тому

    Nyc information bhai ❤️

  • @cooldudecs
    @cooldudecs Рік тому

    I call the random key architecture a newbie architecture. State change only occurs on when key doesn't exist

  • @gsenthilkumar8139
    @gsenthilkumar8139 8 місяців тому

    Idempotent key is generated by client it self using UUID lib not by calling the server

    • @AsliEngineering
      @AsliEngineering  8 місяців тому

      Both approaches are possible, I prefer doing it at server side to have greater control.

  • @gmmkeshav
    @gmmkeshav Рік тому

    maja agaya sir

  • @waleedahmad2012
    @waleedahmad2012 Рік тому

    So a single network request would be converted to two requests for one operation😵

  • @ankitkalavagunta8951
    @ankitkalavagunta8951 Рік тому

    If redis goes down you've lost state. You need a persistent DB.

  • @gomchik
    @gomchik Рік тому

    Please allow me to join Feb cohort

    • @AsliEngineering
      @AsliEngineering  Рік тому

      Feb cohort is full and really sorry I cannot accommodate more. I am just trying to maximize learning outcomes. I hope you understand.
      Looking forward to seeing you in the April cohort. The admission will open in March first week. Please join the waitlist to get notified.

    • @rohitsrivastava3768
      @rohitsrivastava3768 Рік тому

      Video Published: 2 hrs back today
      This comment: 1d ago
      How is this even possible 🥺

    • @AsliEngineering
      @AsliEngineering  Рік тому +1

      @@rohitsrivastava3768 it was a premiere. The video was listed but was not playable until today 10 am.

    • @gomchik
      @gomchik Рік тому

      @@rohitsrivastava3768 The Video publisher can schedule a stream in advance on UA-cam.