Reliability is crucial for this type of platform since the users should trust that the payment is done successfully
Strong Consitency, and durability Is one of another key feature since a success or a failed payment should clearly indicate it and should be not lost.
Security should be strong to avoid unwanted payments. Encryption with expiration on the payment links should be included to be able to identify that the link is generated by the platform. Here the signing of the URLS should be included to assure authenticity including the expiration.
Let's suppose the system will have 1 million active users, that will generate about 10 payments links each.
=> payment link entity is about: 256 bytes each
payment Id: 8bytes
payment method: 2 bytes
userId: 8 bytes
card issuer: 8 bytes
realm: 8 bytes
amount: decimal (8 bytes)
date: (12 bytes)
currency: 2 bytes
signing: 30 bytes
status: 10 bytes
-> 10 million transactions daily results in 2.5 million KB -> 2.5 TB daily
resulting 950 TB of data yearly.
-> 10 million of users data growing in 2 years -> 2TB of data
Aprox 2 Petabytes of data in 2 years.
->Post users: create a user account
{
username: "",
email: "",
date: "",
password: ""
} -> responds 200 OK with link of the resources created.
PUT /api/users to add the payments methods.
-auth header with JWT
{
paymentMethods: []
} -> responds with 200 OK, 401 if unauthorized
-> POST /api/payment
{
amount: decimal,
date: timestamp,
paymentMethod: string/enum.
currency: string/enum
realm: string,// to allow payments to be groupped (site name).
}
with auth header containing auth api key. and secret, only to be exposed in backend.
I can use PostgreSQL because of the strong consistency that is offers for the users management. For payments I will choose a database with built in sharding and scaling like DynamoDB. The partition key for this database will be account id, also the transaction logs involved in a payment will be stored in the database along with payments.
Gateway to authorize requests and build
LB - to load balance between multiple instances of the same service: users microservice
User microservice: to allow user managements and user account details
Payment microservice to generate payment links, and update status, coordinate transactions.
Validate Payment microservice: validate the authenticity of the
Payment transaction microservice.
Fraud detection analytics: all the payments links created are going to analytics database via CDC streaming built-in in DynamoDB
For the verification and creation of the links a cryptographic mechanism should be created to determine the authencity of the links. Private-public keys can be employed for this job, singing it with the public key and decrypt it with private. Shared secret can be used allowing only backend to backend communication
The tradeoff on using two for our system 1 for users PostgreSQL with offers strong consistency and one for payment and transaction logs which high volumes of data offering a boost of performance.
To scale the microservices Kubernetes can be used although the microservice architecture come with a lot of other challenges like distributed transactions (coordinate transactions).
A deduplication process need to be introduced for clients which may retry the payments.
The common use case is the failing of the databases but since I try to use managed instances of DynamoDB and PostgreSQL in RDS.
Other failure I see a lot happening is the browser of the payer closes before the payment finishes.
Multiple retry of the same payments.
A rate limit can be also configured so the microservices are protected.
Since we are sharding by user account Id the problem o having a hot shard microservice