School management systems are rarely as simple as they seem
When people think about a school management system, even developers often picture something fairly simple. Managing students, classes, attendance, tuition fees. It sounds like a CRUD app, just slightly extended.
CRUD stands for Create, Read, Update and Delete. These are the four most basic, core operations for managing and interacting with persistent data in software systems, relational databases (SQL) and NoSQL. CRUD helps users create, view, edit, and remove information.
I used to think that too.
That changed when I joined a real EdTech project and realized what I was dealing with was not just an application, but a large, layered system that runs every day according to how schools actually operate.
At some point, you realize it is no longer an app but an ecosystem
The project I joined was not a single app. It served a school chain with around 20 campuses and more than 100,000 users. More importantly, the users were not just "end-users" in the usual sense.
Within the same system, we had to serve parents, students, teachers, and operations staff. Each group uses the system differently, needs different actions, and comes with a different level of data sensitivity.
And when I say "system," I actually mean multiple systems running in parallel. There was the school admin web, the parent app, the teacher app, the parent web portal, along with integrated systems such as CRM for admissions, ERP for finance, payment, and SSO.
From a technical perspective, this is no longer just a project. It is an ecosystem, where a small change in one place can trigger a chain reaction across many others.
The real complexity starts when data and business logic move across systems

Think of a simple situation. A parent registers their child for admission.
The initial data is created in the admissions system, where the application is recorded and tracked. Once the student is accepted, that data is passed to the school management system so the academic journey can begin. At the same time, tuition information is sent to the finance system to create receivables and track payments. When the parent pays, the payment system updates the finance system, which then affects what services the student is allowed to use.
Throughout this process, the parent logs in only once. But behind the scenes, multiple systems are coordinating step by step.
From the outside, everything looks seamless. Underneath, however, data is constantly moving between systems, and each step depends on the state created by the previous one.
This is no longer about building a single application. It is about designing how multiple systems work together without breaking consistency.

The hardest part is not the technology but the constantly changing business logic

Familiar technology does not make the problem easier
If you only look at the technology, this does not seem like a particularly difficult project.
The stack is familiar: PHP with Laravel, ReactJS, React Native, MySQL. Nothing especially new, nothing that looks overly complex.
But the project is still hard.
Because the difficulty is not in the technology. It is in the business logic.
In EdTech, business rules are layered and constantly changing by school, by program, by academic year. Sometimes they even exist only because "this is how operations are used to doing things," without being fully documented anywhere.
Only when all of that is brought into a shared system does the real complexity show up.
What determines scalability is how you model the business
In systems like this, technology is only the visible layer. What really determines scalability is how the business is modeled and how the system handles change.
If the business logic is not clearly designed from the beginning, every change will turn into patches scattered across the system, and things will gradually become harder to understand and maintain.
If you look at school software simply as a tool for entering, storing, and connecting data, you will almost certainly underestimate how difficult the problem actually is.
If you treat a student as just a data record, you will design the system wrong
Data is only the visible part, state is where the real complexity lies
One of the biggest shifts in my thinking came from how the system needs to understand a student.
In this system, a student is not just a row in a table. A student is an entity with states and a lifecycle.
A student moves through multiple states: pending enrollment, pending document completion, admitted, pending admission, active, on hold, or pending transfer. These states are not for display. They determine what the student can do, what is restricted, and directly affect service registration, payments, and how information is shown to parents.

If states and transitions are not clearly defined, the system becomes harder to fix over time
In system design, there is a concept called a state machine. It defines what states an entity can be in and how it is allowed to move between those states.
A state machine is a model used to manage how a system behaves over time. At any given moment, the system is in a specific state and transitions to another state based on inputs and conditions. This makes the logic clearer and easier to maintain.
In EdTech, this is very close to the core of the business.
There are cases where a student can carry multiple states at the same time across different campuses. If you still approach the problem as "save form, update table," the design is already going in the wrong direction.
When the state model is unclear, the system starts producing bugs that are hard to reproduce, logic overlaps, and every fix makes things more complicated instead of simpler.
Once you scale across campuses, the problem is no longer just about data
Each school is effectively a different way of operating
One early assumption the team made was that schools using the same system would be mostly similar.
That turned out to be wrong.
The difference between a preschool and a K-12 school alone is enough to create significant differences in how things operate. From how services are registered, to how forms are structured, to validation rules that are valid in one school but not in another.
Individually, these differences seem small. But when you bring them into a single platform, the problem changes. It is no longer about writing correct logic. It is about designing a system that can absorb variation.

Validation is about matching real-world operations, not just checking data
Validation is not just about checking if data is empty or correctly formatted. It is about ensuring that what is entered aligns with how the system is supposed to operate in reality.
Whether something is valid may depend on the school, the grade, the program type, the academic year, and the student's current state.
Some rules are valid in School A but not in School B. Some rules apply this year but must change next year.
At that point, the challenge is not writing one correct rule set. It is designing a system that can handle continuous change without collapsing.

Keeping the core stable is the hardest part
The core is where the most important shared logic lives. If too many special cases are pushed into that layer, the system gradually becomes harder to change. Adding new features becomes risky. Modifying existing ones becomes difficult. A small change can affect many unrelated parts.
That is why, in multi-school systems, the problem is not just data separation. The real challenge is managing differences in how each school operates while keeping the core clean and stable.
Some systems are heavy in logic and hit peak load at very normal times
System pressure does not only come from rare situations. In EdTech, it often comes from very ordinary moments.
At 8 a.m., when teachers mark attendance at the same time. At the beginning of the school year, when parents register for services simultaneously.
A simple action from the user's perspective, entering data and clicking save, can trigger a complex chain of processing. The system may need to check the student's current state, determine the correct form based on school, grade, and program, validate business rules, and store data according to the academic year.
This creates a situation where complex logic and high load happen at the same time. If you optimize performance without understanding the business, you optimize the wrong thing. If you focus only on correctness and ignore load, the system fails exactly when it matters most.

The hardest part is not writing code but understanding the system
When the project started, the hardest part for the team was not writing APIs or building UI. It was understanding the full picture, tracing how data connects, and uncovering business logic scattered across the system.
In many cases, we had to work backward from the running system by reading code, talking to different stakeholders, and testing scenarios ourselves before we could piece together a complete picture.
It often felt like reverse-engineering the business from the system.

The hardest systems are those with complex and constantly changing business logic
After working on this project, one thing became very clear.
The hardest systems are not the ones with complex technology. They are the ones where the business itself is complex and constantly evolving.
In EdTech, the business involves many stakeholders, processes change over time, and each unit operates differently. The code only reflects all of that. If you cannot manage change at the business level, the system will eventually become very hard to scale and maintain.
And this is still just the easier part.
What I have shared so far is only the foundation. The project becomes much harder when requirements keep changing, there is no clear Product Owner, and development starts before the team truly understands the business.
That is usually the point where things begin to go off track, even if the technology was initially done right.
In the next post, I will share one mistake the team made very early on: starting development before truly understanding the business.
If you have worked on multi-tenant systems, systems with many stakeholders, or systems with complex business logic, this will probably feel very familiar.
Follow BiPlus for more stories!