Design Course, Module, and Lesson Progress APIs
Fora TravelSoftware Engineer · Technical ScreenLast updated
Tests your ability to design RESTful APIs and underlying data access patterns for a hierarchical learning management domain (Course -> Module -> Lesson) with authenticated user scoping, idempotent completion updates, and derived completion metrics.
Scenario
You are building the core learning progress service for an online travel advisor training platform. The curriculum is organized into a three-level hierarchy:
- Course: Contains multiple ordered Modules.
- Module: Contains multiple ordered Lessons.
- Lesson: The atomic unit of content that a user completes.
You need to design the authenticated HTTP APIs and supporting data access patterns for tracking learner progress.
Requirements
1. API Endpoints
Design clean, RESTful endpoints (HTTP method, path, request payload, and response status/shape) for:
- Mark Lesson Complete: Given a lesson ID, mark it as completed for the authenticated user. This operation must be idempotent (calling it multiple times should not create duplicate records, corrupt timestamps, or return errors).
- Get Course Progress: Fetch progress for a single course, returning course-level completion percentage, a breakdown per module, and completion status for every lesson within the course.
- List User Courses: Return a paginated list of all enrolled courses for the authenticated user along with their high-level completion status (e.g.,
not_started,in_progress,completed) and overall percentage.
2. Authorization & Scoping
- Explain how you guarantee that learners can only read or mutate their own progress, even if malicious input provides another user's ID in parameters or headers.
- Ensure hierarchy validation: verify that a lesson belongs to an active course the learner is actually enrolled in before accepting completion.
3. Data Model & Derived Progress
- Outline the database schema (tables, foreign keys, constraints, and indexes) to support these queries efficiently.
- Detail whether module and course completion percentages should be calculated dynamically on read or materialized/cached on write, and justify your choice.
Deliverables
- API Specifications: Detailed request/response contracts for all three endpoints.
- Database Schema: Relational table definitions with primary keys, unique constraints, and recommended indexes.
- Concurrency & Idempotency Strategy: Explanation of how concurrent completion requests for the same lesson are handled safely without race conditions.
- Query Efficiency: Strategy to avoid
N+1query bottlenecks when generating the nested course progress response.
Hints
Hint 1
Rely exclusively on the verified authentication token (e.g., session or JWT claims) to extract the learner's `user_id` rather than trusting path or query parameters.
Hint 2
For idempotency and race condition safety, define a compound unique constraint on `(user_id, lesson_id)` and utilize an `INSERT ... ON CONFLICT DO NOTHING` (upsert) pattern.
Hint 3
To avoid N+1 queries when loading nested course progress, fetch all modules and lessons for the course alongside the user's completed lesson IDs in two bulk queries, joining them in memory.
Follow-up questions
- How would you handle a curriculum update where a new lesson is added to an already completed module or course?
- If course enrollment reaches millions of active learners, how would you optimize the `List User Courses` query to keep response times sub-50ms?
- How would you design the API if a lesson requires partial progress tracking (e.g., video watch percentage or quiz score) instead of a simple boolean completion?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.