Idempotency Keys: How PayPal and Stripe Prevent Duplicate Payment
Have you ever tried to make a failed payment again and suspected that you payed twice? Payment Service providers such as PayPal or Stripe use a method to handle multiple requests for same payment: Idempotency Keys. Let’s increase our domain knowledge by examining this method together!
The Essence of Idempotency in Payment Systems
Idempotency is a crucial safeguard in digital payment systems, ensuring that transactions are executed just once, no matter how many times a request is sent. Its role is vital in handling the complexities of online payments, from accidental multiple clicks the “pay” button to retrying payment request failed due to network issues. This principle prevents customers from being charged multiple times for the same purchase.
Idempotency Keys
At the heart of idempotency lies the use of unique idempotency keys for each transaction request. When a client initiates a transaction, the payment system requires an idempotency key to be included in the request. This key, often a universally unique identifier (UUID) or a similarly robust random string, is generated by the client. It acts as a transaction fingerprint, allowing the payment system to recognize if the same request is submitted multiple times.
Workflow of Idempotency
- Client sends a payment request (HTTP POST) to the payment service provider by putting idempotency key to request header.
- Payment service provider checks if this idempotency key has been already seen by controlling Redis cache.
- If the idempotency key has been seen, system gets current status of firstly executed request, otherwise processes the request and inserts new payment to Database and idempotency key to Redis cache.
- Payment service provider returns current status of the payment as
HTTP 201-Created: If it’s the first request for that payment
HTTP 422-Unprocessable Entity: If it’s the duplicated request for that payment
Example Request with Idempotency Key
curl https://api.stripe.com/v1/charges \
-u sk_test_BQokikJOvBiI2HlWgH4olfQ2: \
-H "Idempotency-Key: AGJ6FJMkGQIpHUTX" \
-d amount=2000 \
-d currency=usd \
-d description="Charge for Brandur" \
-d customer=cus_A8Z5MHwQS7jUmZ
In this practical example from Stripe request, the -H "Idempotency-Key: AGJ6FJMkGQIpHUTX"
header includes a unique idempotency key. If the request fails due to a network connection error, it can be safely retried with the same idempotency key. This mechanism ensures that, despite any potential retries, the customer is charged only once for the intended amount [1]. The idempotency key AGJ6FJMkGQIpHUTX
serves as a unique identifier for this transaction request, enabling Stripe's systems to recognize and prevent duplicate processing of the same charge.
It’s important to note that the specific names of idempotency key headers can vary across different payment service providers (PSPs). For instance, PayPal employs a slightly different approach in naming and using idempotency keys for its API requests. In PayPal’s case, the idempotency key is provided through the PayPal-Request-Id
header in API calls. If you want to see example payment request of PayPal with idempotency key, please see [2].
Efficient Retry Strategy for Failed Payments with Idempotency Keys
To manage retries for failed payments without overloading the system, employing fixed intervals with exponential backoff is effective. This method increases wait times after each failure of the request with same idempotency key, reducing the risk of server overload. Utilizing idempotency keys ensures retries don’t lead to duplicate charges, maintaining transaction integrity while preventing additional system strain.
Expiration Timeframes of Idempotency Keys
Idempotency keys have a lifespan, after which they expire to prevent the system from becoming overloaded with data. While the specific expiration timeframe for idempotency keys can vary between payment service providers (PSPs), a common practice is to set this period to 24 hours. This duration is often a balance between giving enough time for clients to retry failed transactions (due to network issues or other errors) and preventing the system from holding onto keys for too long, which could impact database performance and storage.
For example, Stripe specifies that idempotency keys are automatically removed from their system after 24 hours [1]. On the other hand, Adyen adopts a policy where idempotency keys are valid for a minimum of 7 days, ensuring uniqueness at the company account level and potentially retaining them longer for enhanced transaction reliability [3]. These policies ensures that if a request is retried using the same key after related periods, it will be treated as a new request, with no risk of referencing a previous transaction’s outcome.
Conclusion
In conclusion, idempotency keys represent a fundamental innovation in digital payments, ensuring transactions are executed once and thereby enhancing security and user experience. Despite variations in implementation across platforms like Stripe, PayPal, and Adyen, the core principle of preventing duplicate payments is universally valued. As e-commerce grows, the importance of these mechanisms will only increase, underscoring the need for reliable and efficient payment systems.
Thank you very much for taking your valuable time to read my article. Don’t forget to clap if you liked this article 👏🏻
References
[1] “Idempotent requests | Stripe API Reference,” stripe.com. https://stripe.com/docs/api/idempotent_requests (accessed Feb. 09, 2024).
[2] “Idempotency,” developer.paypal.com. https://developer.paypal.com/reference/guidelines/idempotency/ (accessed Feb. 09, 2024).
[3] “API idempotency | Adyen Docs,” docs.adyen.com. https://docs.adyen.com/development-resources/api-idempotency/ (accessed Feb. 09, 2024).
[4] “Designing robust and predictable APIs with idempotency,” stripe.com, Feb. 22, 2017. https://stripe.com/blog/idempotency (accessed Feb. 09, 2024).