Canvas and Anthology's Blackboard Learn are vendor-hosted SaaS, so the vendor scales the platform for exam peaks and you rely on their contract: both are documented with a 99.9% availability SLA. Moodle is self-hosted or managed, so exam-day capacity is something you engineer: shared Redis sessions and caches, PHP-FPM sized to your CPU, a database that fits in memory, Moodle 5.0's pre-created quiz attempts, and a load test that simulates everyone pressing Start in the same 30 seconds. The synchronised start, not total users, is what breaks exams.
Key takeaways
- An exam is not normal traffic. Hundreds or thousands of students log in, start and submit inside a few minutes, so the peak is many times the daily average.
- Canvas and Blackboard Learn SaaS scale on the vendor's cloud. You don't tune them; you check their SLA, their status history and how they handle your exam calendar.
- Moodle gives you control and ownership, which means exam-day capacity is your job or your hosting partner's job.
- Size Moodle by CPU against simultaneous exam starts, not by RAM per registered user.
- Moodle 5.0 added pre-created quiz attempts, which moves the heaviest part of 'Start attempt' to a scheduled task before the exam opens.
- A 99.9% uptime SLA measures availability, not speed under load. A slow exam can still be 'up'.
- Load test the synchronised start on a staging copy, never on production.
Why an exam window is different from a normal teaching day
On a normal day an LMS sees traffic spread across hours. Learners drift in, watch a video, post in a forum and leave. Capacity planning built on that pattern looks comfortable on paper.
A timed online exam compresses the same population into minutes, and it does so three times:
- The login wave. Everyone authenticates in the 10 to 15 minutes before the paper opens. Single sign-on helps the LMS but moves part of the spike to your identity provider.
- The start spike. The quiz opens at 10:00 and most students press Start inside the first minute. Creating an attempt means writing rows for every question slot, so this is the most expensive moment of the exam.
- The submit spike. In Moodle, the default 'When time expires' behaviour is that open attempts are submitted automatically. If everyone started together, the timer runs out for everyone together, and grading work lands in one burst.
How compressed is the start? In a 2025 Moodle community discussion on realistic concurrency for quizzes, one administrator reported that in roughly one in ten of their exams with 200 to 1,500 participants, more than two-thirds of students started within 30 seconds. In his JMeter tests the start produced "a very sharp, short CPU spike" that was out of proportion to steady-state load and settled within about two minutes. That is one site's data, not a benchmark, but it matches what every exam-day operator sees: the synchronised start, not the total number of users, is the number to plan for.
How Canvas, Anthology and Moodle handle the peak
The three platforms answer the same question in two different ways. Canvas and Blackboard Learn SaaS are run by their vendors, on the vendors' cloud. Moodle is open source: you, your IT team or a hosting partner run it, and the capacity is whatever you build.
| Canvas (Instructure) | Blackboard Learn SaaS (Anthology) | Moodle (self-hosted or managed) | |
|---|---|---|---|
| Who scales it | Instructure. Internet2's NET+ Canvas page says it runs on Amazon EC2 and "provisions resources automatically" during peak usage. | Anthology. Its Learn SaaS overview lists "scalability & elasticity" as a SaaS benefit. | You or your hosting partner: servers, PHP workers, database, cache, CDN. |
| Availability commitment | 99.9% uptime guarantee in the Internet2 contract. | 99.9% availability SLA on both the Plus and Advantage tiers, per Anthology's overview. | Whatever your host contracts for. Moodle itself carries no SLA. |
| What you can tune for exams | Exam settings and scheduling only; infrastructure is not yours to change. | Exam settings and scheduling only. | Everything: session store, caches, worker counts, database, pre-created attempts, maintenance windows. |
| Main risk on exam day | A platform-wide incident you can't influence, shared with every other tenant. | The same: shared infrastructure, vendor-controlled response. | Under-sized or untested infrastructure, and nobody watching it at 10:00. |
Neither model is automatically safer. SaaS removes the engineering work and replaces it with dependency: if the platform has a bad morning, your exam has a bad morning, and your only lever is the support ticket. Moodle puts the lever in your hands, which is exactly why institutions that run high-stakes exams on it treat exam day as an engineering event rather than a calendar entry.
What "99.9% uptime" actually allows
99.9% of a 30-day month is about 43 minutes of permitted downtime; over a year it is roughly 8.8 hours. Two more things matter more than the number itself:
- Availability is not performance. A platform that answers every request in eight seconds is "up". Ask any vendor how they measure availability and whether response time is part of it.
- Timing matters more than totals. Forty minutes of downtime at 03:00 on a Sunday is invisible. Ten minutes at 10:00 on the first day of finals is an incident report. Ask whether the vendor honours exam blackout windows for maintenance, and look at their public status history for your exam season last year.
The Moodle exam-day playbook
If you run Moodle, these are the levers that decide whether 10:00 is a non-event. Most are in Moodle's own documentation; the order is roughly the order of impact.
1. Pre-create quiz attempts (Moodle 5.0 and later)
Moodle 5.0 added a way to take the most expensive work out of the start spike. Under Site administration > Plugins > Activity modules > Quiz > General settings, set a Pre-create period in hours. Then, in a quiz's Timing settings (once 'Open the quiz' is set), enable Pre-create attempts. A scheduled task, which runs hourly by default, builds the attempts in advance; when a student presses Start, Moodle only has to flip the attempt's state and record the start time. Moodle's documentation recommends keeping the period short, because once attempts exist the quiz's questions can no longer be edited.
2. Move sessions and caches off the disk
New Moodle installs store sessions in files by default. That is fine on one server and wrong for a cluster: Moodle's session documentation says cluster nodes "must use shared session storage". Redis is the usual choice for both sessions and the Moodle Universal Cache (MUC), and Moodle's performance recommendations note that caching "can default to disk for a lot of the different caches which is rather slow overall". Keep sessions and MUC on separate Redis instances or databases so one can't starve the other.
// config.php - Redis sessions (cluster-safe) $CFG->session_handler_class = '\core\session\redis'; $CFG->session_redis_host = '10.0.0.20'; $CFG->session_redis_port = 6379; $CFG->session_redis_database = 0; $CFG->session_redis_prefix = 'exam_sess_'; $CFG->session_redis_acquire_lock_timeout = 120; $CFG->session_redis_lock_expire = 7200;
We cover MUC store mapping in detail in Moodle caching and CDN: Redis, MUC and sessions.
3. Size PHP workers to the CPU, not to the user count
Moodle's performance page warns that Moodle "can easily use up to 100MB per process" and gives a conservative worker limit of available memory times 80%, divided by the memory one process uses. That stops the server swapping. But in exam tests the bottleneck is usually CPU: the administrator quoted above found RAM "not the bottleneck" with PHP-FPM and OPcache, and sized by vCPUs against concurrent starts. Use the memory formula as a ceiling and CPU headroom as the real target.
; php-fpm pool - example for a 16 vCPU / 32 GB app node pm = static pm.max_children = 200 ; ~ (32 GB x 0.8) / ~120 MB, then load-test it pm.max_requests = 1000 request_terminate_timeout = 300 ; php.ini opcache.enable = 1 opcache.memory_consumption = 256 opcache.max_accelerated_files = 16000 opcache.validate_timestamps = 0 ; clear opcache on deploy
pm = static avoids forking new workers in the middle of the spike. The numbers are a starting point for a load test, not a recommendation for your hardware.
4. Keep the database in memory, and off the critical path
On a dedicated MySQL or MariaDB server, Moodle's guidance is an InnoDB buffer pool of about 80% of RAM, so the working set never has to come off disk. For very large sites, Moodle notes that read replicas can take "as much as 80-90% of the DB load" away from the primary. On PostgreSQL, keep autovacuum on.
5. Quiet the background during the window
Cron does real work in Moodle: backups, analytics, search indexing, notifications. Run it from the CLI, and reschedule heavy scheduled tasks (course backups, analytics, global search indexing) out of exam hours. Keep the pre-create task and the quiz's overdue-attempt handling running.
6. Push static files and media to a CDN
Every question page pulls CSS, JavaScript, fonts and images. Serving those from a CDN leaves the app servers to do what only they can do: render questions and save answers.
7. Shape the peak with exam settings
- Stagger large cohorts by 5 to 10 minutes using group or user overrides on the quiz.
- Use the grace period option ('There is a grace period when open attempts can be submitted, but no more questions answered') so a slow final save doesn't cost a student their attempt.
- Show one or a few questions per page rather than the whole paper on one page; each save is smaller.
- If you proctor, include the proctoring tool's traffic in your load test. Webcam snapshots and browser checks add requests at exactly the same moments.
For the full server-sizing picture see Moodle hosting and server architecture: scaling 100 to 10,000 users and tuning PHP, OPcache and MySQL for Moodle.
- 1T-21 days: build a staging copy
Clone production to staging on the same instance sizes. A load test on smaller hardware tells you nothing about exam day.
- 2T-14 days: script the real exam flow
Use JMeter. Moodle ships a starting point under Site administration > Development > Make JMeter test plan (developer debugging only, never on a live site). Extend it to log in, open the quiz, start, answer every page and submit.
- 3T-14 days: simulate the synchronised start
Ramp most virtual users into Start inside 30 to 60 seconds. A gentle ramp over 10 minutes produces a reassuring and useless result.
- 4T-10 days: fix, then test again
Watch CPU, PHP-FPM queue, database connections, slow queries and Redis memory. Change one thing at a time and re-run.
- 5T-7 days: freeze
No plugin installs, upgrades or theme changes until the exam window closes. Confirm the maintenance calendar with your host.
- 6T-2 days: switch on pre-created attempts
Enable Pre-create attempts on the exam quizzes (Moodle 5.0+) and confirm the scheduled task is running. Questions are locked once attempts exist.
- 7Exam day, T-60 min: warm and watch
Warm caches by loading the course and quiz pages, pause heavy scheduled tasks, and have someone watching dashboards from the login wave until the last submission.
- 8T+1 day: review
Compare the real peak with the test peak. That ratio is what you plan the next exam season with.
"Which LMS can host 50,000 concurrent users with a 99.9% SLA?"
This question comes up in RFPs and AI-assistant prompts alike, and it is usually the wrong shape. Any of the three platforms can serve very large institutions. The questions that separate vendors are narrower:
- Concurrent what? 50,000 people logged in across a day is a different system from 50,000 pressing Start in the same minute. Ask for the second number.
- Has it been tested? Ask for a load-test report on a comparable synchronised start, not a marketing figure.
- What does the SLA measure? Availability only, or response time too? Monthly or yearly? What are the credits, and do they matter to you as much as a failed exam does?
- Who is watching at 10:00? Is there a named engineer on call for your exam window, or a general ticket queue?
- Video is a separate load. If the requirement includes recorded lectures, serve video from a streaming CDN, not from the LMS servers, whatever platform you choose.
Running exams on Moodle or edzlms?
edzlms is built on Moodle, and EDZLMS runs managed Moodle hosting with exam-window planning: pre-exam load testing on a staging copy, Redis sessions and caches, PHP-FPM sized to your exam starts, a change freeze, and someone watching the dashboards while your students sit the paper.
Frequently asked questions
How do Canvas, Anthology and Moodle handle large concurrent-user loads during peak exam windows?
Canvas and Blackboard Learn SaaS are hosted by their vendors on cloud infrastructure that the vendor scales; both are documented with a 99.9% availability SLA, and the institution's role is to check the contract and the status history. Moodle is self-hosted or managed, so the institution or its hosting partner engineers for the peak with shared Redis sessions and caches, CPU-sized PHP workers, an in-memory database, pre-created quiz attempts in Moodle 5.0 and later, and a load test of the synchronised start.
How many concurrent users can Moodle handle?
There is no fixed limit; it depends on the infrastructure. What matters for exams is how many students start an attempt in the same minute. Moodle sites run exams with thousands of simultaneous students on clustered app servers with shared Redis sessions, a separate database server and a CDN. Load-test your own exam flow to get your number.
What does a 99.9% uptime SLA allow?
About 43 minutes of downtime in a 30-day month, or roughly 8.8 hours a year. It measures availability, not speed, so a slow but responding platform usually still counts as up. Ask when downtime is allowed to happen and whether exam windows are protected.
What is pre-create quiz attempts in Moodle?
A Moodle 5.0 feature that builds quiz attempts in advance with a scheduled task, so that pressing Start only changes the attempt's state and start time. It reduces the load spike when many students start at once. Set the Pre-create period in the quiz plugin settings and enable Pre-create attempts in each quiz's Timing settings.
How do I load test Moodle before an exam?
Use JMeter against a staging copy built on production-sized servers. Moodle's Make JMeter test plan tool, available in developer debugging mode, gives a starting script. Extend it to log in, start the quiz, answer every page and submit, and push most virtual users into Start within 30 to 60 seconds. Never run it against production.
Should we stagger exam start times?
For large cohorts, yes. Starting groups 5 to 10 minutes apart with quiz overrides flattens both the start spike and the automatic-submission spike at the end, with little effect on the exam itself.
Is SaaS safer than self-hosted Moodle for high-stakes exams?
Not automatically. SaaS removes the engineering work but leaves you dependent on the vendor during an incident. Self-hosted or managed Moodle gives you control of capacity, maintenance timing and monitoring, which is why it suits institutions willing to treat exam day as an engineering event.
Sources
- Moodle Docs: Quiz settings (5.0), timing and 'When time expires'.
- Moodle Docs: Quiz administration settings (5.0), pre-create quiz attempts; and MDL-68806.
- Moodle Docs: Session handling.
- Moodle Docs: Performance recommendations.
- Moodle Docs: JMeter test plan generator.
- Moodle.org forum: Realistic concurrent user estimates for Moodle with SCORM + quizzes?
- Internet2: NET+ Canvas, hosting and uptime guarantee.
- Anthology: Blackboard Learn SaaS overview (PDF), availability SLA.
Platform details were checked against these sources on 11 October 2026. Vendor terms change; confirm the current SLA in your own contract.
Planning an exam season on Moodle?
We'll walk through your exam calendar, current hosting and the peak you need to survive, and show how edzlms and our managed hosting handle it.