How to build an LMS: a step-by-step guide
To build an LMS you need five things that work together: accounts with server-checked roles, a course hierarchy (course, module, lesson), enrolments, durable progress, and assessments that keep every attempt. Build them in this order: tenant model and roles, then course structure, content player, enrolment, progress, quizzes, certificates, reports, and finally a production hardening pass. A basic single-organisation LMS is roughly 4 to 8 weeks for one experienced developer by our estimate; adding marketplace sales, SCORM or multi-tenant customer academies pushes it into months. Most of that time goes into the parts a demo never shows: progress that survives a second device, and access rules enforced on the server.
This guide draws on the research behind our Learning Management planner, which covers 38 real LMS platforms, and on a build-off in which three coding models built a learning platform from the same planner package. We audited all three, and they are live on the LMS build-off board.
Build, buy or customise?
Building is the right answer less often than people searching "build your own learning management system" hope. Decide this first, because it changes everything below.
| Your situation | Best route | Why |
|---|---|---|
| You need to deliver courses next month and your needs are standard | Buy a hosted platform | Course builder, player, quizzes and reports already work. See cloud-based LMS options. |
| You want control of the data and have someone who can run a server | Self-host an existing LMS | Moodle, Open edX or Chamilo cover most needs for the cost of hosting and admin time. See self-hosted LMS compared. |
| You already run a WordPress site and sell courses from it | Customise WordPress with an LMS plugin | Fastest path for a single creator. Covered below. |
| Your course or organisation model is the problem: unusual completion rules, customer academies, training tied to your own product | Build | When every trial fails the same requirement, that requirement is your reason to build. |
| The LMS is the product you sell | Build | You need to own the data model, the roadmap and the margins. |
A useful test: write down the specific requirement each platform trial failed. If the list is empty or says "I want a nicer dashboard", buy. If it names a rule about who sees what, how completion is earned or how customers are separated, building is defensible.
The build order at a glance
Each step depends on the one before it being real. The "done when" column is a check you can run yourself in a few minutes, in a browser, with two test accounts.
| Step | What you build | Done when… |
|---|---|---|
| 0 | Tenant model, roles and scope | One page says who the customer is (single creator, organisation, school, corporate, marketplace) and which optional branches are in or out. |
| 1 | Accounts, sessions, roles, people admin | A learner pasting an admin URL is refused by the server, and an admin can add or invite a person without touching the database. |
| 2 | Course hierarchy and publishing | Moving a lesson to another module leaves every learner's progress unchanged, and a draft course is unreachable by direct URL. |
| 3 | Content types and the course player | A learner stops a video or PDF, comes back later, and resumes where they left off. |
| 4 | Catalogue and enrolment | An unenrolled learner cannot open a lesson by URL, even though they can see the course page. |
| 5 | Progress and completion | Progress shown in a second browser matches the first, after a hard refresh. |
| 6 | Quizzes with an attempt ledger | Fail a quiz, then pass it: the failed attempt is still on record. |
| 7 | Certificates | A certificate ID verifies, points to the completion that earned it, and shows as revoked once revoked. |
| 8 | Reports and exports | A dashboard number matches a hand count of the rows behind it, and deleting an enrolment changes it. |
| 9 | Hardening and handover | A production build runs from an empty database, isolation passes a two-way test, and the learner screens work on a phone. |
The rest of this guide explains each step and the way it usually goes wrong.
Step 0: decide the tenant model before the schema
The product and tenant model shows up in 30 of 38 platforms in the research, and it decides data isolation. A single creator selling courses, a company training its staff, a school with classes, a corporate academy that also trains customers, and a marketplace with many instructors are five different products. They share a lesson player and very little else.
Pick one, then pick your branches deliberately. The research separates ten families outside the core, among them live sessions, school gradebooks, compliance and recertification, marketplace sales, SCORM/xAPI/LTI, mobile apps and single sign-on. Each brings its own data model: marketplace sales bring payouts, commission, coupons and refunds; SCORM brings a runtime and a packaging format.
The features of a learning management system post has the full counted list. Use it to write the in and out list before anyone opens an editor.
Step 1: accounts, roles and people admin
Roles and permissions appear in 31 of 38 platforms. Administrator, instructor and learner are the core; manager, organisation admin and moderator come with the models that need them.
Two rules matter. Every request is checked on the server: hiding a menu item is a convenience, refusing the request is the control. And roles do not have to be a ladder. The top build in our build-off refused even its own academy administrator the report screens that belonged to the training manager. That is separation of duties, and it is easier to design in now than to retrofit.
Build the people screens in this step too: first-run setup, invite a person, import a CSV, change a role, deactivate someone and end their sessions. This is the thing our build-off missed most completely. When we later tried to turn the two highest-scoring builds into a product, neither had any way to create a user. Every account came from a demo seed script, and in one build that script wiped every table first. Identity management belongs to no single feature, so nobody asked for it, and nobody built it.
Step 2: a real course hierarchy
A course builder with a module, section and lesson tree appears in 32 of 38 platforms.
The design decision underneath: progress is keyed to the lesson's own ID, never to its position in a list. A flat list with an ordering number looks identical to a tree until the first reorganisation. Then every learner who completed "lesson 4" is credited with whatever lesson 4 is now.
Give courses and lessons explicit states (draft, published, archived) and make drafts invisible on the server, not just unlinked.
Step 3: content types and the player
Lesson and content types are the most common capability in the set, in 33 of 38 platforms: video, text, files and PDFs, audio, embeds, HTML pages.
Pick the two or three you actually need. Each type you keep needs a renderer that records consumption and a resume point. The player is the screen learners live in: outline, current lesson, progress and an obvious next action, and it has to work at phone width.
Step 4: catalogue and enrolment
A course catalogue appears in 31 of 38 platforms, in public, private, branch-specific and marketplace variants. Enrolment is the record that grants access, whether it came from self-enrolment, an assignment by a manager, a request, or a purchase.
Keep one enrolment model and treat those routes as different ways of creating it. Check access against it on every lesson request. The common failure is a front-end filter: the course card is hidden, but the lesson URL still opens.
Step 5: progress and completion
Learner progress tracking appears in 32 of 38 platforms: lesson completion, percentage, resume point and completion date.
This is the defining defect of prompt-built learning platforms. Progress stored in component state works perfectly in a demo, because a demo never involves a second session. Write a durable record per learner per lesson on the server, and compute the course percentage from those records. Keep completion separate from passing: a learner can complete a course and fail its assessment, and your reports need to tell those apart.
Step 6: quizzes with an attempt ledger
Assessments appear in 29 of 38 platforms. Even the lightest quiz needs an attempt record: answers, score, timestamp, feedback. A score field on the enrolment row, overwritten on each attempt, cannot answer "how many attempts did this take?" or "which question does everyone get wrong?".
Decide retry rules and result release here. When we later drove a learner through the top build by hand, quiz results waited for instructor release, but the instructor's home screen showed nothing awaiting it; the queue sat deeper in the course settings. A hidden queue is a blocked learner.
Step 7: certificates
A certificate should reference the completion record that earned it, carry an ID that can be verified later, and support expiry and revocation if you sell compliance training. The research tags certificates as a common feature rather than core, so check whether your buyers need them before you build a designer for them.
Builds differ on who issues the certificate. In our build-off, Grok 4.5's build issued one automatically on completion; GPT-5.6 Sol's build had a training manager issue it against a stated rule. Both are valid. Pick one on purpose.
Step 8: reports and exports
Reports and analytics appear in 31 of 38 platforms. Every figure should be derived at read time from enrolment, progress and attempt records. Counters incremented as things happen are fast to build and drift the first time something is edited, merged or deleted.
Exports should contain the filtered source rows, not a summary of the screen.
Step 9: hardening and handover
Run the production build, not the development server. One of three builds in our build-off would not compile for production: three small errors that never appear in development, while its own test suite reported everything as passing.
Then prove isolation in both directions, with a control: another organisation's record is refused, and the owner does see it. A refusal for everyone only proves an empty database. Finally, start the app on an empty database and walk through setup as a stranger would.
The data model in brief
The core tables should exist before the screens.
| Entity | Holds | The rule that matters |
|---|---|---|
| Organisation / academy | Tenant boundary, branding | Every query carries it if you have more than one |
| User, membership | Person, role per organisation, active flag | Deactivation ends live sessions |
| Course, module, lesson | The hierarchy, state, content type | Progress keys to lesson ID, not position |
| Enrolment | Who has access to what, how they got it | Checked on every lesson request |
| Progress event | Learner, lesson, status, timestamp | Server-side, append rather than overwrite |
| Quiz, question, attempt, answer | Assessments and every attempt | No attempt is ever overwritten |
| Certificate | Completion it came from, ID, expiry, revoked state | Verifiable after the fact |
| Audit log | Who changed an enrolment, grade, certificate or role | Required once anyone disputes a record |
Build it with an AI coding agent
A coding agent can produce every screen in this guide in an afternoon. The problem is underneath. Unprompted, it stores content as a flat list, keeps progress in the browser, writes quiz scores without attempt records, and computes reports from counters. Every one of those passes a demo.
What to hand the agent. Not a prompt, a specification: the tenant model, the roles and what each may do, the branches you chose and the ones you excluded, the data model rules from the table above, and the done-when checks as acceptance criteria. The planner produces exactly that after a discovery session with you. A Basic build is 7 to 9 steps, a Moderate one 10 to 14, and each step carries handover gates: screenshots, persistence after refresh and a second session, role probes and export checks.
What to check after each step. Run the done-when check for that step yourself, in a browser. Then:
- Request a restricted screen by URL as the weakest role. Check the response body, not only the status code.
- When an ID-based request "succeeds" for the wrong user, compare the bodies across two accounts before calling it a leak. In our audit, one endpoint returned 200 to a learner asking for another learner's records, but the body held only the learner's own: the server ignored the ID and scoped to the session.
- Re-run the agent's own tests yourself. Do not accept "all tests pass" as evidence.
What our build-off actually caught. Three models, one planner, scores as found at audit:
| Model | Score | What it got right | What it got wrong |
|---|---|---|---|
| GPT-5.6 Sol | 97 | Customer organisations invisible to each other in both directions; admin refused the training manager's screens; sign-out really ended the session; the only build that compiled for production first time | Password hashing weaker than current guidance; the full enrol-to-certificate journey was not driven in the audit |
| Grok 4.5 | 96 | Every feature driven end to end: authoring to publishing, prerequisite locks, quizzes marked correctly, automatic certificate | Would not compile for production; its own tests said they passed |
| Gemini 3.6 Flash | 68 | Correct per-learner access rules, verified with a control | Those rules sat on a session token a visitor could forge; the demo catalogue was 83% leftover test data |
Gemini 3.6 Flash is a small, fast-tier model, so its score is not directly comparable to the other two. Later fixes are noted on the board but do not change the scores. You can sign into all three from the LMS demos and compare them yourself.
All three had the same planner, so the specification was not the difference. What separated them were defects that only show up when someone checks: a token nobody tried to forge, a production build nobody ran. That is why the done-when column above is the most important table in this guide.
Custom LMS development: hire, build or buy?
If you searched for custom LMS development or LMS development services, you are probably deciding whether to pay a company to build it.
What a custom LMS build involves. Discovery and the scope decisions from Step 0, the nine build steps above, data migration from whatever you use now, design, hosting, and then maintenance: framework security updates, backups, browser changes and the feature requests that start the week after launch. Migration and maintenance are where budgets slip.
Rough effort ranges. These are our estimates, not quotes and not market data. They assume one experienced full-stack developer, a mainstream web framework with an existing authentication library, no custom design system, and a single organisation unless stated.
| Scope | What is in it | Rough effort |
|---|---|---|
| Basic | Three roles, people admin, course hierarchy, two content types, enrolment, durable progress, quizzes with attempts, certificates, derived reports | 4 to 8 weeks |
| Moderate | Basic plus one or two branches, for example assignments with grading, groups and learning paths, or live sessions with attendance | 2 to 4 months |
| Advanced | Multi-tenant customer academies, marketplace payments and payouts, a SCORM or xAPI runtime, single sign-on, or native mobile apps | 6 months or more, usually a team |
Multiply by the rate you are quoted to sanity-check a proposal. If a proposal for the advanced row is priced like the basic one, ask which branches it quietly left out.
What to ask an LMS development company.
- Who owns the source code and the data? Can I export course content and learner records (progress, attempts, certificates) in a documented format?
- Show me progress persisting after a refresh and on a second device, in your previous work.
- How do you prove one customer organisation cannot read another's records? Ask for the test, including the control where the owner can see their own record.
- Is SCORM support a runtime that records results, or a launcher that opens the file? Those are very different amounts of work.
- How are users created, invited, imported and deactivated? Watch for answers that only describe login.
- Will you hand over a production build that starts on an empty database, plus a test suite I can re-run?
- Who applies framework security updates after launch, and what does that cost per year?
Where a coding agent plus a planner fits. This is a third option between hiring and buying: you, or one developer, direct an agent with a full specification. The agent's build time is not the constraint. Your review time is. On a basic build, plan on several days of your own checking across the steps, by our estimate. That is the honest trade: you save most of the development cost, and you take on the verification an agency would otherwise do (or claim to do). If nobody on your side can run the checks in this guide, hire.
We are also preparing a self-hosted LMS of our own, in early access. It started as the Grok 4.5 build from the build-off; we then added the people admin, first-run setup, email and Docker packaging the build lacked. It is not for sale yet, it does not yet import SCORM packages or support single sign-on, and its product page lists those limits plainly. It is an option if you want an LMS on your own server without running Moodle, not a replacement for a custom build.
How to create an LMS in WordPress
If you already run a WordPress site, an LMS plugin is the fastest way to create your own LMS. The plugins below are listed on their official pages; checked on 19 October 2026.
| Plugin | Model | Notes |
|---|---|---|
| LearnDash | Paid only | Pro $399/year, Elite $599/year; a 48-hour free trial, no free plan |
| Tutor LMS | Free core, paid Pro | Certificates, reports and content drip are among the premium add-ons |
| LifterLMS | Free core, paid add-ons and bundles | Core has no limits on courses or enrolments |
| LearnPress | Free core, paid add-ons | Certificates and gradebook are premium add-ons |
| Sensei LMS | Free core, paid Sensei Pro | Made by Automattic |
The honest trade-offs. A plugin gives you a working course builder and player in a day. It also ties your learner records to WordPress and its database, and a free core often moves certificates or reporting into paid add-ons, so price the add-ons you need, not the core. Run the done-when checks from this guide on your trial site anyway: progress on a second device, a failed quiz attempt still on record, a draft lesson by direct URL.
The mistakes that show up every time
No way to add people. Progress in the browser. Reordering that corrupts completion. Overwritten quiz scores. Counters as reports. Access by hidden buttons. Isolation tested without a control. A production build nobody ran. A catalogue that is mostly test data. Each one passes a demo.
Common questions
How much does it cost and how long does it take to build an LMS?
It depends on scope more than technology. By our rough estimate, a basic single-organisation LMS is 4 to 8 weeks for one experienced developer, and an advanced one with multi-tenancy, payments or SCORM is six months or more. Add hosting, migration and maintenance. With a coding agent the build is fast, but checking it properly still takes days. If your needs are standard, a hosted or self-hosted platform will cost less for years.
What tech stack should I use to build an LMS?
Any mainstream web stack with a relational database works. The two top builds in our build-off used different stacks: Grok 4.5 used Next.js with Prisma and SQLite, and GPT-5.6 Sol used Cloudflare Workers with a D1 database. Their scores were one point apart. The data model and the server-side checks matter far more than the framework.
Can I create my own LMS with no code?
Yes, if your needs are standard: a hosted platform or a WordPress plugin is effectively a no-code LMS. No-code app builders can assemble the screens, but durable progress, attempt records and server-enforced roles are exactly the parts that are hard to get right without code, so test those first.
Is it better to build or buy an LMS?
Buy unless a specific requirement fails every platform you trial, or the LMS is the product you sell. Write the failed requirement down; it becomes the first line of your build spec.
The shortcut
Everything in this guide is in the Learning Management planner: the 38-platform feature inventory with counts, the ten branch families as explicit choices, the build steps, and handover gates that ask for proof rather than a claim. Point your coding agent at it, answer the discovery questions, and it writes the spec before it writes code.
Three models built from that same package. The results, 97, 96 and 68, and the findings behind each are on the build-off board. Open the top two side by side: the same brief, two different stacks, and both of them correct on the checks in this guide. Then try the third, and see what one forgeable token does to an otherwise correct set of rules.