EduNexus
A multi-role institute management platform covering attendance, finance, academics and operations — built as a tested, queue-backed system with realtime delivery and CI, not a CRUD app.
- Node.js
- Express
- MongoDB
- Redis
- Socket.IO
- Jest
System schematic
Scope note — This project was built in a team context. The description above covers the system and its architecture; it is not a claim of sole authorship. A precise breakdown of individual contribution is available on request.
Overview
EduNexus is an institute management platform spanning attendance, fees and finance, exams and results, timetables, transport, hostel, library, inventory, HR and payroll, complaints and messaging. It is included here not for its feature count but for its engineering shape: a modular Express service with more than forty domain controllers, background queues, realtime and push delivery, sixteen integration test suites running against an in-memory database, and continuous integration that builds the frontend and runs the backend suite on every push.
Problem
Institutions run on a patchwork of spreadsheets, paper registers and messaging groups. The data exists but is not connected, so every question that crosses two domains — has this student's fee cleared before results are released? — becomes manual work.
The engineering problem is harder than the domain problem. A system like this has many roles with genuinely different views of the same records, work that must not happen inside a request (statement generation, bulk exports, monthly billing), and information that has to reach people who are not currently looking at the application.
Business context
Administrative software is judged on trust rather than features. If a fee ledger disagrees with a receipt, or an attendance record silently changes, adoption stops immediately and does not restart.
That pushes the engineering priorities somewhere specific: validated inputs at the boundary, authorisation that is enforced centrally rather than per handler, and a test suite that can prove the money-and-records paths still behave after a change.
Solution
The API is decomposed by domain — attendance, fees, exams, results, timetables, transport, hostel, library, inventory, HR, complaints, messaging — with each domain owning its controller, routes and models. Cross-cutting concerns live in middleware rather than being repeated per route.
Requests are validated with Joi before reaching a controller, sanitised against operator injection, rate limited, and passed through JWT authentication and role middleware. A handler can assume its input is well-formed and its caller is authorised.
Anything slow or scheduled is moved off the request path onto Bull queues backed by Redis: exports, document generation, notification fan-out, and a monthly fee scheduler that bills on its own clock rather than on a user's click.
Delivery is two-tier. Socket.IO pushes to connected clients; Firebase Cloud Messaging reaches people who are not. Email uses a single shared mail service so every module sends through one configured transport instead of each inventing its own.
Architecture
Clients
Web application
Role-scoped dashboards
Mobile / push targets
FCM device tokens
Edge
Helmet + CORS
Transport hardening
Rate limiting
express-rate-limit
Sanitisation
express-mongo-sanitize
Access
JWT authentication
Signed, expiring tokens
Role middleware
Central RBAC
Joi validation
Schema per endpoint
Domain
Academics
Attendance · exams · results · timetables
Finance
Fees · salary · ledger
Operations
Transport · hostel · library · inventory
Async
Bull queues
Redis-backed workers
Scheduled jobs
Monthly fee scheduler
Exports
PDFKit · CSV · archiver
Delivery
Socket.IO
Connected clients
FCM push
Disconnected clients
Mail service
Single shared transport
Persistence
MongoDB
Domain records
Redis
Queues + ephemeral state
Cloudinary
Documents and media
Implementation
Sixteen integration suites exercise auth, attendance, fees, exams, results, salary, staff attendance, timetables, transport, homework, complaints, notification attachments, CSV export and report-card export. They run against mongodb-memory-server, so the suite needs no external database and behaves identically on a laptop and in CI.
GitHub Actions runs two jobs on every push and pull request: a frontend production build and the backend test suite with --runInBand. A change that breaks either is visible before it is merged rather than after it is deployed.
A pre-start integrity check runs before both dev and start, so the process refuses to boot in a misconfigured state instead of failing later in a way that is harder to diagnose.
Data migrations and seeds are explicit, versioned scripts — demo seeding, username backfill, transport and timetable model migrations — rather than ad-hoc database edits.
Engineering challenges
Many roles, one set of records
Administrators, teachers, students and parents see overlapping but non-identical views of the same data. Encoding that per handler guarantees drift and eventually a leak. Authorisation is therefore expressed once in middleware and applied uniformly, so adding a domain does not mean re-deriving the access rules.
Work that must not happen in a request
Report cards, ledger exports and monthly billing are slow and must survive a closed browser tab. Moving them onto Redis-backed queues keeps request latency bounded and makes retries a property of the queue rather than something each caller reimplements.
Testing a system with this much surface area
Unit tests over forty controllers would prove little about whether the system works. Integration tests against a real Mongo API surface, backed by an in-memory server, test the paths that actually matter — request in, authorisation applied, database mutated, response out — without requiring shared infrastructure.
Key decisions
- Integration tests over unit tests
- The risk in this system lives at the seams: authorisation, validation and persistence interacting. Testing there catches the failures that matter; mocking them away hides exactly the bugs worth finding.
- Queues rather than longer request timeouts
- Slow work in a request couples a user's connection to a job's duration. A queue decouples them and gives retries, backoff and observability for free.
- A single shared mail service
- Every module needs to send email. Left to themselves they would each configure a transport, and provider changes would then require touching every module.
- Fail fast on misconfiguration
- A pre-start integrity check turns a class of silent runtime failures into a loud startup failure, which is far cheaper to diagnose.
Results
No production metrics are published for this project yet. I would rather show nothing here than a number I cannot stand behind — the architecture and the decisions above are the part worth reviewing.
Technology
Backend
- Node.js
- Express
- REST API
- 40+ domain controllers
Data
- MongoDB
- Mongoose
- Redis
Async
- Bull queues
- Scheduled jobs
- Socket.IO
- Firebase Cloud Messaging
Security
- JWT
- Helmet
- express-rate-limit
- express-mongo-sanitize
- Joi validation
Output
- PDFKit
- CSV export
- Cloudinary
- Nodemailer / Resend
Quality
- Jest
- Supertest
- mongodb-memory-server
- GitHub Actions CI
Links
Contact
Have an AI product or workflow worth building?
Send me the problem — not the spec. If it’s a fit I’ll tell you how I’d approach it; if it isn’t, I’ll say so.
Faisalabad, Pakistan · PKT (UTC+5) · Working remotely