CampusG - Food Delivery Platform for Schools

Backend
Frontend
Cloud
React
Flask
Kafka
Temporal
PostgreSQL
Docker
AWS
Web Application
Solution Architecture
CampusG - Food Delivery Platform for Schools

Project grade received: "A+"

Overview

Developed as part of our Enterprise Solution Development (ESD/IS213) module, CampusG is a microservices-based application that hosts a campus food delivery service.

Our platform connects customers placing orders with runners who deliver them.

Demo:

Landing Page & Sign-in Flow

CampusG landing page & signin

Role-Selector (Image)

We colour coded the roles to be blue for placing orders, and green for delivering orders.

CampusG landing page & signin

Placing an Order:

After adding the order details, the place order button will trigger the "Create Order Saga". It sends off the work to the backend, and returns a HTTP 202 Code (Accepted). The user is loaded to the order history page to view the order details at a glance.

CampusG placing an order demonstration

Accepting an Order & Receiving Status Updates:

Via the green profile (runner), accepting an order via the available orders page will allow the runner to fulfil the order, and provide updates on the status of the order. The accept order button on the initial frame triggers the "Accept Order Saga".

CampusG accepting an order demonstration

Completing an Order:

After going through all the required status updates, the runner can confirm the delivery of the item, triggering the "Complete Order Saga".

CampusG completing an order demonstration

User's Dashboard (Image):

Users can see their expenditure and their earnings, as well as make profile adjustments. Here, users can also add their payment method.

CampusG user dashboard

Technical Breakdown

System Architecture & Tech Stack

The following table summarizes the core components of CampusG, the technologies used, and their respective roles within the system:

ComponentTechnology / ToolRole / Description
FrontendReact + Vite (Bolt.new)User interface for customers and runners
User ServiceFlask, Clerk Auth, Stripe APIProfile management, authentication, and payment integration
Order ServiceFlaskManages order lifecycle and states
Payment ServiceFlask, Stripe APIHandles payment processing and fund transfers
Notification ServiceKafka, GrafanaEvent logging and monitoring
Timer ServiceOutsystems (REST API)Manages order timeouts and cancellations
Message BrokerKafkaEvent-driven communication between microservices
Workflow OrchestratorTemporalOrchestrates Accept/Complete Order sagas
DatabasePostgreSQL (per microservice)Persistent storage for each microservice
ContainerizationDockerService isolation and deployment
External ServicesClerk, Stripe, OutsystemsAuthentication, payments, and timer management

Saga Orchestrators


1. Create Order Saga (Flask/Kafka)

Coordinates the order creation flow through Kafka events, interfacing with Order, User, and Payment services, and communicating with the Timer Service via HTTP. Handles compensation actions for failures.

StepAction
1Customer places order
2Saga coordinates order creation
3Retrieves user payment info
4Authorizes payment via Stripe
5Updates order status
6Starts timer (Outsystems)
7Handles failures with compensation (e.g., cancels order if payment fails)
CampusG Create Order Saga microservice interaction diagram

2. Accept Order Saga (Temporal)

Manages the runner order acceptance workflow using Temporal activities to update the Order Service and Timer Service, with compensation logic for failures.

StepAction
1Runner accepts order
2Saga updates order status (assigns runner)
3Notifies Timer Service (Outsystems)
4Handles failures with compensation (e.g., reverts order status)
CampusG Accept Order Saga microservice interaction diagram
CampusG Accept Order Saga temporal workflow execution

3. Complete Order Saga (Temporal)

Orchestrates order completion and payment flows, coordinating between Order, User, and Payment services, and managing fund release to runners via Stripe. Handles failure scenarios with compensation actions.

StepAction
1Runner marks order as completed
2Saga updates order status
3Retrieves runner payment info
4Retrieves payment ID
5Releases funds (Stripe payout)
6Updates final order status
7Handles failures with compensation (e.g., reverts payout/status)
CampusG Complete Order Saga microservices interaction diagram & temporal workflow execution

4. Order Timeout Process

Handles automatic order expiration and cancellation if not accepted within a set time frame.

StepAction
1Timer Service polls every 5 minutes to check if 30 minutes have passed since order creation.
2If expired, marks the order as expired.
3Create Order Saga polls every 1 minute for expired orders.
4If found, initiates order cancellation via Kafka.
5Order Service processes cancellation and confirms via Kafka event.
CampusG Create Order Saga timer execution diagram

Why Saga?

While planning the project, we discovered a post from AWS on the Saga Orchestration Pattern.

AWS Saga Orchestration Step Functions Diagram

Link to diagram from the AWS documentation

In fact, this diagram that closely resembled the steps our services would need to go through, as it involved an ordering process where issues could occur across multiple services with various data states to manage.

Additionally, as most of the team lacked Java experience, we sought Python-based tools to assist with this implementation. We initially used a Pub-Sub system with Kafka to implement one of our Sagas (orchestration via Saga but with choreography-style execution). Later, we discovered a orchestration tool called Temporal and implemented two additional Sagas with it, more closely resembling the AWS Step Functions diagram.

We opted against AWS Step Functions as we were building our solution to run locally, and developing a fully cloud-hosted solution seemed daunting at that point.

The Saga pattern helped us manage complex distributed transactions like order creation, acceptance, and completion/payment. Without it, we would have needed to account for numerous edge cases and engineer multiple flows to handle all types of errors.

Further Improvements

To further enhance our project, several real-world development considerations could be incorporated. For example, introducing an API gateway for our APIs and microservices would provide a unified entry point, enabling advanced features such as rate limiting, API versioning, and secure, permission-based access control.

Implementing an API gateway would have deepened our understanding of these core concepts. While we explored the fundamental capabilities of API gateways in class, integrating one into our project was considered Beyond-the-Lab (BTL) and thus not included in the initial scope.

Additionally, deploying the application to the cloud would enable a live demonstration accessible to all users. This would require further expertise in cloud deployment of microservices, as well as integration with cloud-based message brokers and saga orchestrators.