Check that learners, course access and completion history survive an LMS migration. Includes a reconciliation table, retry tests and a practical cutover review.
Picture the final migration rehearsal. The import dashboard reports 100% complete. One learner signs in to an empty course list, another sees the same course twice, and a manager discovers that last year's completions now carry this week's date.
Every import job may have finished successfully. You still need to establish whether people can learn, teach and report correctly in the new system.
Before cutover, account for each source record with either a verified target result or a documented exception. Then test what users can actually do. A matching row count can help you find a problem, but it will not tell you whether the right learner received the right course.
Our LMS migration checklist covers the wider project. This article focuses on testing and reconciliation between the last rehearsal and the move to the new service. The counts below are illustrative examples rather than a report from a client migration.
Agree what the new system needs to preserve
Start with the records your organization needs after the move. Alongside accounts and course files, that may include enrollments, cohorts, roles, grades, attempts, certificates and historical completion dates. Ask learning operations and reporting users to review the list before the import method is chosen.
Decide where each category will live. Some data needs to work inside the new LMS. Some may be retained as a historical reference or in a separate archive. An archive can be reasonable when the target cannot represent an older record accurately, provided people know how to retrieve it.
Spend time on the meaning of completion. One system may use it for opening an activity; another may require passing an assessment or finishing every required item. Mapping the field name without agreeing on its meaning can change the learning record even when the value imports cleanly.
Write down a few journeys that must work for learners, instructors and managers. These will give the acceptance review something concrete to inspect, alongside the import logs and reconciliation reports.
Match people using stable identifiers
Create a map from each source identifier to its target identifier. Keep it available for the later enrollment and completion jobs. If a source account matches an existing target account, record that match just as carefully as a newly created account.
Email addresses are useful contact details, but can change, be shared or be reused. Decide how to handle missing addresses, duplicates and an address changed between the first export and cutover. Matching only on email can split one person's records across accounts or attach history to the wrong person.
When a conflict appears, send it for review. Appending a number to a name may get an account through an import, but it does not settle which learner should own the original history.
Give every source user a clear status: matched, created, intentionally excluded or waiting for resolution. For unresolved cases, record the reason, owner and affected cohort. The support team can then work through a defined queue instead of comparing spreadsheets with unexplained totals.
Apply the same care to courses and cohorts. Titles change, and two different courses can share a display name. Preserve stable references so enrollment and history jobs can find the intended target.
Test account creation, access and history separately
Creating an account does not grant every required course enrollment. Granting enrollment does not necessarily preserve learning history. Treat these as separate jobs with their own dependencies and evidence.
Moodle's Upload users documentation describes bulk user fields, enrollment options and behavior for existing accounts. Test the settings for the version you operate. A successful user upload should not be taken as proof that all kinds of historical learning records moved with it.
Moodle's flat-file enrollment documentation describes another route for managing enrollments of existing users in existing courses. That dependency matters: an enrollment instruction cannot repair a missing or incorrectly matched account or course.
For your target platform, list the supported import route for each category. Completion history may need a different API, migration tool or agreed archive. Give that route its own rehearsal and acceptance test, even when users can already sign in.
Account for the exceptions in the totals
A reconciliation sheet should explain where every source record ended up. The example deliberately includes unresolved cases and excluded duplicates so the team can see what still needs attention.
| Data category | Source records in this example | Verified target result | Exceptions or exclusions | Cutover evidence |
|---|---|---|---|---|
| Users | 10,000 | 9,800 accounts matched or created | 200 unresolved identities | Each unresolved identity has an owner and affected cohort |
| Enrollments | 30,000 | 29,550 valid access grants | 200 unresolved-user rows, 150 unresolved-course rows, 100 duplicate source rows excluded | Every row has one final disposition |
| Completion records | 18,000 | 17,800 verified historical records | 150 missing references, 50 conflicting records | Original dates and meanings preserved for accepted records |
| Second run of accepted enrollment batch | 29,550 | Same 29,550 intended access grants | No extra grants from replay | Retry test produces no duplicate access |
| Sample learner journeys | 40 proposed test journeys | Evidence recorded per journey | Every failure assigned for repair | Required journeys pass before their cohort moves |
Keep these populations separate. One learner may have several enrollments and many completion records, so adding all the source totals will not produce a unique learner count.
Look at the reason behind a difference too. An intentionally excluded duplicate enrollment row and a learner who has lost access can both reduce the target count by one. They require very different follow-up. Preserve that distinction in the exception report instead of combining everything under “failed rows.”
The same principle applies to accepted rows. A record should be counted as verified only after the checks agreed for that category have passed.
Compare who has access to what
Even if all 29,550 intended enrollments are present, they could still be attached to the wrong accounts or courses. Compare the source user, course, role, status and effective dates with their mapped target values.
Check role mappings explicitly. Two systems may use the same numeric ID for different permissions. Confirm what each role allows in the target; a learner should not acquire instructor access because a number happened to match.
For completion history, check the learner, course or activity, completion state and original date together. An import that assigns today's timestamp to every accepted record may pass a count check while changing the history used in reports.
Automated comparisons can catch missing references and invalid values across large batches. Add a deliberate sample of user journeys as well. A correctly mapped enrollment may point to a hidden course, or a retained certificate reference may open a broken link.
Make exceptions traceable. Someone reviewing one row should be able to find the source record, inspect the target and understand which comparison failed. That saves time when the team starts repairing cases close to cutover.
Interrupt a batch during rehearsal
Let a test batch accept some records, stop it and use the documented recovery procedure to continue. Check whether it recognizes completed work and processes the remaining records without adding duplicate accounts or access grants.
Keep a migration ledger with the batch reference, source reference, target reference, processing result and verification result. Distinguish “sent” from “verified.” A timeout may leave the client unsure about an operation that the target has already completed.
When that happens, inspect the target before repeating the write. The recovery procedure should explain how to do this, rather than leaving the operator to guess whether another request is safe.
Try replaying an older export too. It should not overwrite a subsequently corrected address or reactivate an account deliberately suspended after that export. Use the source versions, timestamps or precedence rules appropriate to the two systems, and test the result.
Capture the changes made after the rehearsal export
People will keep learning while the project prepares for cutover. New accounts appear, enrollments change, assessments finish and administrators correct profiles. A successful rehearsal does not account for that later activity.
Choose how you will capture the final changes. Depending on the systems, you might use a controlled freeze, an incremental export or a supported event-based process. Record the boundary clearly enough that someone can explain which batch includes a particular change.
Test removals and updates as well as new records. A process that only creates accounts can leave old permissions active in the target. Decide what should happen when a learner leaves a cohort or an account is suspended during the migration window.
After the final batch, run reconciliation again. Use the production results for the acceptance decision, with the rehearsal as evidence that the method was tested.
Give each cohort an explicit go-live decision
New learners, active course participants, instructors and reporting users may have different needs. Where the platform and operating plan allow it, moving a verified cohort first can make the support load more manageable.
For each cohort, list the required journeys and remaining exceptions. A missing optional profile field has a different consequence from a missing completion required for an important training record. The accountable learning owner should decide which issues block the move.
Make the decision specific enough to check. For example: every active learner in cohort A has verified access to assigned courses, and the agreed historical records reconcile. “Most records imported” leaves too much open to interpretation.
If a cohort is delayed, explain where its learners should sign in and who will help them. Also record how learning activity during that delay will be reconciled later. Otherwise, a sensible phased move can create another data gap.
Prepare a rollback people can carry out
Before changing the learner's entry point, agree who can authorize rollback, what would trigger it and which steps the team will follow. Test restoration in the environment where it will be needed. A backup file is useful only if the team can restore the required service from it.
Consider activity created after cutover. Restoring an earlier snapshot may discard new completions, messages or profile changes. The plan needs to account for those records as well as the login route.
Agree how long the old environment stays available and in what mode. If it is read-only, support staff need to know. If people can still change records there, define how those changes reach the new system.
Give the support team known issues, account lookup instructions, escalation contacts and the reconciliation report. They should be able to help a learner without first reconstructing the import process.
What a useful migration demonstration should show
Ask the migration team to trace one learner from the source account through to target course access and historical completion. Then choose an unresolved case and ask how it is detected, assigned, repaired and verified.
Try a changed email address, a renamed course, a repeated batch and a completion recorded late in the project. These examples reveal whether the method can handle changes that occur while a real learning service is still in use.
Learning history can sometimes follow users after go-live, if the platform supports it and the business accepts the temporary gap. In that case, document what learners and managers will see, protect new activity from conflicting imports and set a clear verification plan. Keep the requirement open until that work is checked.
Finally, name the people who sign off each category. Engineering can verify transformations and import behavior. Learning operations needs to confirm that the resulting access, experience and history meet the organization's needs. Both checks belong in the cutover decision.
Our software modernization services support phased moves from established systems. Our full-stack development team can build the surrounding integrations and reconciliation tools. You can also explore our education technology solutions. Contact Emerging Stacks with your source LMS, target platform and the records you need to preserve.
Ready to work with us?
Get in Touch


