All projects

Case study

EMIS — Education Management System

Company work (Nnine Solutions) — student records, versioned fees, examinations, marks, PDF/CSV exports — audited writes for trusted operations.

On this page

Overview

EMIS (Education Management Information System) coordinates student records, fee structures, examinations, and reporting. The product goal is trust: finance and academic staff need an audit trail for every change.

Problem

School operations mix high-volume CRUD (enrollment, attendance) with low-volume, high-risk actions (fee overrides, mark entry, result publication). A generic CRUD app would lose the ability to reconstruct who changed what when disputes occur.

Architecture

  • MongoDB for flexible document shapes where modules evolve (exam metadata, attachments) with strict schema validation at the application boundary.
  • Redis for caching hot reference data (academic year config, active terms) and ephemeral session assists.
  • Next.js + React surfaces for staff; Node/Express exposes versioned APIs consumed by both web and eventual mobile clients.
  • Docker + CI for consistent environments between Nepal-based dev machines and cloud deploys.

Schema & auditing

Fee structures are versioned. Adjustments apply to a window; historical invoices remain tied to the snapshot that was active when they were issued.

Audit fields are first-class: actor, timestamp, previous hash or diff pointer—enough to answer compliance questions without drowning in raw JSON.

Exam module

Seat plans, routines, and mark entry share a workflow state machine:

  1. Draft routine
  2. Locked for entry
  3. Review
  4. Published results

Illegal transitions return domain errors, not generic 400s, so the UI can guide recovery.

Reporting

PDF/CSV exports run asynchronously when datasets exceed a threshold size. Staff see job status instead of blocking HTTP requests—better UX and fewer gateway timeouts.

Technical challenges

AreaMitigation
Concurrent mark entryOptimistic locking on marksheet rows; conflicts surfaced to the user
Large CSV exportsStreaming responses + worker queue for big jobs
RBAC sprawlPermission strings namespaced by module; middleware composes checks

Performance

  • Indexes on studentId + academicYear patterns used by every list screen.
  • Aggregation pipelines reviewed with explain before shipping new dashboards.

Tradeoffs

  • Mongo vs Postgres for EMIS: documents win for evolving forms; relational reporting paths sometimes require denormalized read models—document where those exist.

Results (directional)

Replace with your real figures: e.g. report generation time before/after streaming, or reduction in support tickets after audit logs shipped.

Lessons learned

  • Publishing is an event, not a flag flip—wire webhooks or notifications at the state transition, not in ad-hoc controllers.
  • UX for partial saves in mark entry matters more than micro-optimizations on the happy path.