Designing a Realtime Tracking Application for Arewaport
Tags: systemdesign, backenddevelopment
Published: 2023-07-29 10:42:24

## Problem Statement 

Arewaport is a hypothetical transportation company which has its headquarters in the northern part of Nigeria. Customers have been complaining of drivers taking detours during interstate travels. The management at Arewaport would like you to design and build an application that would enable them keep track of the location of their vehicle and drivers during travels. The system should also provide functionality that would allow users to book and make online payments for their journeys.

## Goals and Objectives

The goal of this post is to lay out my thought process as well as how I would go about designing and building the project. 

## Functional Requirement

- Management should be able to track the location of riders.
- Users should be able to books journeys. 
- Users should be able to make payments online.

## Non-Functional Requirements 

- The system should be scalable and efficient
- The system should have high availability 

## Choice of Frameworks, Tools and Technologies

- Backend framework: `Nestjs` : Due to its default typescript support and the fact that I enjoy working with it. 

- Mobile framework: `react-native` : I already know a little bit of react so using react-native seems like a natural progression. 

- Database: `Postgres`: Postgres because it's the default database I use for projects as well as the fact that it is highly extensible. Since the data is not highly relational, a Nosql database such as `Mongodb` would also work fine.

## Data Model Design

The following tables would be used to reflect our requirement 

- Driver: this would contain the information of the driver and would include fields such as `id`, `name`, `mobile_number`, `password`, `email`,`date_of_birth`, `created_at`.

- Vehicle: this would hold information of the vehicle being used by a driver during a journey and would hold fields such as `id`, `registratin_number`, `vehicle_model`, `date_bought`,

- User: this would hold user related information and would include fields such as `id`, `name`, `mobile_number`, `email`, `password`, `created_at`.

- Journey: this would hold information about each journey made by Arewaport drivers. It would also hold the current location of the driver/vehicle and would store information such as `id`, `vehicle_id`, `driver_id`, `status`, `start_point`, `destination`, `time_started`, `time_completed`, `passengers`, `current_location`.

- Payment: this table would hold payment related information such as `id`, `journey_id`, `amount`, `payer_id`, `payment_method`, `payer_name`.

## API Design

We would focus mainly on the most important endpoints.

- Register user: This endpoint would handle user registration.
```
registerUser(name: string, mobileNumber: string, email: string, password: string)
``` 

- Register driver: This endpoint would handle driver registration. Only admins would be allowed to register a driver. A Nestjs guard would be used to ensure only admins can access this endpoint.
```
registerDriver(name: string, mobileNumber: string, dateOfBirth: Date)
``` 

- Login drivers: this endpoint would be used to login drivers.
```
loginDriver(email: string, password: string)
```

- Login users: this endpoint would be used to login users.
```
loginUser(email: string, password: string)
```

- Start a journey: this endpoint would be used by users to signify that they have started a journey
```
startJourney(driverId: string, startPoint: string, destination: string, vehicleId: string, numberOfPassengers: number)
```

- End a journey: this endpoint would be used by drivers to signify the end of a journey
```
endJourney(driverId: string, journeyId: string)
```

- Book a journey: this endpoint would be used by users to make online bookings.
```
bookAJourney(userId: string, journeyId: string)
```

- Make a payment: this endpoint would provide the functionality to allow users to make payments online.
```
makePayment(userId: string, amount: decimal, journeyId: string)
```

## Driver Tracking 

Driver tracking would be implemented with the aid of a websocket connection between the client (rider's mobile phone) and the backend server. The client would be responsible for emitting events with a Payload containing its location and timestamps. The frequency of the events to be emitted would be configurable such that longer trips would have longer time in between while shorter trips would have shorter times. 

Due to the poor cell reception during transit, the Payloads to be sent to the server can be stored in a FIFO (First In First Out) queue which would be flushed to the server once there is cell reception 

The server would actively listen for the events and then query the database to save the details of the Payload accompanying the event once it is received.

## Architecture

I intend to use a monolithic architecture as opposed to microservice architecture. The major reason for this is that at this stage, I do not see the need for the added complexities that using a microservice architecture brings. I also believe that for now, the major scaling needs for the project would be vertical as opposed to horizontal. 

If for whatever reason there was need to change the architecture in the future, I would divide this system into the following core services:

- user service: this would handle operations regarding user authentication, authorization and information

- core service: this service would handle the core operations of the system and would responsible for booking journeys by users, keeping track of the riders location

- notification service: this service would be used to send push notifications as well as email notification to users and riders

- payment service: this service would handle payment related activities.

## Choice of Messaging System

If I were to shift to a microservice architecture sometimes in the future, Rabbitmq would be my messaging system of choice as opposed to kafka. This is mainly because I already have experience using Rabbitmq. The second reason for my choice would be the fact that rabbitmq is easier to setup and get working unlike kafka which is a little bit more complicated. The only reason I would pick Kafka over rabbitmq is if I needed to retain, reread or process and analyze messages sent to the different queues by the services.

This post was inspired by Karan Pratap Singh system design course. If you want to learn more about system design, {% embed https://dev.to/karanpratapsingh/system-design-the-complete-course-10fo %}