Inside a TMS Data Model: Sessions, Instructors, Venues and Enrollments

Featured image with a periwinkle pastel background and a grid pattern, showing the post title "Inside a TMS Data Model: Sessions, Instructors, Venues"

Inside a TMS Data Model: Sessions, Instructors, Venues and Enrollments

A TMS data model is the set of records a training management system keeps to run instructor-led training: courses, scheduled sessions, venues, instructors and enrollments, plus the links between them. The key design choice is to separate what you teach (the course) from when and where you teach it (the session) and who signed up (the enrollment).

Get that split wrong and every later feature hurts. Reschedules overwrite history, a cancelled learner vanishes from reports, and two classes quietly book the same room. This guide walks through the entities, the relationships and the rules worth enforcing in the database, with a worked example and SQL you can adapt.

Key takeaways

  • Model three layers: the course (catalog entry), the session (one scheduled run) and the meeting (one dated block). Learners enroll in sessions, not courses.
  • Vendors use “session”, “event”, “class” and “section” for different layers, so map the terms before you compare, integrate or migrate.
  • Attach rooms and instructors to meetings, not sessions, so multi-day, split-site and substitute-teacher classes work.
  • Never delete a cancelled enrollment. Keep status history and attendance as separate records.
  • Let the database block double bookings with constraints, with application warnings on top.

What does a TMS data model need to represent?

A TMS data model must represent five things: what is taught (courses), when it runs (sessions and meetings), where (venues and rooms), who delivers it (instructors) and who attends (learners, enrollments and attendance). Payments and certificates hang off those records rather than replacing them.

This is a different job from a learning management system, which centers on content and learner progress. In instructor-led training the scarce things are room-hours, instructor-days and seats, so each needs a first-class record, not a text field on a course.

Why do TMS products use different words for the same thing?

There is no standard vocabulary for the middle layer. The scheduled run that learners book is called a “session” in some products, an “event” in others and a “class” or “section” elsewhere. Check what each term means in a given product before you compare, integrate or migrate.

Source Catalog entry Scheduled run learners enroll in Dated block inside the run
Oracle PeopleSoft Course Course session Cut session, with its own dates, times, location and instructor
Microsoft industry data model Training Course Training Session (also called a class or section) Meeting, where attendance can be recorded per meeting
Totara Learn Seminar activity Event Session, with a start and finish time and optionally one room
This post Course Session Meeting

The collision is real. “Session” names the middle layer in PeopleSoft and the Microsoft model but the bottom layer in Totara. This post uses course, session and meeting as defined in the last column.

How do a course, a session and a meeting differ?

A course is the catalog entry: title, objectives, duration and prerequisites. A session is one scheduled run of that course, with seats, a delivery mode and a status. A meeting is one dated block inside the session, with its own time, place and instructor. Learners enroll in sessions.

What belongs on the course?

Keep only what is true of every run: code, title, description, prerequisites, standard duration, default minimum and maximum seats, and the delivery modes you offer. A catalog change should never silently change a class that is already selling seats.

What belongs on the session?

The session holds what is true of one run: its course, status, seat limits, delivery mode, language and price. PeopleSoft uses three session statuses (Active, Canceled and Complete). Most providers also want draft and full, so plan for a short, explicit list.

What belongs on the meeting?

The meeting holds a start, an end, a time zone, a room or join link, and its instructors. PeopleSoft splits a session into “cut sessions” that each carry their own dates, times, location and instructor, and requires their durations to add up to the session duration. A meeting layer gives you the same flexibility.

Pro tip: Copy defaults, do not share them. When you create a session, copy the course’s duration and seat limits onto it, as PeopleSoft does with duration and minimum and maximum students. Later catalog edits then affect future sessions only, and past reports stay true to what was sold.

What does the core TMS data model look like?

Ten entities cover most instructor-led operations. The table lists each one, what it holds and how it links to the others. Treat it as a starting schema to adapt, not a standard: it is a synthesis of the vendor models cited above plus the design reasoning in this post.

Entity What it represents Key fields Links to
Course Catalog entry code, title, default duration, default min and max seats Has many sessions
Session One scheduled run course, status, min and max seats, delivery mode, price Has many meetings and enrollments
Meeting One dated block starts_at, ends_at, time zone, join link Belongs to a session; at most one room
Venue A site name, address, time zone, owner (yours or a client’s) Has many rooms
Room A bookable space name, capacity Used by many meetings
Instructor A person who teaches person, status, qualified courses Has many assignments
Instructor assignment Who teaches which meeting meeting, instructor, role (lead or assistant) Joins meetings and instructors
Learner A person who attends person, employer or customer Has many enrollments
Enrollment One learner in one session session, learner, status, source, timestamps Has status history and attendance
Attendance Presence at one meeting enrollment, meeting, status, recorded by Joins enrollments and meetings

The relationships read like this:

course 1--* session 1--* meeting *--1 room *--1 venue
meeting 1--* instructor_assignment *--1 instructor
session 1--* enrollment *--1 learner
enrollment 1--* attendance *--1 meeting

Keep one person record and give it roles. The same person can be an instructor on one course and a learner on another, and PeopleSoft checks an instructor’s language skills in the person profile for multilingual courses.

How should you model venues, rooms and equipment?

Model a venue as a site with an address and time zone, and a room as a bookable space with a capacity inside it. Link each meeting to at most one room. Treat equipment as separately bookable resources, and treat virtual delivery as a join link on the meeting, not as a fake room.

Totara lets a session be tied to one room and any number of assets. PeopleSoft checks the session’s maximum students against room capacity when a facility is chosen, and represents external sites through vendor records. Training providers often teach at client premises or hired rooms, so allow a venue to be one-off or owned by a customer.

Keep two capacity numbers. Room capacity is physical. Session maximum seats is a commercial decision that must not exceed the smallest room used by any of its meetings. Put the delivery mode on the meeting, not only the session, because a hybrid class needs both a room and a join link.

How should you model instructors and their assignments?

Keep the instructor as a role on a person record and assign instructors to meetings, not sessions. A meeting-level link handles co-teaching, a substitute on day two and an assistant for a lab day. The session can still display a lead instructor, derived from its meetings.

PeopleSoft lists only qualified, available instructors when you pick one, and it checks availability against teaching schedules and absence data. For the schema, you need a qualification link between instructor and course, with valid-from and valid-to dates, plus unavailability blocks stored as time ranges. Matching logic on top of that is a separate topic.

What is an enrollment, and what should it record?

An enrollment (spelled “enrolment” in UK English) is one learner’s booking in one session. It holds a status, timestamps and a source, but not attendance or completion. Those live in their own records, so a cancelled learner or a no-show stays visible in reports.

Vendors document slightly different states. Totara describes waitlisted, approval pending, accepted or rejected, cancelled and archived sign-ups, and moves waitlisted learners to the booked list when a space opens. PeopleSoft distinguishes waiting and enrolled. A practical set looks like this:

  • Pending approval: a manager or administrator must approve before a seat is held.
  • Waitlisted: the session is full, ordered by the time the learner joined the list.
  • Confirmed: the learner holds a seat.
  • Cancelled: the seat is released but the record stays.

Store every change as a row in a status history table with the new status, time, actor and reason. Seats taken are then a count of confirmed enrollments, and a dispute about who cancelled when has an answer.

Attendance is one row per enrollment per meeting, matching the Microsoft model’s option to record it per meeting. Completion should be derived from attendance by a rule you can change, such as presence at every meeting. Prices, payers and invoices belong in an order record that points to the enrollment.

How should a meeting store dates and time zones?

Store each meeting’s start and end as UTC instants, together with the IANA time zone name of the place it happens, such as Asia/Singapore. Display times in the learner’s zone. Never store only a local time, and never only a UTC offset, because offsets change with daylight saving.

Generate recurring series into concrete meeting rows when the session is created. “Every Tuesday at 9:00” then becomes real rows that can be moved, cancelled or reassigned one at a time, and conflict checks work on plain time ranges instead of recurrence rules.

Which rules should the database enforce itself?

Enforce the rules that must never be broken, whichever application sends the write: one active enrollment per learner per session, valid time ranges, no overlapping meetings in the same room or for the same instructor, and no seats beyond the limit. Application code can add friendly warnings on top.

The PostgreSQL documentation explains that an exclusion constraint can express “non-overlapping” on a range type, and that the btree_gist extension lets you combine it with an equality test on a plain column such as a room. That maps directly to double booking:

CREATE EXTENSION IF NOT EXISTS btree_gist;

CREATE TABLE meeting (
  meeting_id bigint PRIMARY KEY,
  session_id bigint NOT NULL,
  room_id    int REFERENCES room,
  starts_at  timestamptz NOT NULL,
  ends_at    timestamptz NOT NULL,
  CHECK (ends_at > starts_at),
  UNIQUE (meeting_id, starts_at, ends_at),
  EXCLUDE USING gist
    (room_id WITH =, tstzrange(starts_at, ends_at) WITH &&)
);

CREATE TABLE meeting_instructor (
  meeting_id    bigint NOT NULL,
  instructor_id int NOT NULL,
  starts_at     timestamptz NOT NULL,
  ends_at       timestamptz NOT NULL,
  FOREIGN KEY (meeting_id, starts_at, ends_at)
    REFERENCES meeting (meeting_id, starts_at, ends_at)
    ON UPDATE CASCADE,
  EXCLUDE USING gist
    (instructor_id WITH =, tstzrange(starts_at, ends_at) WITH &&)
);

The default range includes its start and excludes its end, so a 09:00 to 12:00 meeting and a 12:00 to 13:00 meeting in the same room do not collide. Decide which conflicts are hard blocks, such as a room holding two classes, and which are only warnings, such as an instructor’s preferred hours. Only hard blocks belong in constraints.

Pro tip: Copy the time range into the assignment table. An exclusion constraint checks rows in one table, so the instructor check above needs the meeting’s times copied onto each assignment. The composite foreign key with ON UPDATE CASCADE keeps the copy correct when a meeting moves, so there is no drift to repair.

How does one course turn into rows? A worked example

Suppose a provider runs a two-day course, “Excel for Finance Teams”, twice in November 2026. That is one course, two sessions and four meetings. The invented data below shows where each fact lives, including a substitute instructor and a waitlist promotion.

Record Example values
Course EXC-201, 2 days, default 6 to 16 seats
Session S1 In person, 9 to 10 Nov, 14 seats (the room holds 16), status confirmed
S1 meetings 9 Nov and 10 Nov, 09:00 to 17:00 Asia/Singapore, both in Room 2
S1 assignments Instructor A leads on 9 Nov; Instructor B substitutes on 10 Nov
Session S2 Virtual, 16 to 17 Nov, 25 seats, no room, join link on each meeting
S1 enrollments 14 confirmed; a 15th learner waitlisted
Status history A confirmed learner cancels; the waitlisted learner moves to confirmed, with both changes timestamped

With this shape, three operational questions become single queries: who teaches on 10 Nov, how many seats S1 has left (14 minus confirmed enrollments), and what happened to a particular learner’s booking. If one of your current questions needs a spreadsheet or a phone call, that is the gap in the model.

What does a TMS data model leave to other systems?

A scheduling core should stay focused. Leave payments and invoicing to an order and billing model, content delivery and learner progress to an LMS, and credentials to a certificate model. Each should reference your enrollments by ID, so the scheduling data stays clean when those systems change.

Instructor matching, which scores availability, qualification and cost, also sits on top of this schema rather than inside it. Records that must reach an HR system need a sync design of their own. Mundrisoft’s piece on custom enterprise LMS platforms and HRIS integration shows how that side is usually framed.

What should you do next?

Lay your current schema or spreadsheet against the ten-entity table and mark every entity that lives in free text, such as venue names typed into a course row. Those are the places where conflicts and reporting gaps will appear first.

Then run the three questions from the worked example against your data. If you are comparing platforms, ask each vendor to show how its objects map to course, session and meeting, and where rooms and instructors attach.

SimpliTrain, Mundrisoft’s platform for instructor-led and virtual training, is aimed at professional training companies that run instructor-led and virtual classes.

Frequently asked questions

What is a TMS data model?

It is the structure of records a training management system uses to run instructor-led training. Core entities are courses, sessions, meetings, venues, rooms, instructors, learners, enrollments and attendance, and the relationships between them. A good model lets you answer who teaches when, where, and who is booked, without manual cross-checking.

What is the difference between a course and a session in a TMS?

A course is the catalog entry that describes what is taught. A session is one scheduled run of that course, with dates, seats, a delivery mode and a status. One course has many sessions over time. Learners enroll in sessions, which is why price and capacity belong there.

Should instructors be assigned to sessions or to meetings?

Assign them to meetings. A session-level link cannot represent a substitute on day two, a co-teacher for one afternoon or an assistant on a lab day. You can still show a lead instructor on the session by deriving it from the meetings.

How do you model a waitlist in a TMS?

Treat waitlisted as an enrollment status, not a separate table. Order waitlisted learners by the time they joined the list. When a confirmed learner cancels, move the first waitlisted learner to confirmed and record both changes in the status history, so every promotion can be explained later.

Why store UTC and a time zone name for each meeting?

UTC gives an exact instant for conflict checks and reminders. The IANA zone name, such as Asia/Singapore, records where the class happens, so you can show the correct local time and handle daylight saving. A bare offset cannot, because the offset for a place changes during the year.

What is the difference between enrollment and attendance?

Enrollment says a learner holds a seat in a session. Attendance says whether that learner was present at each meeting. Keeping them apart lets you report no-shows, partial attendance and late cancellations accurately, and lets completion rules change without rewriting booking history.