OmniEat: Distributed Food Delivery Platform
Project Overview
| Field | Value |
|---|---|
| Course | Advanced Microservices Architecture |
| Type | Microservices System |
| Duration | ~56 hours |
| Version | v1.0 |
| Total Points | 100.0 |
Learning Objectives
- Refactor monolithic Python code into decoupled microservices using FastAPI and Django
- Implement an API Gateway pattern with centralized authentication and security
- Design event-driven architectures using RabbitMQ for asynchronous inter-service communication
- Orchestrate distributed transactions using the Saga pattern to ensure data consistency
- Optimize system performance through caching strategies and database indexing
- Implement full-stack observability with distributed tracing, logging, and metrics
Prerequisites
- Proficiency in Python (Intermediate/Advanced)
- Basic knowledge of REST APIs and HTTP
- Familiarity with Docker and Docker Compose
- Understanding of SQL databases (PostgreSQL)
Project Description
In this course-long project, you will build 'OmniEat', a backend system for a food delivery application similar to UberEats or DoorDash. You will start with a legacy codebase and progressively evolve it into a robust, scalable microservices architecture. The system will handle user authentication, restaurant menu management, order processing, payment handling, and delivery notifications. By the end of the course, you will have a fully containerized ecosystem communicating via both synchronous APIs and asynchronous message queues, monitored by industry-standard observability tools.
Tasks
Task 1: Service Decomposition & Containerization
Unit: 1 - Unit 01: Fundamentals & Refactoring
Topics Covered: Monolith vs Microservices, Domain Driven Design (DDD), Docker & Docker Compose, Code Refactoring
Estimated Time: 6.0 hours
Description
You are provided with a messy 'Order Service' script that handles orders, payments, and notifications in a single file. Your task is to refactor this into a clean, modular structure and prepare the environment for microservices.
Requirements
- Refactor the provided legacy code into a clean 'Order Service' using FastAPI.
- Implement a proper folder structure (routers, schemas, models, services).
- Create a
docker-compose.ymlfile to spin up the Order Service and a PostgreSQL database. - Ensure the service can connect to the database and perform basic CRUD on orders.
Guidelines
- Analyze the provided
legacy_order.pyto identify distinct domains. - Separate Pydantic models (schemas) from SQLAlchemy models (ORM).
- Use environment variables for database credentials.
- Write a Dockerfile that uses a multi-stage build for a smaller image footprint.
Hints
- 💡 Don't worry about payments or notifications yet; just focus on creating and retrieving orders.
- 💡 Use
python-dotenvto manage configuration. - 💡 Ensure your Docker container exposes port 8000.
Deliverables
- Refactored Source Code
- Dockerfile
- docker-compose.yml
Bonus Features (Extra Credit)
- ⭐ Implement a Makefile for common commands (build, run, test)
Task 2: Gateway Implementation & Auth Service
Unit: 2 - Unit 02: API Gateway & Security
Topics Covered: API Gateway Pattern, JWT Authentication, Reverse Proxying, Rate Limiting
Estimated Time: 8.0 hours
Description
The system now needs a 'Restaurant Service' (Django) and a secure entry point. You will introduce an API Gateway and an Authentication Service to secure the platform.
Requirements
- Create a basic 'Restaurant Service' (can be simple CRUD) using Django or FastAPI.
- Implement a dedicated 'Identity Service' for user registration and login that issues JWTs.
- Set up an API Gateway (e.g., Nginx, Kong, or a custom Python Gateway) to route traffic to Order, Restaurant, and Identity services.
- Enforce JWT validation at the Gateway level or via middleware in each service.
Guidelines
- The Gateway should listen on port 8080 and proxy /orders, /restaurants, and /auth.
- Use a shared secret key or public/private key pair for JWT signing.
- Ensure the Order Service cannot be accessed directly from the host machine (expose ports only within the Docker network).
Hints
- 💡 If using Nginx as a gateway, look into
proxy_passdirectives. - 💡 FastAPI has excellent built-in security utilities for OAuth2 password flow.
Deliverables
- Identity Service Code
- Restaurant Service Code
- Gateway Configuration
- Updated docker-compose.yml
Bonus Features (Extra Credit)
- ⭐ Implement Rate Limiting on the Gateway
Dependencies: Complete Task(s) 1 first
Task 3: Event-Driven Notifications
Unit: 3 - Unit 03: Async Communication
Topics Covered: Message Queues (RabbitMQ/Kafka), Pub/Sub Pattern, Background Tasks, Event Consistency
Estimated Time: 6.0 hours
Description
Decouple the notification logic. When an order is created, the user should receive an email/SMS confirmation asynchronously without blocking the HTTP response.
Requirements
- Add RabbitMQ to the Docker Compose stack.
- Create a new 'Notification Service' that listens for messages.
- Modify the 'Order Service' to publish an
OrderCreatedevent to RabbitMQ upon successful order placement. - The Notification Service must consume this event and simulate sending an email (print to logs).
Guidelines
- Define a standard JSON structure for your events (e.g.,
event_type,payload,timestamp). - Use a library like
pikaorfaststreamfor RabbitMQ interaction. - Ensure the Notification Service can handle connection retries if RabbitMQ isn't ready immediately.
Hints
- 💡 Use a 'Direct' or 'Topic' exchange in RabbitMQ.
- 💡 The Order Service should return '201 Created' immediately after publishing the message, not wait for the email to be sent.
Deliverables
- Notification Service Code
- Updated Order Service with Publisher logic
Bonus Features (Extra Credit)
- ⭐ Implement a Dead Letter Queue (DLQ) for failed notifications
Dependencies: Complete Task(s) 1, 2 first
Task 4: Saga Pattern for Payments
Unit: 4 - Unit 04: Distributed Transactions
Topics Covered: Distributed Data Consistency, Saga Pattern (Choreography), Compensating Transactions, Idempotency
Estimated Time: 10.0 hours
Description
Introduce a 'Payment Service'. Implement a distributed transaction where an Order is only 'Confirmed' if the Payment succeeds. If Payment fails, the Order must be 'Cancelled'.
Requirements
- Create a 'Payment Service' that attempts to charge a mock card.
- Implement a Choreography Saga:
-
- Order Service creates order (Status: PENDING) -> Publishes
OrderCreated.
- Order Service creates order (Status: PENDING) -> Publishes
-
- Payment Service consumes
OrderCreated-> Processes Payment.
- Payment Service consumes
-
- Payment Service publishes
PaymentSuccessorPaymentFailed.
- Payment Service publishes
-
- Order Service consumes Payment events -> Updates status to CONFIRMED or CANCELLED.
Guidelines
- Simulate random payment failures (e.g., 20% chance of decline) to test the rollback logic.
- Ensure your message consumers are idempotent (processing the same message twice shouldn't corrupt data).
- Log every state change clearly.
Hints
- 💡 You will need multiple queues or routing keys:
orders.new,payments.success,payments.failed. - 💡 Keep the logic stateless where possible.
Deliverables
- Payment Service Code
- Saga Implementation Logic
- Log files demonstrating success and failure flows
Bonus Features (Extra Credit)
- ⭐ Implement an Orchestrator service instead of Choreography
Dependencies: Complete Task(s) 1, 2, 3 first
Task 5: Caching & Query Optimization
Unit: 5 - Unit 05: Performance
Topics Covered: Redis Caching, Cache Invalidation, Database Indexing, N+1 Query Problem
Estimated Time: 5.0 hours
Description
The Restaurant Service is experiencing high read traffic for menus. Optimize the system using Redis caching and SQL tuning.
Requirements
- Add Redis to the Docker stack.
- Implement caching for the 'Get Menu' endpoint in the Restaurant Service.
- Implement 'Cache Aside' pattern: Check cache -> If miss, DB -> Write to cache.
- Ensure cache invalidation/update happens when a restaurant owner updates their menu.
- Analyze Order Service queries and add necessary DB indexes (e.g., on
user_idorstatus).
Guidelines
- Set a reasonable TTL (Time To Live) for the cache keys.
- Use a tool like
EXPLAIN ANALYZE(Postgres) to verify index usage. - Use
redis-pyoraioredisfor implementation.
Hints
- 💡 Cache keys should be unique, e.g.,
menu:{restaurant_id}. - 💡 Be careful of race conditions when invalidating cache.
Deliverables
- Redis integration code
- SQL migration script for indexes
- Performance comparison (Before vs After response times)
Bonus Features (Extra Credit)
- ⭐ Implement response compression (Gzip/Brotli)
Dependencies: Complete Task(s) 2, 4 first
Task 6: Distributed Tracing & Metrics
Unit: 6 - Unit 06: Observability
Topics Covered: OpenTelemetry, Jaeger/Zipkin, Prometheus & Grafana, Structured Logging
Estimated Time: 8.0 hours
Description
It is becoming difficult to track requests across 4+ services. Implement distributed tracing to visualize the full request lifecycle.
Requirements
- Integrate OpenTelemetry (OTel) into all services (Order, Payment, Restaurant, Notification).
- Add a Jaeger (or Zipkin) container to visualize traces.
- Ensure the
TraceIDis propagated across HTTP headers and RabbitMQ messages. - Expose a
/metricsendpoint in the Order Service for Prometheus scraping (request count, latency).
Guidelines
- Use the auto-instrumentation libraries for FastAPI/Django where possible, but add manual spans for critical logic (e.g., 'Processing Payment').
- Configure Docker Compose to network the telemetry collector correctly.
Hints
- 💡 Propagating context over RabbitMQ requires extracting headers from the message properties and injecting them into the new context.
- 💡 Check
opentelemetry-instrumentation-fastapi.
Deliverables
- OTel configuration code
- Screenshot of a full trace in Jaeger (Order -> Payment -> Notification)
- Screenshot of Grafana dashboard
Bonus Features (Extra Credit)
- ⭐ Set up an alert in Grafana for high error rates
Dependencies: Complete Task(s) 1, 2, 3, 4, 5, 6 first
Task 7: Integration Testing & Chaos
Unit: 7 - Unit 07: E2E Review & Debug
Topics Covered: End-to-End Testing, TestContainers, Chaos Engineering, Debugging
Estimated Time: 6.0 hours
Description
Verify the system's reliability. Write an automated E2E test suite and simulate a service failure to see how the system behaves.
Requirements
- Create a separate 'Tests' folder/container.
- Write a Python script (using
pytestorrequests) that simulates a full user flow: Login -> Get Menu -> Place Order -> Verify Notification. - Perform a manual 'Chaos Test': Stop the Payment Service container while placing an order, restart it, and verify how the system recovers (or fails gracefully).
Guidelines
- The E2E tests should run against the Dockerized environment.
- Document the behavior during the Chaos Test in a markdown file.
Hints
- 💡 Use
pytest-dockeror simply run tests externally againstlocalhostports. - 💡 Expect 500 errors or timeouts during the Chaos test; the goal is to ensure the data doesn't get corrupted.
Deliverables
- E2E Test Suite
- Chaos Test Report (Markdown)
Bonus Features (Extra Credit)
- ⭐ Automate the Chaos test using a script
Dependencies: Complete Task(s) 1, 2, 3, 4, 5, 6, 7 first
Task 8: Final System Defense
Unit: 8 - Unit 08: Final Exam
Topics Covered: System Architecture Review, Deployment Readiness, Code Quality, Documentation
Estimated Time: 4.0 hours
Description
Prepare the OmniEat platform for final submission. This involves finalizing documentation, cleaning up code, and preparing a presentation of the architecture.
Requirements
- Complete the
README.mdwith setup instructions, architecture diagrams, and API documentation (Swagger links). - Ensure all
TODOcomments are resolved or documented as future technical debt. - Verify that
docker-compose upworks on a fresh machine without manual intervention. - Prepare a 5-minute video walkthrough or slide deck explaining your Saga implementation and Observability setup.
Guidelines
- Diagrams can be generated using tools like Mermaid.js or drawn manually.
- Ensure environment variables are provided in a
.env.examplefile.
Hints
- 💡 Double-check your port mappings.
- 💡 Review your code against PEP8 standards.
Deliverables
- Final Source Code
- Comprehensive README
- Architecture Diagram
- Presentation Video/Slides
Bonus Features (Extra Credit)
- ⭐ Deploy to a cloud provider (AWS/GCP) free tier
Dependencies: Complete Task(s) 1, 2, 3, 4, 5, 6, 7 first
Task 9: Post-Audit Refinement
Unit: 9 - Unit 09: Audit
Topics Covered: Code Review, Refactoring, Security Auditing, Best Practices
Estimated Time: 3.0 hours
Description
Based on the feedback received during the Final Exam/Review, address critical issues and perform a self-audit on security vulnerabilities.
Requirements
- Run a security linter (like
bandit) against your code and fix High/Medium severity issues. - Refactor one module based on instructor feedback (e.g., simplify a complex function, improve variable naming).
- Submit a 'Change Log' document detailing what was fixed after the initial submission.
Guidelines
- Focus on code maintainability and security best practices.
- If no critical bugs were found, focus on optimizing Docker image sizes.
Hints
- 💡 Use
pip install bandit. - 💡 Look for hardcoded secrets which are a common audit failure.
Deliverables
- Patched Source Code
- Bandit Security Report
- Change Log
Dependencies: Complete Task(s) 8 first
Submission Guidelines
- All code must be pushed to a private GitHub repository.
- The repository must contain a
docker-compose.ymlat the root. - Each unit's work should ideally be in a separate branch or tagged commit (e.g.,
unit-1-complete), but themainbranch must represent the final state. - Video presentations must be accessible via a shared link (Google Drive/Loom).
Grading Rubric
| Criterion | Weight | Excellent (90-100%) | Good (75-89%) | Satisfactory (60-74%) | Needs Improvement (<60%) |
|---|---|---|---|---|---|
| Functionality & Architecture | 30.0% | All microservices communicate correctly; Saga pattern handles rollbacks flawlessly; Gateway routes all traffic securely. | Core flow works, but edge cases (like payment failure) might be buggy; Gateway works but config is messy. | Basic happy path works, but async communication or distributed transactions are unstable. | System fails to start or services cannot communicate. |
| Code Quality & Standards | 20.0% | PEP8 compliant, clear separation of concerns, excellent naming conventions, modular folder structure. | Mostly clean code, some minor linting issues or mixed logic in controllers. | Functional but messy; large functions, poor variable names, logic leaks between layers. | Spaghetti code, hard to read or maintain. |
| Testing & Reliability | 20.0% | Comprehensive E2E tests, Chaos test analysis is deep, unit tests present for core logic. | Basic E2E happy path test included; Chaos test performed but analysis is shallow. | Manual testing only, or tests are provided but do not run. | No testing evidence provided. |
| Observability & DevOps | 15.0% | Full tracing implemented, logs are structured, Docker Compose is optimized and reliable. | Tracing works but has gaps; Docker works but images are large. | Basic logging only; Docker setup requires manual tweaks to run. | No observability; application runs on bare metal only. |
| Documentation & Presentation | 15.0% | Professional README, clear architecture diagrams, articulate video presentation. | Good README, basic diagrams, presentation covers main points. | Minimal README, missing diagrams, or unclear presentation. | Documentation missing or unintelligible. |