The key components of the system are:
- Frontend: The web and mobile applications that users interact with to select and navigate routes.
- Backend API: The API that provides the predefined routes to the frontend and stores completed routes for users.
- User service: The service that handles user operations. Such as following and viewing other users and modifying user profiles
- Route service: The service that handles route operations. Such as creating, updating, and deleting routes.
- Real-time location tracking service: The service that tracks the position of other users navigating the same route in real-time.
- Database: The database that stores user profiles, completed routes, and notes.
The system architecture is a typical client-server architecture, where the frontend and backend communicate via a RESTful API. The real-time location tracking service is integrated into the backend API, which communicates with the frontend via websockets. User and routes have their own services, which communicate with the database via an ORM.
@startuml
actor User
participant "Web Application" as web
participant "Mobile Application" as mobile
participant API
participant "User Service" as user
participant "Route Service" as route
participant "Real-time Location Tracking Service" as location
participant Database
User -> web: Uses
User -> mobile: Uses
web -> API: Sends request
mobile -> API: Sends request
API -> user: Sends request
user -> Database: Reads/Writes data
API -> route: Sends request
route -> Database: Reads/Writes data
API -> location: Sends request
location -> Database: Reads/Writes data
@enduml
The pros of this design are:
- Separation of concerns: The frontend and backend are decoupled, which allows for easier maintenance and scalability.
- Real-time updates: The use of websockets allows for real-time updates of the position of other users on the same route.
- Scalability: The use of a RESTful API and websockets allows for horizontal scaling of the backend API.
The cons of this design are:
- Complexity: The use of websockets and real-time location tracking adds complexity to the system.
- Increased latency: The use of websockets can increase latency compared to a traditional RESTful API.
- Single Database: The use of a single database can lead to performance issues and data consistency problems. To improve performance and data consistency, the system could use a separate database for each service. Nosql or sql database types can be used for each service.
Completed routes for users can be stored in a relational database such as MySQL or PostgreSQL. The tradeoffs between different solutions include:
- Relational databases: These are well-suited for storing structured data such as completed routes, and provide features such as transactions and referential integrity. However, they can be less scalable than other solutions.
- NoSQL databases: These are well-suited for storing unstructured data such as routes (route has path which has unstructured data), and can be more scalable than relational databases. However, they may not provide the same level of data consistency and referential integrity.
To interact with the storage layer, the backend services can use an ORM such as Sequelize or TypeORM to abstract away the database-specific details and provide a more convenient interface for interacting with the data.
Here's a basic data model for routes and the link between users and the routes they completed:
User
- id (primary key)
- name
- email
- password
Route
- id (primary key)
- name
- description
- distance
- duration
- path (array of map points)
CompletedRoute
- id (primary key)
- userId (foreign key)
- routeId (foreign key)
- note
- completedAt
Referring to the system architecture diagram, the part of the system that deals with showing other Relivers on the route works as follows:
- The frontend sends a request to the backend API to start tracking the user's location on the route.
- The backend API starts tracking the user's location and sends updates to the real-time location tracking service.
- The real-time location tracking service broadcasts the user's location to all other users on the same route via websockets.
- The frontend receives the location updates and displays the position of other users on the route in real-time.
If the new app is a huge hit, the system design would need to be scaled horizontally to handle the increased load. Here are some changes that could be made to improve scalability:
- Use a load balancer to distribute incoming requests across multiple instances of the backend API.
- Use a caching layer such as Redis to cache frequently accessed data and reduce the load on the database.
- Use a NoSQL database such as MongoDB to improve scalability and performance.
- Use a message queue such as RabbitMQ to handle asynchronous tasks and improve scalability.
- Use a CDN such as Cloudflare to cache static assets and improve performance.
- Use distributed file storage such as Amazon S3 to store user-uploaded files and improve scalability.
- Use a container orchestration tool such as Kubernetes to manage the deployment and scaling of the system.
- Use a serverless architecture such as AWS Lambda to improve scalability.
- Use a service mesh such as Istio to improve observability and reliability.
- Use different databases to read and write data. Apply the CQRS pattern.
By making these changes, the system would be able to handle a larger number of users and requests while maintaining performance and reliability.