⚡ tldr;
Airbnb needed to design a payment system that wouldn't double charge users if they made duplicate requests like clicking the "purchase" button twice.
They achieved this using idempotency, or making sure the same request keeps returning the exact same failure or success response.
The overall design was to save a request id with it's response to the database and simply return that if the same request was made.
💰 HELP WANTED
This newsletter has grown to 16,000 → 16,500 AMAZING READERS. It’s grown to a scale that a single person can’t maintain all of it on their own.
If you’re interested in being a byte-sized design writer, apply here!
What's the Problem?
When making any payment request for AirBnB, the company needed a reliable system to avoid making double payments.
Nobody wants to get charged twice... ever.
Give me the Requirements
Summarized from the article
The system must be generic. Don't specify this design for reservations or experiences only.
Data has to be consistent. Don't keep data in a weird state.
Low latency. Make the payment requests speedy fast. 🚀
Separate data integrity and data consistency
🧠 Simplify the Design!
Airbnb created their payment system based off of "idempotency", meaning the same request will return the exact same success or failure response.
This correctly handles double payments because if the exact same payment request is made, the server can look up the request in the database to decide whether to complete the request or not, avoiding duplications.
The overall design as explained in the image above is to
Give every request an idempotent key to identify uniqueness. Can be generated by UUID or based off the contents of the request.
Create a database schema with {key: idempotentRequestKey, value: actualResponseForRequest}
For every payment request, if the idempotent key exists in the database, return the response. (This avoid double payments)
If not, process the request and save the response in the database.
But what if there's too many requests?
Start cleaning up the database after a certain time frame. 6 Hours is probably enough to clean up and avoid duplicate requests.
What about Replica Lag?
Don't use replicas, read and write directly to master. Consistency is more important than availability when dealing with payment data.
We're storing everything on a single master node?
Shard it out. No to replicas, yes to shards. Even out the load based off the idempotent key.
📝 Official Article
It was a longer article! Take the time to go through it if you’re curious about payment processing!
Keep reading with a 7-day free trial
Subscribe to Byte-Sized Design to keep reading this post and get 7 days of free access to the full post archives.