System requirements


Functional:

  1. A start payment service that communicates with a third party company to start the process of getting the payment transaction id.
  2. A post payment service that communicates with a third party company to post the payment.
  3. A Receipt service that is Cached and used for read only purposes in case the user only wants to read their receipt.
  4. A NONSQL database to store the payment information while we wait for the client to complete the charge.
  5. A Message Queue to ensure atomicity, and isolation.
  6. 1 Write DB and 2 read DB's to ensure durability.



Non-Functional:

  1. A monitoring service to ensure durability and consistency. We will include a heartbeat service and log metrics in case a failure happens.
  2. An Elastic Application Load Balancer to manage load. This will scale up and down if needed.





Capacity estimation


  1. 1000 Reads a second.
  2. 10 writes a second
  3. 1000 * 60 = 60000 + 10 * 60 = 60060 transactions a minute. Each transaction is around 1 MB = 60GB a minutue * 60 = 3600GB an hour * 24 = 8 TB a day




API design

Define what APIs are expected from the system...


  • https://startPayment

{

user_id: unique id,

email_id: unique email,

timestamp: time it's been requested,

payment_type: credit/debit

}

  • https://postPayment

{

user_id: unique id,

email_id: unique email,

timestamp: time it's been requested,

payment_type: credit/debit,

transaction_id: unique transaction_id

}

  • https://getReceipt

{

user_id: unique id,

email_id: unique email,

timestamp: time it's been requested,

payment_type: credit/debit,

receipt_id: unique receipt id

}




Database design

Defining the system data model early on will clarify how data will flow among different components of the system. Also you could draw an ER diagram using the diagramming tool to enhance your design...


User Table

  • user_id
  • email_id
  • index: user_id

Payment Table

  • user_id
  • timestamp
  • type
  • transaction_id
  • index: user_id
  • amount: string

Receipt Table

  • user_id
  • receipt_id
  • timestamp
  • index: user_id


High-level design

You should identify enough components that are needed to solve the actual problem from end to end. Also remember to draw a block diagram using the diagramming tool to augment your design. If you are unfamiliar with the tool, you can simply describe your design to the chat bot and ask it to generate a starter diagram for you to modify...







Request flows

Explain how the request flows from end to end in your high level design. Also you could draw a sequence diagram using the diagramming tool to enhance your explanation...


  1. The client starts the payment process by making a https post request to the startPayment end point. This includes the user_id, email_id, timestamp, and the payment type.
  2. The request goes through the Load balancer. This will ensure the correct request reaches the correct services. This also sets us up to add more servers if needed. This is an Application load balancer since it managers http and https requests.
  3. The request then goes into the Message Queue. Since we're communicating with the Write database, the message queue helps us isolate the current transaction from other transactions, there by enforcing isolation.
  4. The message queue communicates with the payment service from paypal or stripe and retreives a payment token for the current session. The payment service sends back the token to the message queue and then the message is sent to the NOSQL write database. We store all necessary data in the write database. The NOSQL write database sends the replicated data to the Read databases.
  5. Finally the information is sent back to the client.
  6. The user fills in the necessarry payment information and then posts the payment through the postPayment API. The postPayment aPI sends over: user_id, timestamp, payment type, transaction_id, and payment amount.
  7. The request goes through the Load balancer.
  8. The load balancer sends the request to the Post Payment service.
  9. The Post Payment service sends the data to the message queue
  10. the message queue sends the request to paypal/stripe. Paypal/stripe sends the request back to the Queue, which sends it to the Write DB. The write DB sends it to the receipt service and the cache. The receipt service sends it back to the client


Detailed component design

Dig deeper into 2-3 components and explain in detail how they work. For example, how well does each component scale? Any relevant algorithm or data structure you like to use for a component? Also you could draw a diagram using the diagramming tool to enhance your design...


Databases

  • The Database uses a NOSQL key/value store. we use NOSQL since there isn't many relationships we need to manage and because it's highly scalable and highly performant. Since we don't have to join databases, the NOSQL database is usually faster than SQL datbases.
  • The Write database and the read databases are replicas of one another. The write database is the leader and the read databases are the followers. If the write datbase goes down one of the read database gets promoted to leader.
  • We're okay with eventual consistency.


Monitoring Services

  • this service connecs to all parts of our architecture
  • A heartbeat service is used to send messages between all components
  • The message includes unique information specific to the component its getting information from. Such as running processes from the post payment service or the databases, memory consumption, and client workstation specific data.
  • This service allows us to to be highly reliable by being able to help us fix issues before they occur
  • The monitoring service collects logs to help diagnose and fix issues that can be very hard to fix...such as concurrency issues or random network issues.





Trade offs/Tech choices

Explain any trade offs you have made and why you made certain tech choices...

We're not sharding the databases because our user base is not yet large enough to justify the extra cost. We instead replicate since it's less complicated and very stable and with the lower usage rate it's still highly efficient.


We only have one write DB for simplicity reasons. Once you have more than one DB consistency starts to be an issue. Having one DB is highliy consistent and less error prone and given our user base size it's justified for now


Failure scenarios/bottlenecks

Try to discuss as many failure scenarios/bottlenecks as possible.


We only have one message queue. We should have more


We only have single components in many places, we should add more.


Databases are not shareded so if we keep growing at a high usuage rate we'll eventually run into an issue with scailability.




Future improvements

What are some future improvements you would make? How would you mitigate the failure scenario(s) you described above?


having more than one queue would resolve not having as many queues.


Sharding databases will resolve our scailability issue with databases.