Context
To improve the Open edX mobile experience, we need to provide learners with a fast, accurate list of upcoming exam and assignment due dates across all of their enrolled courses. This is critical for enabling mobile-first learning workflows, proactive planning, and push notifications.
The current approach, which relies on get_course_date_blocks() and modulestore traversal, is inefficient, especially for multi-course scenarios. The Open edX community has committed to limiting modulestore usage in runtime systems (ADR 0011) and modularizing content and date management.
Solution Summary
We are going to reuse and extend the edx-when application as the unified backend for both course-level and user-level due dates:
- Use
ContentDate to store published due dates from course metadata
- Use
UserDate to store user-specific overrides, including:
- Personalized schedules (self-paced)
- Instructor-granted extensions
- Create a new API endpoint to return a merged and filtered list of upcoming due dates for the authenticated user
Rejected Alternatives
The following approaches were considered during the design phase but ultimately rejected due to technical or architectural limitations:
1. Continue Using Only XBlock Metadata for Dates
- Description: Store all
start, due, and graceperiod fields in the modulestore within XBlock definitions.
- Reason for Rejection:
- No support for user-level overrides.
- Requires course republishing for any change.
- Cannot support dynamic scheduling, self-paced courses, or extensions.
2. Use Only the schedules App to Drive Dates
- Description: Centralize all date logic through
schedules.Schedule and schedules.CourseDateOverride.
- Reason for Rejection:
- Not designed for block-level (e.g., exam-specific) due dates.
- Cannot serve instructor-paced or hybrid course modes.
- Adds significant refactor requirements to upstream LMS and Mobile APIs.
3. Store Dates in a Separate Custom Table or External Service
- Description: Introduce a new app or microservice for handling exam due dates independently of
edx-when.
- Reason for Rejection:
- Duplicates functionality already available in
edx-when.
- Adds operational and architectural overhead.
- Increases latency and coupling across services.
4. Compute Dates On-the-Fly at Runtime
- Description: Dynamically calculate due/start dates based on enrollment and pacing without persisting them.
- Reason for Rejection:
- Degrades performance at scale.
- No audit trail or persistence for extension history.
- Makes date behavior inconsistent and hard to debug.
The final decision to use and extend the edx-when data model preserves flexibility, supports both default and override scenarios, and ensures consistent integration across all platform interfaces (LMS, MFE, Mobile).
Impact on Existing Functionality
Based on our review of the current Open edX codebase, the ContentDate and UserDate models from the edx-when module are not widely integrated into core platform components at this time. Their usage appears to be limited, with no direct dependencies from LMS rendering paths or block structure transformers in the default configuration of the platform.
As a result, the changes proposed in this ADR are not expected to impact existing functionality. The models in question do not currently serve as a critical path for date resolution in standard learner-facing APIs or courseware behavior.
Architecture Overview
✅ What We Reuse
| Component |
Role |
edx-when.ContentDate |
Stores canonical due dates published for each course content element |
edx-when.UserDate |
Stores per-user overrides (e.g., extensions, personalized pacing) |
Schedules |
Provides start_date for self-paced learners (used in overrides) |
🆕 What We Add
| Component |
Purpose |
| New API |
Returns all due dates visible to the user across their courses |
| Runtime logic |
Merges ContentDate and UserDate, applies filtering/visibility |
Data Flow
- Studio authors define dates → written to
ContentDate via publishing
- Overrides from instructors or learners → stored in
UserDate
- Mobile client calls new API
/api/user-due-dates/
- Backend logic:
- Loads enrolled courses
- Retrieves corresponding
ContentDate and UserDate records
- Applies overrides and visibility checks
- Returns sorted, paginated results
API Responsibilities
The new API will:
- Authenticate the user
- Retrieve the list of enrolled courses
- Fetch all related
ContentDate and UserDate entries
- Apply overrides and enforce content visibility
- Return fields such as:
course_id
title
due_date
first_component_block_id
override_source (if applicable)
Scope Limitations
❌ CCX courses (Custom Courses for EdX) are excluded from this implementation due to their unique override structure and management.
Benefits
- ✅ Performance: Indexed queries instead of runtime block traversal
- ✅ Consistency: All dates managed in one canonical system
- ✅ Maintainability: No need to create redundant data models
- ✅ Scalability: Reusable for LMS, mobile, and analytics
- ✅ Forward-compatible: Aligned with plans to remove MongoDB and improve RBAC
Next Steps
- Ensure publishing pipeline writes dates to
ContentDate
- Use
UserDate to record instructor and learner overrides
- Build new endpoint
/api/user-due-dates/
- Merge base and override dates at runtime
- Implement access control and visibility filtering
- Monitor for latency, accuracy, and correctness
Context
To improve the Open edX mobile experience, we need to provide learners with a fast, accurate list of upcoming exam and assignment due dates across all of their enrolled courses. This is critical for enabling mobile-first learning workflows, proactive planning, and push notifications.
The current approach, which relies on
get_course_date_blocks()and modulestore traversal, is inefficient, especially for multi-course scenarios. The Open edX community has committed to limiting modulestore usage in runtime systems (ADR 0011) and modularizing content and date management.Solution Summary
We are going to reuse and extend the
edx-whenapplication as the unified backend for both course-level and user-level due dates:ContentDateto store published due dates from course metadataUserDateto store user-specific overrides, including:Rejected Alternatives
The following approaches were considered during the design phase but ultimately rejected due to technical or architectural limitations:
1. Continue Using Only XBlock Metadata for Dates
start,due, andgraceperiodfields in the modulestore within XBlock definitions.2. Use Only the
schedulesApp to Drive Datesschedules.Scheduleandschedules.CourseDateOverride.3. Store Dates in a Separate Custom Table or External Service
edx-when.edx-when.4. Compute Dates On-the-Fly at Runtime
The final decision to use and extend the
edx-whendata model preserves flexibility, supports both default and override scenarios, and ensures consistent integration across all platform interfaces (LMS, MFE, Mobile).Impact on Existing Functionality
Based on our review of the current Open edX codebase, the ContentDate and UserDate models from the
edx-whenmodule are not widely integrated into core platform components at this time. Their usage appears to be limited, with no direct dependencies from LMS rendering paths or block structure transformers in the default configuration of the platform.As a result, the changes proposed in this ADR are not expected to impact existing functionality. The models in question do not currently serve as a critical path for date resolution in standard learner-facing APIs or courseware behavior.
Architecture Overview
✅ What We Reuse
edx-when.ContentDateedx-when.UserDateSchedulesstart_datefor self-paced learners (used in overrides)🆕 What We Add
ContentDateandUserDate, applies filtering/visibilityData Flow
ContentDatevia publishingUserDate/api/user-due-dates/ContentDateandUserDaterecordsAPI Responsibilities
The new API will:
ContentDateandUserDateentriescourse_idtitledue_datefirst_component_block_idoverride_source(if applicable)Scope Limitations
❌ CCX courses (Custom Courses for EdX) are excluded from this implementation due to their unique override structure and management.
Benefits
Next Steps
ContentDateUserDateto record instructor and learner overrides/api/user-due-dates/