The LMS mistakes that only show up after launch
Role design, video delivery, progress semantics, payments, certificates, and student data. The decisions that determine whether an LMS survives its first cohort.
Zynitex Engineering
Product & engineering notes

The short answer
Most LMS projects fail on the boring parts: role design, video delivery, progress semantics, payment webhooks, certificates, and reporting. Build the course player last. First define who can see, do, pay for, and prove what.
What this note covers
- One “student” role is usually at least three roles.
- Define completion per course, not as one global percentage.
- Serve video through object storage and a CDN, never from your app server.
- Make payment webhooks idempotent and put wallet balances in a ledger.
- Certificates need a verification path, not just a PDF.
On this page(11 sections)
- 01Mistake 1: treating “student” as one role
- 02Mistake 2: the video player is an afterthought
- 03Mistake 3: “completed” is undefined
- 04Mistake 4: certificates anyone can fake
- 05Mistake 5: payment webhooks that enroll twice
- 06Mistake 6: no teacher workflow
- 07Mistake 7: student data treated casually
- 08Mistake 8: launching without support paths
- 09A launch checklist that saves a quarter
- 10What two very different platforms taught us
- 11Build the player last
Every LMS starts with “it’s just courses and videos”. Then a teacher uploads a 2.1 GB file, a parent wants a refund, a student finishes 80% and expects a certificate, and the support inbox becomes a second product.
We’ve built learning platforms with four portals, paid cohorts, career tools, AI interview scoring, and certificate generation. The features that took the longest weren’t the flashy ones. They were permissions, progress, and payment state.
Mistake 1: treating “student” as one role
A school student, a career switcher buying a ₹499 course, a parent checking progress, and a corporate learner are not the same user. If your permission model has only admin, teacher, and student, you’ll bolt on exceptions until nobody can explain who can see what.
| Role | Needs | Common bug |
|---|---|---|
| Guest | Browse, preview a lesson, compare courses | Sees a paid lesson because preview is not scoped |
| Student | Access, progress, certificate, support | Can replay after a refund or expiry |
| Parent | Progress, fees, communication | Sees another child’s record |
| Teacher | Content, roster, Q&A, earnings | Edits a published course without versioning |
| Admin | Refunds, roles, reports, compliance | No audit trail for sensitive actions |
| Support | Reset access, refund lookup | Full database access to fix one ticket |
Draw the matrix before the UI. Every cell is a query and a test. If a role can’t be described in one sentence, it’s probably two roles.
Mistake 2: the video player is an afterthought
Serving a 1.5 GB MP4 from your app server is not a course player. It’s a bandwidth bill with a play button. Use object storage plus a CDN, HLS for adaptive playback, signed URLs, resumable progress, and captions.
I wrote the streaming architecture as a separate piece: AWS HLS streaming architecture. The short version: private bucket, transcoding pipeline, CDN, short-lived access.
Enroll
access
Learn
progress
Practice
feedback
Certify
verify
Every step needs a permission rule and an audit trail — not just a progress bar.
Mistake 3: “completed” is undefined
Is a course complete when the last video ends? When 80% of lessons are viewed? When the quiz is passed? When the assignment is graded? Each answer creates a different database and a different certificate.
- Define completion per course, not as one global percentage.
- Store progress events, not just a percentage. Events can be audited; a number cannot.
- Make playback progress idempotent. A refresh shouldn’t add another thirty seconds.
- Handle timezone changes, multiple devices, and offline viewing.
- Show students exactly what is left, not just a bar.
Note
A backwards progress bar is worse than no progress bar
If a student watches on a phone, then opens a laptop and sees 62% instead of 78%, they stop trusting the platform. Decide how devices reconcile before launch.
Mistake 4: certificates anyone can fake
A certificate is a trust document. If it’s a PNG with a name typed on it, employers can’t verify it and your brand carries the risk.
| Strong certificate | Weak certificate |
|---|---|
| Unique ID that resolves on a public verification page | Only a JPEG shared in a WhatsApp group |
| Course title, version, issuer, and issue date | A generic “certificate of completion” |
| Recipient’s legal name and a stable record | A name typed into a template |
| Revoked/reissued state | No way to invalidate a refund or mistake |
| Download and print-friendly PDF | Screenshot-only output |
The verification page is the feature. The PDF is the souvenir.
Mistake 5: payment webhooks that enroll twice
Razorpay and Stripe retry webhooks. If your handler isn’t idempotent, one payment creates two enrollments, two invoices, or two wallet credits. Use the provider event ID as a unique key, verify the signature, and make the database write transactional.
- Verify the webhook signature before trusting the payload.
- Store the provider event ID with a unique constraint.
- Handle failed payments, delayed authorisation, and refunds.
- Revoke access according to a written refund policy, not an ad-hoc email.
- Model credits as a ledger with entries, not one mutable balance column.
- Reconcile provider settlements against enrollments every week.
ElyteSpark uses a credit wallet for pay-per-session interviews. That kind of balance needs a ledger — debit, credit, reason, reference — not a single number someone can overwrite.
Mistake 6: no teacher workflow
Teachers don’t upload one video. They upload forty, reorder modules, fix a typo in lesson twelve, schedule a drip release, answer questions, and ask why payouts are late.
- Bulk upload with processing status and clear failures.
- Draft, preview, publish, and unpublish without deleting history.
- Version a course so a certificate can reference what was actually completed.
- Drip schedules in the teacher’s timezone.
- A Q&A queue with notification and moderation.
- An earnings report that matches the payment provider.
- A student roster export for offline support.
Mistake 7: student data treated casually
An LMS may handle minors, resumes, interview recordings, payment data, and health information in one product. That’s not a privacy-page problem; it’s a data-map problem.
- Collect only what the learning experience needs.
- Record consent and purpose where required, especially for minors.
- Set retention rules for recordings, resumes, and assessment notes.
- Log admin access to sensitive records.
- Provide export and deletion paths.
- Review vendor terms before sending student data to an AI or analytics tool.
Watch out
Resumes and mock interviews are sensitive
For a career LMS, don’t send a candidate’s resume or interview recording to an AI vendor without a lawful basis, a retention rule, and a clear answer about where it is processed.
Mistake 8: launching without support paths
The top five tickets are predictable: can’t log in, payment succeeded but no access, video won’t play, certificate name is wrong, refund requested. Write the scripts and admin actions before day one.
- A support inbox with order/enrollment lookup.
- One-click resend of access and receipt emails.
- An admin action to fix a certificate name with an audit note.
- A documented refund and access-revocation policy.
- A video-delivery status page for processing failures.
- A status page for platform incidents.
A launch checklist that saves a quarter
- Model every role and permission, including support and parents.
- Define completion per course and test multi-device progress.
- Test video on a mid-range Android phone and a slow connection.
- Verify webhooks, retries, refunds, and duplicate events.
- Generate a certificate and verify it publicly.
- Run a refund and access-revocation drill.
- Test teacher bulk upload and a failed transcode.
- Export the student roster and check the columns.
- Review data retention and AI vendor flows.
- Write the top ten support replies.
- Load-test enrollment and certificate generation.
- Run a small paid cohort before the big launch.
What two very different platforms taught us
Kristive runs four portals — admin, teacher, student, parent — with courses, payments, and certificates. ElyteSpark combines courses with mock interviews, resume checks, job discovery, and credits. The lesson from both: the product is not the video player. The product is the confidence that access, progress, and proof are correct.
Build the player last
Build the course player last. Before it, write the role matrix, the completion rules, the payment state machine, and the certificate verification path. Those four documents will save more time than a prettier dashboard ever will.
Direct answers
Questions people actually ask
Short, checkable answers. Every entry here is also published as structured FAQ data for search and answer engines.
Should we build an LMS or use Moodle?
Use Moodle or a hosted LMS if your needs are standard course delivery, quizzes, and reporting. Build custom when the learning model, career tools, payments, multi-portal roles, or integrations are the reason students choose you. Custom is not automatically better; it is more specific and more expensive to own.
How long does a custom LMS take?
A focused course platform with payments, progress, and certificates can take 8–16 weeks. A multi-portal platform with career tools, AI features, and complex billing can take 3–6 months. The scope of roles and reporting usually drives the timeline more than the video player.
Do certificates need a public verification page?
If employers or institutions are expected to trust the certificate, yes. A unique ID and a public verification page make it checkable. A PDF alone is easy to edit and hard to invalidate.
Can we add AI later?
Yes, if you keep assessment data and content structured. Adding AI to a pile of PDFs and unstructured videos is expensive. Decide early what data you will need to evaluate a learner, and store it with consent.
References
Sources and further reading
- MeitY — Digital Personal Data Protection Act
Data minimisation, consent, and retention context for learner data.
- Razorpay — webhooks
Signature verification, retries, and idempotency.
- W3C — WCAG 2.2 quick reference
Captions, keyboard access, and accessible course interfaces.
- Zynitex — projects
Kristive and ElyteSpark LMS work.
Compliance notes are operational guidance, not legal or tax advice. Rules and thresholds change — confirm your position with a qualified professional.
Written by
Zynitex Engineering
We design and build the systems behind Zynibill, Invoice Studio, and client platforms like Regalia, Kristive, and ElyteSpark. These notes are the things we wish we had read before shipping them.
More about ZynitexKeep reading
Related notes
A sane AWS video streaming architecture for 2026
Upload, transcode, package, deliver, authorise, observe. A practical HLS pipeline with S3, MediaConvert, CloudFront, signed access, and the cost traps.
22 September 2026·12 minEngineeringShipping AI features without shipping a liability
Demos are easy. Production AI needs an eval set, guardrails, privacy rules, cost controls, and a fallback. A field guide from two AI products we shipped.
9 October 2026·10 minBusinessWhen custom software is worth it (and when it’s an expensive hobby)
A decision framework with real economics: status-quo cost, three-year ownership, the 80% rule, hybrids, and the questions to ask before you sign.
15 September 2026·9 min