Technical Exploration Questions & Answers

Technical Exploration Questions & Answers

This document compiles a series of technical questions and answers that emerged during a research and exploration phase focused on the current user grouping mechanisms in Open edX: Cohorts, Teams, and Enrollment Track groups. The goal of this exploration was to gain an in-depth understanding of the behavior, structure, and limitations of each mechanism to assess the feasibility of unifying them into a more flexible, centralized grouping model. The questions are organized by key topics and serve as a foundation for identifying requirements, risks, and opportunities for the transition to a new model.

1. Current Behavior of Existing Mechanisms

Assignment and Membership

How and under what rules are users assigned to groups in each mechanism (manual assignment, automatic, conditions)?

Cohorts

  • Automatic (Random):

    • If automatic cohorts are configured, users are randomly assigned to one of them the first time they access course content.

    • If there are no automatic cohorts, a default cohort ("Default Cohort") is created, and users are assigned there.

    • If multiple automatic cohorts exist, the user is randomly assigned to one.

  • Manual:

    • Instructors can assign users to specific cohorts from the instructor dashboard in the LMS or by uploading a CSV file.

    • Manual assignment can be done for any type of cohort (automatic or manual).

    • It is possible to assign users to a cohort before they enroll in the course, or even before they have a registered account on the platform (using the UnregisteredLearnerCohortAssignment model).

Teams

  • Manual:

    • All teams within a team set are manually managed by instructors or students.

    • Instructors can assign students to specific teams via a CSV upload.

    • If the team to which an instructor assigns a student does not exist, the team is created, and the student is assigned.

      Types of Team-Sets/Groups/Topics:

      • Open (open): Students can join, leave, or create teams from the LMS.

      • Public Managed (public_managed): Only instructors manage teams; teams are visible to all.

      • Private Managed (private_managed): Only instructors manage teams; team content is private; students can only see their team.

      • Open Managed (open_managed): Only instructors can create teams; students can join/leave teams freely (requires MFE config enabled).

Enrollment Track

  • Automatic:

    • When enrolling, students select a "course mode" (audit, verified, professional, etc.)

    • Based on their course mode, they are automatically assigned to the corresponding enrollment track group.

    • Enrollment can be updated during the course (re-enroll or enrollment mode update via support tools).


Can a user belong to multiple groups within the same type?

Group Type

Multiple memberships allowed?

Group Type

Multiple memberships allowed?

Cohorts

No (only one cohort per course)

If a user is assigned to another, it's automatically removed from the previous one. This is controlled by the CohortMembership model, which ensures only one association per course.

Teams

No, within the same team set

✅ Yes, across different team sets

A user can join only one Team within the same Team-Set, but can belong to several Teams if each one is in a different Team-Set.

Enrollment Track

No (only one enrollment track per course)

It is determined by the user's CourseMode.


How is membership managed when a user changes groups?

Group Type

Change Process

System Behavior

Group Type

Change Process

System Behavior

Cohorts

  • Cohort change is manual and exclusive.

  • Managed through CohortMembership.assign(cohort, user).

  • Automatically removes previous membership in any other Cohort of the course and records the new association in the database.

Teams

  • To change Teams within the same Team Set:

    • The user must leave their current team first.

    • Then they can join another Team in the same team set if space is available.

  • Process depends on the Team-Set type:

    • In open or open_managed, users can do it through the interface.

    • In public_managed or private_managed, only instructors can manage the change.

  • The CourseTeamMembership.delete(...) model handles removing the previous membership and updating the team size.

Enrollment Track

  • Change is not managed at the group system level, but at the enrollment level (CourseEnrollment).

  • A user cannot manually change their Enrollment Track within the platform.

  • To change tracks, users typically must cancel their enrollment and re-enroll in the desired mode, if available.


What restrictions exist when changing groups?

Group Type

Restrictions

Group Type

Restrictions

Cohorts

Exclusivity: A user can only belong to one cohort per course.

  • A user cannot change cohorts themselves; only an instructor can reassign them.

Teams

Uniqueness per Team-Set: A user can only belong to one team per team-set.

Depending on the type of team set (e.g., private_managed, public_managed):

  • The user might not be able to self-assign to a new team.

  • Instructor intervention may be required to make the change.

Some teams might be full, preventing the change if the new team has already reached its max_team_size.

Enrollment Track

Not editable through the LMS once assigned.

  • The Enrollment Track is determined at the time of enrollment, and there is no exposed UI or API to change it afterward.

  • To change tracks, users must unenroll and re-enroll under a different mode.

Roles and Permissions

What permissions do different roles (instructors, staff, students) have over groups, and through which interfaces (LMS, Studio)?

Cohorts

Role

Allowed Actions

Available Interfaces

Role

Allowed Actions

Available Interfaces

Instructor / Staff

  • Create, modify, and assign cohorts.

  • Change users' cohort assignment.

  • Enable cohort-based discussion division.

  • Restrict content per cohort (via Partitions).

LMS (Instructor Dashboard), Studio (Course Outline Restrictions and Discussion Division)

Student

  • No control over cohort assignment.

  • Assigned automatically or by staff.

Passive interaction only (LMS)

Teams

Role

Allowed Actions

Available Interfaces

Role

Allowed Actions

Available Interfaces

Instructor / Staff

  • Create Team-Sets and Teams.

  • Modify team configurations (type, size, etc.).

  • Assign or move students between teams.

  • View all teams and their members.

  • Restrict content per Team (via Partitions).

  • Studio (Settings for Team-Sets and ORA configuration)

  • LMS (Team tab, if enabled)

Student

Depending on the type of Team-Set:

  • Create teams

  • Join or leave a team.

  • View teams (if public).

LMS (Team tab, if enabled)

Enrollment Tracks

Role

Allowed Actions

Available Interfaces

Role

Allowed Actions

Available Interfaces

Instructor / Staff

  • No direct control over the groups.

  • Restrict content by Enrollment Track (via Partitions)

Studio (Group Configurations)

Student

  • Select Enrollment Track during enrollment (audit, verified, etc.).

  • Cannot easily change it afterwards.

Passive interaction only (LMS)

Technical Structure

Where is the group assignment information stored in the database?

Cohorts

  • Main group model: CourseUserGroup

  • User assignment: CohortMembership

  • Additional group information: CourseCohort

  • Course-level configuration: CourseCohortsSettings

  • Preliminary assignment (for unregistered users): UnregisteredLearnerCohortAssignment

  • Relation to partitions: CourseUserGroupPartitionGroup

Technical Notes:

  • All these models are located in: openedx/core/djangoapps/course_groups/models.py

  • The relationship between CourseUserGroup and CohortMembership ensures uniqueness per course.

  • Partitions allow linking a cohort to specific course content (using Content Groups)

 

Teams

  • General configuration and Team-Set:
    Not stored in a model, but directly in the CourseBlock (field teams_configuration in JSON format).

  • Group model: CourseTeam

  • User assignment: CourseTeamMembership

Technical Notes:

  • Models are located in: lms/djangoapps/teams/models.py

  • Each CourseTeam belongs to a Team-Set, defined in the course’s advanced settings.

  • CourseTeamMembership manages the relationship between users and teams.

 

Enrollment Track

  • There is no explicit "group" model.

  • Group assignment is based on the user's enrollment mode (CourseEnrollment.mode).

Technical Notes:

  • Dynamic partitioning uses the CourseMode model to generate groups at runtime.

  • EnrollmentTrackUserPartition and EnrollmentTrackPartitionSchema define the logic in the code, but grouping is not explicitly persisted in the database.


What models and fields are used by each mechanism?

Cohorts

Main Models:

  • CourseUserGroup

    • id: Group ID

    • name: Group name (unique per course)

    • course_id: The Course the group belongs to

    • group_type: Currently only "cohort"

  • CohortMembership

    • user: Assigned user

    • course_user_group: Associated group

    • course_id: Course (may seem redundant, but useful for validation)

  • CourseCohort

    • course_user_group: ForeignKey to CourseUserGroup

    • assignment_type: "random" or "manual"

  • CourseCohortsSettings

    • course_id: Course ID.

    • is_cohorted: Boolean that enables/disables cohorts in the course

  • UnregisteredLearnerCohortAssignment

    • email: Email of unregistered user.

    • cohort: Cohort assigned to the user.

File: openedx/core/djangoapps/course_groups/models.py

Teams

Course Configuration (not a Django model):

  • teams_configuration (JSON within CourseBlock)

    • enabled: Whether Teams is enabled

    • max_team_size

    • team_sets: List of dictionaries with:

      • id

      • name

      • description

      • max_team_size

      • type: "open", "public_managed", "private_managed" or "open_managed"

      • user_partition_id

Main Models:

  • CourseTeam

    • team_id: Unique ID

    • name, description, country, language

    • topic_id: ID of the Team Set it belongs to

    • discussion_topic_id

    • course_id

    • organization_protected

  • CourseTeamMembership

    • user: Assigned user

    • team: Corresponding team

    • date_joined, last_activity_at

File: lms/djangoapps/teams/models.py

Enrollment Track

No dedicated group models. Uses:

  • CourseEnrollment

    • user

    • course_id

    • mode: "audit", "verified", etc.

Other related models:

  • CourseMode: Describes available modes for the course

Dynamically generated groups in code using:

  • EnrollmentTrackUserPartition

  • EnrollmentTrackPartitionSchema

Files: Logic distributed in openedx/core/lib/partition and openedx/core/djangoapps/course_modes/models.py


APIs for Managing Groups

Cohorts

Legacy API

Base URL: /courses/<course_id>/cohorts/

Available Methods:

  • Create, list, and update Cohorts

  • Assign and remove users from Cohorts

  • Get and update Cohort settings

Key Endpoints:

  • GET /courses/<course_id>/cohorts/: Lists cohorts in a course

  • POST /courses/<course_id>/cohorts/: Creates a new cohort

  • PUT or PATCH /courses/<course_id>/cohorts/<id>/: Updates a cohort

  • POST /courses/<course_id>/cohorts/<id>/add/: Assigns a user to a cohort

  • DELETE /courses/<course_id>/cohorts/<id>/delete/: Removes a user from a cohort

  • GET /courses/<course_id>/cohorts/settings/: Gets cohort settings for a course

  • PATCH /courses/<course_id>/cohorts/settings/: Updates cohort settings for a course

Note: There is a GET endpoint to obtain cohort members, but the URL conflicts with /courses/<course_id>/cohorts/<id>

Code Location: openedx/core/djangoapps/course_groups/views.py

DRF API

Base URL: /api/cohorts/v1/

Available Methods:

  • Create, list, and update Cohorts

  • Assign, list, and remove users from Cohorts

  • Get and update Cohort settings

Key Endpoints:

  • GET /api/cohorts/v1/courses/<course_id>/cohorts/: Lists cohorts in a course

  • POST /api/cohorts/v1/courses/<course_id>/cohorts/: Creates a new cohort

  • PATCH /api/courses/<course_id>/cohorts/<id>/: Updates a cohort

  • GET /api/cohorts/v1/courses/<course_id>/cohorts/<id>/: Gets a specific cohort

  • GET /api/cohorts/v1/courses/<course_id>/cohorts/<id>/users/: Lists users in a cohort

  • POST /api/cohorts/v1/courses/<course_id>/cohorts/<id>/users/<username>/: Assigns a user to a cohort

  • DELETE /api/cohorts/v1/courses/<course_id>/cohorts/<id>/users/<username>/: Removes a user from a cohort

  • POST /api/cohorts/v1/courses/<course_id>/cohorts/<id>/users/: Assigns multiple users to a cohort

  • POST /api/cohorts/v1/courses/<course_id>/users/: Assigns users to a cohort using a CSV file

  • GET /api/cohorts/v1/settings/<course_id>/: Gets cohort settings for a course

  • PATCH /api/cohorts/v1/settings/<course_id>/: Updates cohort settings for a course

Code Location: openedx/core/djangoapps/course_groups/views.py

API Documentation: /api-docs/#/cohorts

 

Teams

REST API (v0)

Base URL: /api/team/v0/

Available Methods:

  • List team sets in a course

  • List teams in a course or for a user

  • Create, list, update, or delete teams

  • Assign, list, or remove team members

  • Generate or upload CSV files with team memberships

Key Endpoints:

  • GET /api/team/v0/topics/?course_id=<course_id>: Lists team-sets in a course

  • GET /api/team/v0/topics/<topic_id>,<course_id>: Gets a specific team-set

  • GET /api/team/v0/teams/?course_id=<course_id>: Lists teams in a course

  • POST /api/team/v0/teams/: Creates a team

  • GET /api/team/v0/teams/<team_id>: Gets a specific team

  • PATCH /api/team/v0/teams/<team_id>: Updates a team

  • DELETE /api/team/v0/teams/<team_id>: Deletes a team

  • GET /api/team/v0/team_membership/?team_id=<team_id>: Lists members of a team

  • GET /api/team/v0/team_membership/?username=<username>: Lists teams a user belongs to across the platform

  • POST /api/team/v0/team_membership/: Assigns a user to a team