E
edzlearn
Products
AI Roleplay (Gelato)
Services
Solutions
Resources
About
Watch DemoBook a Demo
edzlearn

The AI learning OS for teams that need to perform — not just complete a quiz. Author with AI, assess with AI, practise with AI.

Product
  • LMS Platform
  • AI Course Builder
  • AI Roleplay
  • Study with AI
  • Onboarding AI
Services
  • LMS Development
  • Content Development
  • DevOps Support
  • SCORM Analyser
Solutions
  • LMS Use Cases
  • Roleplay Use Cases
  • Corporate & Enterprise
  • Academics
Company
  • About Us
  • Security
  • Blog
  • Case Studies
  • Glossary
  • Contact
AI Roleplay (Gelato)
  • AI Tutor
  • Mock Interview
  • Corporate Experiential Learning
  • Overview
© 2026 EdzLMS · All rights reserved.
PrivacyTermsISO 9001 · ISO 27001
Home/Blog/Moodle

Moodle Hosting & Server Architecture: Scaling 100 to 10,000 Users (2026)

How to size and architect Moodle hosting by peak concurrent users — from a single tuned server to a high-availability cluster for 10,000+ — with sizing tables, real config snippets and the scaling mistakes to avoid. Spoke 1 of our Moodle performance series.

MJ
Mihir Jana
·5 July 2026·11 min read
MOODLE
⚡ Quick answer

Size Moodle hosting by concurrent (peak) users, not total accounts — peak concurrency is usually only 10–25% of your total user base. A single well-tuned server (4–8 vCPU, 16 GB RAM) comfortably serves up to roughly 100–200 concurrent users. Beyond that you scale in stages: first split the database and cache onto their own servers, then add multiple load-balanced application nodes with shared moodledata for thousands of concurrent users, and finally a high-availability setup with database replicas and object storage for 10,000+. The database is almost always the first bottleneck. edzlms runs Moodle on this exact staged architecture as a managed, performance-tuned service, sized to your real concurrency.

10–25%
of total users are typically online at peak — the number that actually sizes your servers
100–200
concurrent users a single well-tuned Moodle server can handle
#1
bottleneck as you scale is almost always the database, not the web tier
+1s
of page latency measurably raises drop-off and lowers course completion

Key takeaways

  • Capacity planning starts with peak CONCURRENT users, not total enrolments — estimate concurrency at 10–25% of your active base.
  • Scale in four stages: single server → split DB + cache → horizontal app nodes → full high availability. Don't over-build before you need to.
  • The database is the first thing to buckle under load; give it dedicated resources before you add web nodes.
  • The moment you run more than one application node, moodledata and sessions must be shared (object storage / NFS + Redis) or logins and files break.
  • Slow Moodle is not just an IT issue — latency drives learner drop-off and lower completion, so architecture is a learning-outcomes decision.
  • This is Spoke 1 of the Moodle performance series; deep PHP/DB and caching tuning are covered in the linked pillar and companion posts.

This is part of our Moodle Performance Optimization Guide (2026) — the pillar covers all five performance levers; this spoke goes deep on the first one: hosting and server architecture.

Size by concurrent users, not total accounts

The most common Moodle sizing mistake is planning around total enrolments. A platform with 10,000 registered learners does not need to serve 10,000 simultaneous requests — it needs to serve however many are online at the same moment during your busiest period. That peak concurrency is the number that sizes your hardware, and it is usually a small fraction of the total.

Usage patternPeak concurrency (of total users)Example
Self-paced, spread across the day~5–10%10,000 users → ~500–1,000 concurrent
Corporate training, business hours~10–20%5,000 users → ~500–1,000 concurrent
Scheduled exams / live cohorts~25–40%+2,000 users → ~500–800 concurrent spikes

If you run timed assessments or instructor-led sessions where everyone logs in at once, plan for the spike, not the average — those synchronised events are what bring under-provisioned servers down.

The four architecture stages

Moodle scales horizontally very well, but you should grow into each stage rather than over-engineering on day one. Here is the progression and roughly where each stage tops out:

StagePeak concurrentApprox. total usersArchitecture
1. Single serverup to ~100–200up to ~1,000All-in-one: web + PHP-FPM + DB + Redis + moodledata on one box
2. Split services~200–500~1,000–5,000Dedicated DB server + Redis server; app stays separate
3. Horizontal scale~500–2,000~5,000–20,000Load balancer + multiple app nodes, shared moodledata, DB read replicas
4. High availability2,000+20,000+Multi-AZ HA, DB primary+replicas, object storage, autoscaling, CDN

The ranges overlap because tuning matters as much as tier — a well-configured single server can beat a poorly-tuned split setup. Treat these as planning guides, then load-test against your real content and concurrency.

Stage 1 — the single well-tuned server

Most organisations start (and many happily stay) here. One server runs the web server, PHP-FPM, the database, Redis and the moodledata directory. The goal is to right-size CPU and RAM, then make sure PHP-FPM and the database buffer pool are tuned to actually use that RAM.

Peak concurrentvCPURAMNotes
up to ~502–48 GBSmall team / pilot
~50–100416 GBTune OPcache + PHP-FPM pool
~100–200816–32 GBStart planning to split the DB

The single biggest web-tier lever is the PHP-FPM process pool. Each PHP-FPM child handles one request at a time and consumes memory, so you size pm.max_children by how much RAM you can spare divided by the average process size:

; /etc/php/8.3/fpm/pool.d/www.conf
; Rule of thumb: max_children = (RAM for PHP) / (avg PHP-FPM process ~64-128MB)
; e.g. 8GB reserved for PHP / 100MB ≈ 80
pm = dynamic
pm.max_children = 80
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 30
pm.max_requests = 500        ; recycle workers to curb memory leaks

Set max_children too high and a traffic spike swaps the box to death; too low and requests queue even though CPU is idle. Measure your average process size under load, then size deliberately. Deep PHP, OPcache and database tuning is the subject of Spoke 2 — here we care about the architecture around it.

Stage 2 — split the database and cache off first

When one server can no longer keep both PHP and the database happy, the first move is not a second web server — it is giving the database its own machine. The DB is the shared bottleneck every request touches, and it competes with PHP for exactly the same RAM. Separating them lets you tune each independently and size the database's InnoDB buffer pool to hold your working set in memory:

# my.cnf on the dedicated DB server (MariaDB/MySQL)
# Give InnoDB ~60-70% of the DB server's RAM
innodb_buffer_pool_size = 12G      # on a 16GB DB box
innodb_buffer_pool_instances = 8
innodb_flush_log_at_trx_commit = 2 # faster; small durability trade-off
max_connections = 300              # >= peak PHP-FPM children across app nodes
innodb_flush_method = O_DIRECT

At the same time, move Redis (used for Moodle's Universal Cache / MUC and sessions) onto its own service so cache pressure never evicts database pages. A typical Stage 2 layout is three roles: app server (web + PHP-FPM + moodledata), database server, and Redis server. You are still single-app-node here, so moodledata can stay local — that changes in Stage 3.

Redis/MUC and CDN specifics are covered in Spoke 3 of this series.

Stage 3 — scale out to multiple app nodes

Past roughly 500 concurrent users you scale the application tier horizontally: put a load balancer in front of two or more identical app nodes. This adds throughput and removes the app server as a single point of failure — but it introduces the rule that trips up most self-hosters: state can no longer live on any single node.

Three things must become shared

  • moodledata — the shared files directory must be reachable by every app node, via NFS or an S3-compatible object store. If node A writes an uploaded file and node B can't see it, learners get broken downloads.
  • Sessions — store sessions in Redis (not on local disk) so a learner load-balanced to a different node stays logged in. Configure this in config.php:
// config.php — shared Redis sessions across app nodes
$CFG->session_handler_class = '\\core\\session\\redis';
$CFG->session_redis_host = '10.0.0.20';   // Redis server
$CFG->session_redis_port = 6379;
$CFG->session_redis_acquire_lock_timeout = 120;
$CFG->session_redis_lock_expire = 7200;
  • Cron — run Moodle's scheduled cron on exactly one node (or a dedicated worker), never on all of them, to avoid duplicate task execution.

For the database, add one or more read replicas and point Moodle's read-only queries at them to take load off the primary. With shared state handled, you can add or remove app nodes freely — the basis for Stage 4.

Stage 4 — high availability for 10,000+

At the top tier the goal shifts from raw capacity to resilience: no single failure should take the platform down, and capacity should flex with demand. The building blocks:

  • Multiple app nodes across availability zones behind a highly-available load balancer, with autoscaling on CPU/traffic for exam-day spikes.
  • Database HA — a primary with synchronous/asynchronous replicas and automatic failover; reads spread across replicas.
  • Object storage for moodledata (S3-compatible) instead of a single NFS box, removing a shared point of failure.
  • Redis HA (replicated/clustered) for sessions and MUC.
  • CDN in front of static assets and media to cut origin load and latency for distributed learners.

This is real infrastructure engineering, and it is where DIY self-hosting gets expensive in both cloud spend and specialist time. The learning-outcomes payoff is concrete: even during your busiest assessment window, pages stay fast, sessions hold, and learners don't abandon mid-course because the site stalled.

  1. 1
    Estimate peak concurrency

    Take your active user count and apply a realistic peak factor (10–25%, higher for timed exams). This single number drives the whole design.

  2. 2
    Pick the lowest stage that fits

    Match concurrency to Stage 1–4. Don't build HA for 80 concurrent users — right-size, then grow.

  3. 3
    Tune before you scale out

    Max out a well-configured single server (OPcache, PHP-FPM pool, InnoDB buffer pool) before adding machines. It's cheaper and simpler.

  4. 4
    Split the database first

    When one box strains, give the DB its own server before adding web nodes — it's the shared bottleneck every request hits.

  5. 5
    Share state before adding app nodes

    Move sessions to Redis and moodledata to shared storage, and pin cron to one node, the moment you run more than one app server.

  6. 6
    Load-test against real content

    Simulate your peak (e.g. an exam start) with realistic courses and users, then adjust. Never size on guesswork alone.

DIY self-hosted scaling

  • You size, tune and load-test every tier yourself
  • You engineer shared moodledata, Redis sessions & DB replicas
  • You own failover, patching, backups and 3am incidents
  • Cloud bill and specialist time grow fast at Stage 3–4
  • Mis-sizing shows up as exam-day outages

Managed Moodle (edzlms)

  • Architecture sized to your real peak concurrency
  • Shared storage, caching & DB scaling pre-engineered
  • HA, failover, backups and patching handled for you
  • Predictable pricing instead of runaway infra spend
  • Performance tuned so latency stays low under load
ℹ

Not sure which stage you need?

Tell us your active user count and how learners use the platform (self-paced vs timed exams vs live cohorts) and we'll size the right architecture — and run it for you as managed, performance-tuned edzlms Moodle hosting in India.

💡

Design for your spike, not your average

If you run timed assessments or instructor-led sessions, everyone logs in at once. Size for that peak minute — it's what actually takes servers down — and use autoscaling so you're not paying for it 24/7.

Frequently asked questions

How many users can a single Moodle server handle?

A well-tuned single server (4–8 vCPU, 16 GB RAM) typically handles about 100–200 concurrent users, which can map to well over 1,000 total accounts depending on how spread-out usage is. Tuning OPcache, the PHP-FPM pool and the InnoDB buffer pool matters as much as raw hardware.

Should I size Moodle by total or concurrent users?

Concurrent (peak) users. Peak concurrency is usually only 10–25% of total accounts, and it's the number that determines how much CPU, RAM and how many app nodes you need. Timed exams and live sessions push concurrency higher.

What is the first bottleneck when Moodle slows down under load?

Almost always the database. Before adding web servers, give the database its own machine and size the InnoDB buffer pool to hold your working set in RAM. Only then scale the application tier.

What breaks when I add a second Moodle app server?

Anything stored on a single node. moodledata must move to shared storage (NFS or S3-compatible), sessions must move to Redis, and cron must run on only one node. Miss these and you get broken file downloads, random logouts, or duplicated scheduled tasks.

Do I need high availability for a few hundred users?

Usually not. A tuned single server or a split DB+cache setup comfortably serves several hundred concurrent users. Full HA (replicas, object storage, autoscaling) is for thousands of concurrent users or where downtime is unacceptable.

Does slow hosting really affect learning?

Yes. Added page latency increases drop-off and reduces course completion — learners abandon slow pages. So server architecture is not just an IT concern; it directly affects training outcomes and ROI.

Get an architecture sized to your real load

Whether you're at 100 users on one server or planning for 10,000 across a high-availability cluster, the right design comes from your actual peak concurrency and usage pattern. Share those and we'll map the stage you need — and run it for you, tuned and monitored, as managed edzlms Moodle hosting.

Next in the series: the Moodle Performance Optimization pillar ties together architecture, PHP/OPcache, database, caching and CDN.

Book a Free Demo

Prefer to pick a slot directly? Grab a time here, or email marketing@edzlms.com.

Written by Mihir Jana, founder of edzlms — connect on LinkedIn.

Tags

Moodle hostingserver architectureMoodle performancescalingedzlms

Related articles

Moodle12 min read

Moodle Migration: The Complete Step-by-Step Guide (2026)

A complete, step-by-step Moodle migration guide for 2026 - move from another LMS to Moodle, and migrate a Moodle install to a new server or domain, with the exact commands.

Moodle8 min read

Best Moodle Plugins in 2026: The Admin, Teacher & UI Add-Ons That Matter

The best Moodle plugins for 2026, grouped by job — administration, teaching and UI/UX — with plugin types, install counts and what each one does, plus the AI layer edzlms adds on top.

Moodle10 min read

Moodle Performance Optimization: The Complete 2026 Guide

A complete 2026 guide to Moodle performance - architecture, PHP and OPcache, MySQL/MariaDB tuning, Redis caching and CDNs - with the settings that actually move the needle for any LMS.

See EdzLMS in action.

Book a 45-minute demo tailored to your industry.

Book a Free Demo →