DEV Community

Alahira Jeffrey Calvin
Alahira Jeffrey Calvin

Posted on • Edited on

Designing a Realtime Tracking Application for Arewaport

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)
Enter fullscreen mode Exit fullscreen mode
  • 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)
Enter fullscreen mode Exit fullscreen mode
  • Login drivers: this endpoint would be used to login drivers.
loginDriver(email: string, password: string)
Enter fullscreen mode Exit fullscreen mode
  • Login users: this endpoint would be used to login users.
loginUser(email: string, password: string)
Enter fullscreen mode Exit fullscreen mode
  • 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)
Enter fullscreen mode Exit fullscreen mode
  • End a journey: this endpoint would be used by drivers to signify the end of a journey
endJourney(driverId: string, journeyId: string)
Enter fullscreen mode Exit fullscreen mode
  • Book a journey: this endpoint would be used by users to make online bookings.
bookAJourney(userId: string, journeyId: string)
Enter fullscreen mode Exit fullscreen mode
  • Make a payment: this endpoint would provide the functionality to allow users to make payments online.
makePayment(userId: string, amount: decimal, journeyId: string)
Enter fullscreen mode Exit fullscreen mode

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,

Top comments (0)