Photo by Marek Piwnicki on Unsplash
Problem Statement
Consider that you have to build a checkout system. The microservice should have the following functionalities
- API to create an empty cart and associate it with a user
- API to add items to the cart
- API to delete items from the cart
- API to empty the cart
Part 1 - Based on the requirements given, write down functional requirements for the service. Take assumptions and write down non-functional requirements for the service
Part 2 - Break down decisions that have to be taken to build this service. Divide them into high cost and low-cost decisions
Part 3 - Use domain-driven design and relating to real-world domains to document how would a user interact with the service. Document what additional conditions happen in the real world that is not given as part of the requirements.
Part 4 - Write down what business metrics and system metrics should be generated by the system
Solution
The Cart service will be a RESTful service and our consumers should be able to access the service via the following APIs. There are some assumptions that we make while creating the design for this microservice.
Part 1 - Based on the requirements given, write down functional requirements for the service. Take assumptions and write down non-functional requirements for the service
Assumptions:
-
There will also be a few entities like a
User
that we will be using during the course of designing this microservice. We are assuming that these entities exist and they will also be available via an API. -
The Cart microservice should be a part of a bigger Checkout system which will include the Cart microservice communicating in tandem with the Payments microservice. Certain assumptions will be made about the Payments microservice.
-
We are assuming the existence of another service, namely the Coupon microservice which will interact with the Cart microservice to tally and calculate the total price and the discount amount. We assume that the Coupon microservice is functional for the case of this exercise.
TLDR;
Assume the existence of the following entities:
- User - Has a
userId
attribute - Cart - Consists of CartItems and is associated to a user
Assume that the following microservices are functional:
- Coupons Microservice - To check the validity of coupons
- Payments Microservice - To make online payments
Functional requirements for the Cart Service:
- API - Given a user, create an empty cart and associate it with a user
- API - Given a user, add an item to a cart
- API - Given a user, delete the item from the cart, if it exists in the cart
- API - Empty the cart
- Entity - User - We assume the entity exists and there's a unique id
userId
associated with a user - Entity - CartItem - A representation of the item when inside a cart. Will have a unique item id called
itemId
and aquantity
. - API - Given a cart, fetch the total amount of the items in the cart
- API - Given a cart, apply a coupon from the user
Non-Functional requirements
- Logging
- Load Balancer/Proxy
- API Protocol
- Tracing library
Part 2 - Break down decisions that have to be taken to build this service. Divide them into high cost and low-cost decisions
The decisions to be taken for the above functional and non-functional requirements are grouped below:
Low Cost Decisions:
- Logging Library
- Tracing Library
- Caching - Perhaps not needed for the given API
High Cost Decisions
- Load Balancer
- API Protocol
- Logging Infrastructure
Part 3 - Use domain-driven design and relating to real-world domains to document how would a user interact with the service. Document what additional conditions happen in the real world that is not given as part of the requirements.
Real-life physical carts have wheels, but we don't need them here. However, we do need the capability for the cart to hold items, the functionality to add and remove items and reflect the total cost of the items in the cart.
Following are the API interactions that a user would do with this cart:
- Get a cart for a particular user
If a cart exists, then it's data representation can be fetched for a user. If a cart does not exist for a user, then we can create a cart object and send it off.
- Add an item
Given a cart, the user should be able to add an item and the quantity to the cart.
- Remove an item
Given a cart with some item, the user should be able to remove that item from the cart either completely or by decreasing the quantity of that item. Modelling against the real world, when the user removes the item completely from the cart by decreasing it's quantity to zero, then the item should be removed completely from the object representation of the cart.
- Empty the cart
The user can abandon a full shopping cart in the store in the physical world, similarly we give the user an option to "abandon" the cart by giving them the option to empty the cart. We remove all items from the representation of the cart.
Part 4 - Write down what business metrics and system metrics should be generated by the system
We care about the following system metrics:
- Performance & Latency of each API
- Disk usage and latency caused by logging systems
- CPU, Memory, Disk space of the server
- Error and success rates of each API
- Resource usage
- Processes
For business metrics, these are the line items:
- Analytics of the items, which items are often added to a cart and which are removed.
- How many times the Empty cart functionality is used.
- How many times a user goes into the checkout flow from the cart.