Skip to main content

OmniEat: Distributed Food Delivery Platform

Project Overview

FieldValue
CourseAdvanced Microservices Architecture
TypeMicroservices System
Duration~56 hours
Versionv1.0
Total Points100.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.yml file 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

  1. Analyze the provided legacy_order.py to identify distinct domains.
  2. Separate Pydantic models (schemas) from SQLAlchemy models (ORM).
  3. Use environment variables for database credentials.
  4. 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-dotenv to 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

  1. The Gateway should listen on port 8080 and proxy /orders, /restaurants, and /auth.
  2. Use a shared secret key or public/private key pair for JWT signing.
  3. 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_pass directives.
  • 💡 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 OrderCreated event to RabbitMQ upon successful order placement.
  • The Notification Service must consume this event and simulate sending an email (print to logs).

Guidelines

  1. Define a standard JSON structure for your events (e.g., event_type, payload, timestamp).
  2. Use a library like pika or faststream for RabbitMQ interaction.
  3. 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:
    1. Order Service creates order (Status: PENDING) -> Publishes OrderCreated.
    1. Payment Service consumes OrderCreated -> Processes Payment.
    1. Payment Service publishes PaymentSuccess or PaymentFailed.
    1. Order Service consumes Payment events -> Updates status to CONFIRMED or CANCELLED.

Guidelines

  1. Simulate random payment failures (e.g., 20% chance of decline) to test the rollback logic.
  2. Ensure your message consumers are idempotent (processing the same message twice shouldn't corrupt data).
  3. 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_id or status).

Guidelines

  1. Set a reasonable TTL (Time To Live) for the cache keys.
  2. Use a tool like EXPLAIN ANALYZE (Postgres) to verify index usage.
  3. Use redis-py or aioredis for 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 TraceID is propagated across HTTP headers and RabbitMQ messages.
  • Expose a /metrics endpoint in the Order Service for Prometheus scraping (request count, latency).

Guidelines

  1. Use the auto-instrumentation libraries for FastAPI/Django where possible, but add manual spans for critical logic (e.g., 'Processing Payment').
  2. 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 pytest or requests) 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

  1. The E2E tests should run against the Dockerized environment.
  2. Document the behavior during the Chaos Test in a markdown file.

Hints

  • 💡 Use pytest-docker or simply run tests externally against localhost ports.
  • 💡 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.md with setup instructions, architecture diagrams, and API documentation (Swagger links).
  • Ensure all TODO comments are resolved or documented as future technical debt.
  • Verify that docker-compose up works on a fresh machine without manual intervention.
  • Prepare a 5-minute video walkthrough or slide deck explaining your Saga implementation and Observability setup.

Guidelines

  1. Diagrams can be generated using tools like Mermaid.js or drawn manually.
  2. Ensure environment variables are provided in a .env.example file.

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

  1. Focus on code maintainability and security best practices.
  2. 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.yml at the root.
  • Each unit's work should ideally be in a separate branch or tagged commit (e.g., unit-1-complete), but the main branch must represent the final state.
  • Video presentations must be accessible via a shared link (Google Drive/Loom).

Grading Rubric

CriterionWeightExcellent (90-100%)Good (75-89%)Satisfactory (60-74%)Needs Improvement (<60%)
Functionality & Architecture30.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 & Standards20.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 & Reliability20.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 & DevOps15.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 & Presentation15.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.