TL;DR
For my Service-Oriented Architecture course, I built a food delivery platform where customers, restaurants and delivery personnel each have their own module. Instead of one tightly coupled application, the modules communicate through RESTful APIs built with PHP and MySQL, with a responsive Bootstrap front end.
Food delivery is a good example of a system with many moving parts. A single order involves a customer placing it, a restaurant preparing it and a rider delivering it, and each of them needs up-to-date information at every step.
This made it a natural fit for my Service-Oriented Architecture (SOA) course project. In this post I explain the architecture, how the three user modules talk to each other, and what I learned about designing APIs.
01 What Is Service-Oriented Architecture?
In a traditional monolithic application, every feature lives in one codebase and shares everything directly. SOA takes a different approach: the system is split into services, each responsible for one part of the business, and services communicate through well-defined interfaces.
- Loose coupling: a service can change internally without breaking the others, as long as its interface stays the same.
- Reusability: the same service (for example, order management) can be used by the customer, restaurant and rider interfaces.
- Clear responsibilities: each service has one job, which makes the system easier to understand and test.
In this project, those interfaces are RESTful web services: standard HTTP requests (GET, POST, PUT, DELETE) that exchange data in JSON.
02 System Architecture
The platform is organised around three user modules that share a common set of services and a MySQL database:
- Browse restaurants & menus
- Place orders
- Track order status
- Manage menu items
- Accept & prepare orders
- Update order status
- View assigned orders
- Pick up & deliver
- Mark as delivered
All three modules use the same REST API to read and update data, so there is a single source of truth for every order. The front end is built with HTML, CSS and Bootstrap, and the whole system was developed and tested locally with XAMPP.
03 How the Modules Communicate
The heart of the system is the order lifecycle. Each step is triggered by one module and becomes visible to the others through the API:
- 1. Customer places an order: the customer interface sends a POST request to create the order.
- 2. Restaurant accepts it: the restaurant interface retrieves new orders and updates the status as it prepares the food.
- 3. Rider picks it up: the delivery interface sees orders that are ready and updates the status during delivery.
- 4. Customer tracks it: the customer interface reads the latest status at each stage.
Here is a simplified example of what an endpoint for updating an order's status can look like in PHP:
<?php
header('Content-Type: application/json');
require 'db.php';
$data = json_decode(file_get_contents('php://input'), true);
$allowed = ['accepted', 'preparing', 'ready', 'on_the_way', 'delivered'];
if (!in_array($data['status'], $allowed)) {
http_response_code(400);
echo json_encode(['error' => 'Invalid status']);
exit;
}
$stmt = $conn->prepare('UPDATE orders SET status = ? WHERE order_id = ?');
$stmt->bind_param('si', $data['status'], $data['order_id']);
$stmt->execute();
echo json_encode(['success' => true]);
04 Designing the API
Building the APIs taught me that the interface matters as much as the code behind it. A few principles guided my design:
- Resource-based endpoints: URLs describe things (orders, menus, restaurants) and HTTP methods describe actions.
- Consistent JSON responses: every response follows the same structure, so the front end handles success and errors the same way.
- Meaningful status codes: 200 for success, 400 for invalid input, 404 when something is not found.
- Validation on the server: the API checks every input instead of trusting the front end.
Key insight
Once the API was defined, the three interfaces could be developed independently. As long as everyone followed the same request and response format, changes in one module did not break the others.
05 Key Lessons & Takeaways
Design the interface first
Agreeing on endpoints and data formats before writing code saved time and made integration much smoother.
Think in workflows, not pages
Mapping the full order lifecycle helped me see which module needed which data at each step.
Never trust the client
Validating input and using prepared statements on the server keeps the data consistent and safe.
Responsive design matters
Riders and customers often use phones, so a responsive Bootstrap interface was essential.
What's Next?
This project changed how I think about building systems: as services with clear contracts instead of one big application. If you'd like to talk about it, feel free to reach out.
Get In Touch