SCL Guides
How to Migrate Student Records to a New SIS
Migration is the reason most schools stay on software they dislike. Here is how to move student records to a new system without losing a year of data or a summer.
On this page
- Decide what actually has to move
- Start from an export, never a blank template
- Match on names your staff use, not internal IDs
- Let it validate before it writes
- Understand the four things a row can do
- Expect the system to do work after the import
- Give the timetable its own rehearsal
- Move catalogs early, because they are easy
- Run it twice
- A sequence that works
Ask a school why they are still running a system nobody likes and the answer is almost never "it works well". It is that moving looks worse. Somewhere in the building is a person who remembers the last migration, and that memory is doing more to keep the contract alive than the software is.
That fear is reasonable. It is also mostly a fear of the wrong thing. Migrations rarely fail because data cannot be moved. They fail because nobody decided what had to move, the first attempt was also the only attempt, and errors surfaced after the write instead of before it.
Here is how to do it properly.
Decide what actually has to move
The instinct is to move everything. It is the wrong instinct, and acting on it is what turns a two-week job into a summer.
Split your data into three piles:
- Must move, live. The current roster: who is enrolled right now, in which grade and class, with the identifiers your school actually uses. Without this nothing else in the new student information system functions.
- Should move. Things the new system will keep generating and that benefit from continuity: your catalogs, your timetable, your subject and grading structure, families and contact details.
- Archive, do not migrate. Deep history. Five years of daily attendance marks, individual assignment scores from closed years, message threads. These are almost never queried again, and every hour spent forcing them into a new schema is an hour not spent on the roster.
For the third pile, export it from the old system in whatever format it offers, put it somewhere safe and readable, and write down where it is. A school that keeps a clean PDF and CSV archive of closed years has met its obligations and saved itself weeks. What you genuinely need forward-facing is the transcript-level summary, not every mark that produced it.
Be honest about this pile in particular. In SCL, Import Data brings in the people and the shape of the school: students, parents, teachers, staff, classrooms, subjects, teaching groups and who is in each group. It does not carry a decade of historical marks across from another vendor, and any vendor who tells you their importer does that without seeing your data first is guessing.
Start from an export, never a blank template
The most common migration mistake is building your import file from the vendor's blank template. You end up guessing at column names, value formats and what counts as required, and you find out you guessed wrong after uploading.
Work the other way round. Get a handful of students into the new system by hand, correctly. Then export that, and you are holding a file with the exact columns, in the exact order, with real values in the right format. That becomes your template, and the guessing stops.
SCL is built for this loop directly. Beside each import's Download template sits Export current records, which downloads what SCL holds now with precisely the columns the import reads back. Export, open it, add your data underneath the real rows, upload. The round trip is the feature. And if a heading in your file is spelt differently, SCL still matches it and shows you the match before anything is written.
Match on names your staff use, not internal IDs
A migration file that requires internal database IDs for every grade, class and house is a migration file only a developer can produce. Every value your registrar has to look up is a value they can get wrong.
Check how the importer resolves relationships. SCL matches the educational level, the classroom and the house by their names, so a row reads "Grade 5" and "5A" the way your staff would write it. When a value cannot be read for certain, such as a classroom name with a typo, SCL asks you once and remembers your answer. Nobody has to know that Grade 5 is internally 17.
The one identifier that does matter is the student code, because it is what makes a student unique and what every later update will match on. Settle your student code scheme before you import anything, not after. If you are changing the scheme as part of the move, change it in the file, once, before the first upload.
Let it validate before it writes
This is the question that separates a safe importer from a dangerous one: does it check the whole file before it writes a single row?
A dangerous importer writes as it reads. It gets to row 240, hits a malformed date, stops, and now you have 239 students in and 61 out and no clean way to work out which. Your only honest option is to delete all of them and start again, and by the third attempt people are editing the database directly, which is how migrations become disasters.
SCL runs a dry run first. Every row is saved exactly as it would be, with the same checks as a student added by hand, and then undone, so nothing is written until you click Import. The dry run lists every row with its number and what it would do, and each problem with its reason: a required value missing, a classroom that does not exist, a code another student already uses. A row with a problem is never imported. By default the rows that pass go in and the rest are left out; switch on Import only if every row passes and the file goes in whole or not at all.
That behaviour is worth stating plainly, because it changes how the work feels. You see every row's fate before you commit, Download the rows with problems hands those rows back with a Problems column, and the result lists what happened to each row. Fix the rows that were left out and import the file again: the rows already in show as Unchanged, so nothing is added twice.
Understand the four things a row can do
In the dry run, SCL sorts every row into one of four kinds and tells you the count of each before you live with the result:
- New. The row matches no student in SCL, so it adds one, and the dry run shows the code the new student will get.
- Changed. The row finds an existing student by SCL ID, student code or a national ID your admission form marks as unique, and only the fields that actually differ are written. An empty cell leaves what SCL holds alone unless you choose otherwise.
- Problem. The row would not save: a required value is missing, a classroom does not exist, or the student has left. This is the safety net: a stale file cannot resurrect a student who has left.
- Unchanged. The row matches an existing student exactly. Nothing happens.
The practical value of this is that the same file is safe to upload twice. A migration you can re-run without fear is a migration you can rehearse, and rehearsal is the entire difference between a calm move and a bad one.
Two things to know before your first real run. Imports are scoped to the current academic year and to students who are actually enrolled, so leavers and alumni are not touched. And every new student takes a licence seat: if a file would add more students than your licence has seats free, the dry run says so and the import does not start, rather than importing part of it.
Expect the system to do work after the import
Loading a roster is not the same as having a working school. Students need to land in the right subject groups, language streams and religion classes before a teacher can take an attendance register or open a gradebook.
Ask how much of that is automatic. In SCL, a student added by an import joins the teaching groups of their level and classroom for every subject set to Automatically Assign, as one added by hand does, and their second language and religion groups follow the values in the file. Import Enrolment places them in any other group. That is the step schools most often underestimate when they migrate by hand, because it does not look like data entry until you are doing it three hundred times.
Give the timetable its own rehearsal
The timetable is the highest-risk single object in the whole move. It touches every teacher and every student on the first morning, and it is the thing people notice immediately when it is wrong.
Treat it separately from the roster and demand a dry run. SCL imports from aSc TimeTables in three deliberate steps: the upload parses the file and stages it without writing anything, a preview shows exactly what would change, and only then does a commit write it. If the result is wrong, one click reverts that exact batch and restores what was there before.
After that, each change to the timetable takes the same route: make it in aSc and import its file again, with the same preview. That routine matters more than the first import itself, because a one-time import drifts from the day somebody makes the first change in the wrong place.
Move catalogs early, because they are easy
Catalogs are the reference data everything else points at: subjects, grading scales, houses, and for many schools the library. They are low-risk, they are quick, and having them in place before the roster arrives means students land into a school that already exists rather than an empty shell.
The library is a good example of why to do this early rather than late. SCL takes a CSV with the columns a librarian already recognises, including ISBN, title, authors, publisher, barcode, accession number and shelf location, and it looks up cover images in the background rather than making you wait for a few thousand of them. Start it, and go and do something else.
Run it twice
Everything above is in service of this one instruction, which is the only piece of migration advice that matters if you remember nothing else.
The first run is a rehearsal. Load the real file, look at the counts, open ten student records and check them against the old system, and get your registrar to look for the twenty students they know are awkward: the mid-year joiners, the siblings with similar names, the child whose name is spelled two different ways in the old system.
The second run is the real one. By then you know your file is clean, you know what the counts should be, and the whole thing is uneventful. Uneventful is what you are buying.
Schedule the rehearsal at least three weeks before you need the system live. Not because the import takes three weeks, but because the rehearsal is what tells you which data in your old system is worse than anyone admitted, and finding that out is the actual purpose of doing it.
A sequence that works
- Set up the school structure first: divisions, grades, classes, subjects, grading scales.
- Import catalogs and reference data.
- Add a few students by hand, correctly, then export to get your real template.
- Build the full student file from that export.
- Rehearse the import. Read the errors. Fix the file, not the system.
- Check the awkward twenty by hand.
- Import the timetable with its dry run, and review the preview properly.
- Run the real import.
- Open the parent app as a parent before you announce anything to families.
- Archive the old system's history somewhere readable, and write down where.
None of this requires heroics. It requires deciding what moves, working from an export instead of a template, insisting on validation before writing, and running the whole thing once before it counts.
If you are still choosing a system rather than moving to one, the questions to ask are in our buyer's checklist. If you want to talk through what moving your school would actually involve, with your data in front of us, get in touch.