The application will be used by 1000 companies which own 10 000 employees.
Let's suppose that 5% of the employee of one company want to trade their shift.
Write path: 500 * 1000 -> 500 000 daily trades
The 50% users will check daily which are the employees which are working in shift. ->
5000 * 1000 requests daily -> 5 000 000, results in supposing that 1 day has approximately 100K seconds results in 50 req/s.
Storage estimation:
Swift swap record;
userIdinitiated -> 8bytes
managerAccepted -> 8 bytes
userAccepted -> 8 bytes
shiftIdFrom -> 8 bytes
shiftIdTo -> 8 bytes
dateTimeCreate -> 8 bytes
dateAccepted -> 8 bytes
we can estimate that 1 shift swap can take 128 bytes => 64 000 KB => 64 MB / day
2 years storage estimation will result in 2* 365 * 50MB = 800 * 64MB => 50 000 MB => 50GB.
Shift trades system looks similar with a bank transactions system, so a database with strong consistency should and can be employed. The natural fit for a database with ACID properties is PostgreSQL.
ApiGateway used to load balance the traffic and route the requests to specific service
Cache used to cache shift data and shift employees within a company.
SwapTradeService used to store requests of trades and accept of the requests by another employee
ShiftDetService will handle the get requests on the service
Admin Service will deal with accepting the trades which will determine the change of the shift by the employee.
get_shift_details -> the client will initiate the request which will reach the Api Gateway. The API Gateway will route the request to the ShiftDetService which will get the shift medata from cache, also will try to get the shift employees from cache. If the metadata is not found an query for the metadata is issued to the db using a technique called read through-cache.
accept_swift_trade -> will go from the client to the apiGateway and then to AdminService. This will update the status of the tradeRequest in accepted and will change the shift employees in Db, then we try to update the cache with the new change of the shift employees.
cancel_swift_trade -> the same path as accept_swift_trade but the only the status of the request changes.
register_trade -> will be use to register the request of the employee which is first initiating a trade request.
accept_trade -> will the user which accepts the trade.
ShiftDetService will be use to retrieve the employees participating to the shift. This service will benefit from precomputing the shift structure in the cache. In the database will keep the initial shift structure shift_id and employee_Id and use the trades table to store only the accepted shifts. One user/employee can change or be changed only a single time during 1 day. so will not have to implement a graph of changes.
In case one employee is participating in more than 1 trade, the first accepted trade will invalidate the other trade was interested to participate.
We can use a separate service that can compute shift structure but the action of the administrator to accept can determine to update the precomputing in the cache.
We choose an SQL database over a NoSQL database for its strict and strong consistency which is needed for a trading system.
Further grow of the system can involve scaling of the database using sharding or partitioning which in case of world wide companies can be made for company_id in composition with a region_id.
Retry mechanisms can used for accepting registering the trades and accepting the trades in a combination with idempondency
Imposing 1 change of the user per day in shift can result in some inconveniences many other trades needed to be canceled automatically.
Cache stampede can happen when multiple shifts expire in the same time
Implementing analytics over the trades and the performance of the teams that were having trades.
Implement reports to show statistics and analyse trends.