Moodle performance tuning and caching

How to make a self-hosted Moodle fast under peak load: the settings, cache and session choices, background task design and load testing that come before exam periods.

On this page

Why Moodle slows down at peak and how to tune performance before exams

A self-hosted Moodle that runs well in normal weeks often slows or times out during assessments and enrolment peaks because load concentrates on a few components at once. The fix is to tune PHP, the database, the cache stores, session handling, cron and ad hoc task workers, and file storage together, measuring each under realistic exam traffic before the exam period starts. Tuning one layer in isolation usually moves the bottleneck to another, so the sequence of changes matters as much as the changes themselves.

Moodle's core is licensed under GPL-3.0 and can be run on infrastructure you control, which means the performance baseline is your responsibility. Nobody else tunes your PHP workers, sets your database connection limits or decides where session data lives. Moodle HQ publishes the platform and its release notes, but the team running the site owns the sizing, the configuration and the evidence that the site holds under load. The same ownership applies whether the site runs on a single virtual machine or a set of web nodes.

The supported software versions set the floor for any tuning work. Moodle 5.1 requires 64-bit PHP 8.2 or later, with PHP 8.3 and 8.4 supported, and Moodle 5.3 requires 64-bit PHP 8.3 or later. Database requirements differ by release as well, so confirm the PHP and database versions in the release notes for the exact Moodle version you run before changing any setting. A PHP upgrade to reach a supported version can change opcache behavior, memory use and request speed, so it should be measured as a performance change in its own right, not assumed to be neutral.

Before changing anything, ask who owns each layer and what evidence you have. Confirm the current PHP version and opcache configuration, the database engine and its connection limits, the cache store and session handler in use, how cron and ad hoc tasks are scheduled, and where moodledata sits. Record slow query logs, PHP request times and task queue lengths from a normal week and from the last peak. Those records tell you which layer is constrained and give you a baseline to test against, which is far more useful than a general recommendation to add memory.

Which Moodle components decide how fast the site responds

A slow Moodle site is rarely slow in one place. Each request passes through the PHP runtime, the database, Moodle's caches, the session store, background tasks and file storage, and a weak link in any of them shows up as lag for every user. Check these layers in the order a request meets them, and confirm each against your own telemetry before changing settings.

PHP runtime and OPcache

PHP executes every Moodle page, and OPcache holds compiled scripts in memory so they are not parsed on each request. Check the PHP version against the Moodle release you run, since the supported range changes between releases, and confirm OPcache is enabled and sized for the full code base, including plugins. Watch for memory exhaustion errors and slow pages that share one PHP worker pool, which point to runtime limits rather than the database.

Database engine and query load

Moodle reads and writes most state through its database, and query time often dominates page generation on course, grade and report pages. Confirm the engine and version your target Moodle release supports, such as PostgreSQL 15 or 17, MySQL 8.4, MariaDB 10.11 or 11.4, or SQL Server per release notes. Look for long-running queries in the slow query log and for lock waits during peak logins, then review indexes and plugin queries that scan large tables.

MUC cache stores and definitions

Moodle Universal Cache (MUC) keeps frequently read data such as configuration, course information and capabilities in cache stores, and each cache definition decides which store serves it. A missing or undersized store forces repeated database reads, while a shared store that is not reachable from every web node causes inconsistent results. Review cache store statistics in the administration pages and check which definitions are hit most often before changing stores.

Session storage

Session data links each logged-in user to state held between requests, and where it is stored affects both speed and failover. Storing sessions in the database adds writes to every page view, while a dedicated store reduces that load but adds another service to run and secure. Check session lock contention on pages that issue several AJAX calls at once, and confirm the storage choice before adding a second web node.

Cron and adhoc task runner

Scheduled tasks and adhoc tasks, such as gradebook recalculation, notifications, backups and reports, run outside page requests and compete with users for CPU and database connections. Confirm cron runs on a schedule that does not overlap with itself, and review the scheduled task log for tasks that run long or fail repeatedly. During exam periods, check how many adhoc tasks queue behind each other, since a backlog delays grade and notification updates even when page speed looks normal.

Moodledata file storage

The moodledata directory holds uploaded files, course content, temporary files and some cache data, and its storage backend sets the latency of every file download and upload. Local disks serve well for a single node, but network file systems add latency to each file read and need correct locking for shared use. Check the throughput of the mount under load, the free space trend, and how large media files are served, because video and large PDFs often dominate bandwidth during peak use.

Which caching, session and task options fit your load

This table compares the cache, session, task and file storage options for a Moodle site and shows when each fits and what it asks of your operations team. Read each row against your number of web nodes and your peak exam load. The main takeaway is that shared stores and dedicated task workers add services you must run, back up and fail over, so confirm store and plugin support for your Moodle version before you choose.

OptionWhen it fitsOperational cost
Default file-based cache storesOne web node, or a modest number of concurrent users where the default cache keeps upNo extra service to run. Cache data can usually be rebuilt, so confirm with your backup plan whether it needs to be included.
Redis or Memcached cache storesSeveral web nodes that need a shared cache, or heavy cache traffic that the default stores handle poorlyAn extra service to install, monitor, back up and fail over. Needs skills in the chosen store. Confirm store support for your Moodle version and PHP extension.
Local sessions on each web nodeA single web node, or a load balancer configured to keep each user on one nodeSimple to run. Sessions are lost if a node fails, and users may be logged out if routing changes.
Shared sessions in a central storeMultiple web nodes behind a load balancer where users can land on any nodeA session store becomes a shared dependency that needs failover planning, monitoring and capacity checks. Confirm session store support for your Moodle version.
Single cron hostOne web node, a small user base, or light scheduled work with few queued ad hoc tasksOne host to watch. A long-running task can delay others, and failover of the cron role usually needs a scripted or manual takeover.
Dedicated ad hoc task workersExam periods with large queues of background work such as report generation, bulk enrolments or backupsExtra hosts or processes to run and monitor, with queue depth and failed task alerts. Needs Linux administration skills. Confirm how your Moodle version runs task workers.
On-disk moodledata storageA single web node, or a shared network file system with low latency and proven administrationMoodledata must be included in file backups and restores. A shared network file system adds permissions and performance administration.
Object-based file storageSeveral web nodes that need shared file access without a network file system, or very large file volumesRequires an object store, a file storage plugin and backups of both the database and the bucket. Confirm plugin support and version compatibility with your Moodle release.

How to tune a Moodle site step by step

This sequence moves a Moodle site from a measured baseline to a tuned stack, changing one layer at a time and checking each result against the baseline. The output is a documented configuration that handles peak load and can be repeated before each exam period.

  1. Baseline the current site with logs and a synthetic test

    Start by recording how the site behaves today. Collect web server and PHP-FPM logs, slow query logs from the database, and Moodle's own performance debugging output for a normal day and a busy day. Then run a scripted synthetic test that logs in as several test users and opens course pages, quizzes, gradebook views and the dashboard. Record page timings, error rates and the count of concurrent sessions the test reached. The step is done when you have a written baseline table that every later change will be compared against, and that table names the slowest pages and the heaviest database queries.

  2. Confirm PHP and database versions for the target release

    Before changing any setting, confirm that the current PHP and database versions are supported by the Moodle release you will run. Moodle 5.1 requires 64-bit PHP 8.2 or later, with 8.3 and 8.4 supported, and Moodle 5.3 requires 64-bit PHP 8.3 or later, with 8.4 supported. The database requirements also differ by release, including PostgreSQL 15 for 5.1 and PostgreSQL 17 for 5.3. If the target release needs a newer runtime, plan that upgrade first, because tuning values on an unsupported stack will not carry over. The check is a written compatibility list signed off by the platform owner, with each component version recorded next to the target Moodle release.

  3. Tune PHP, OPcache and the database server

    Adjust the PHP process manager, memory limits and OPcache settings so that the number of PHP workers matches the memory and CPU available on each web node. Set database parameters such as connection limits, buffer or memory pool sizes and query logging thresholds according to the database vendor's guidance for your version. Change one group of settings at a time and keep the previous values in version control. The check is a rerun of the synthetic test from the baseline step, with a comparison of median and slowest page timings, plus confirmation that PHP-FPM does not report worker exhaustion during the run.

  4. Configure MUC cache stores and check hit behaviour

    Moodle's Universal Cache (MUC) stores definitions and application caches. Review the cache stores configured under Site administration, decide which store serves each cache definition, and confirm that the chosen store is available to every web node. Shared caches are required when more than one web node serves the same site. After the change, look at cache hit and miss statistics for the most-used definitions and check for high miss rates or lock contention in logs. The check is a stable hit rate on the core definitions during the synthetic test and no new cache-related errors in the logs, compared with the baseline.

  5. Set session handling for the expected load

    Choose where PHP sessions are stored and how long they last. The storage choice depends on whether the site runs on one node or several. Moodle has documented session handler options, and the choice must be compatible with the cache and load balancer design. Review the session timeout and check that lock timeouts are not too short for pages that take longer to render under load. Confirm sticky sessions or shared session storage behave as intended for your topology. The check is a test where the synthetic users log in, stay active for the full test window and log out cleanly, with no unexpected session drops or lock timeouts in the logs.

  6. Separate cron from adhoc task workers and schedule them

    Moodle runs scheduled tasks through cron and runs queued adhoc tasks, such as large report generation or bulk enrolment work, through separate processes. Configure the system cron to run every minute, and set up one or more adhoc task workers so that long jobs do not delay scheduled tasks. Decide which node runs cron if the site has several web nodes, so that tasks do not run twice. Check that workers restart after failure and that their logs are collected. The check is a queue depth reading taken during normal use and during a simulated exam-day batch, showing that the adhoc queue drains and scheduled tasks finish on time.

  7. Review moodledata storage and uploads

    Review the moodledata directory, which holds uploaded files, caches and temporary data. Check the storage type, the free space and the I/O performance of the volume, and confirm that all web nodes mount the same shared storage if the site runs on more than one node. Review the file upload size limits in PHP and the web server, and confirm they match the limits set in Moodle. Clean up temporary files according to the site's policy and check that file serving does not pass through PHP unnecessarily when the web server can serve it directly. The check is a timed upload and download of a large test file from a student account and a review of storage latency during the synthetic test.

  8. Re-measure after each change

    Repeat the baseline measurements after every change, not only at the end. Keep a change log that records each setting, the value before and after, the reason and the test result. Compare page timings, error counts, cache hit rates, queue depth and database slow query counts against the baseline table. If a change makes one page faster but another slower, roll it back or adjust it before moving on. Repeat the full set of tests before each exam period, using the same scripts and user profiles, so results remain comparable over time. The check is a signed-off results document that shows each change and its measured effect, and a schedule for repeating the test before the next high-load period.

How Moodle cache stores and sessions behave under concurrent users

The cache definitions that Moodle uses are declared in code, but the stores that hold the cached data are chosen by the administrator in the Caching configuration pages under Site administration. In a multi-node deployment, every web node reads the same definitions and the same store configuration, so the decision that matters most is whether the stores behind each definition are shared by all nodes. Moodle's Universal Cache (MUC) has several cache modes. Application caches hold data that must be consistent across the site, while request caches exist only for the current page load and are local by design. Before anything else, confirm which definitions use application mode and which stores they map to.

A store that exists only on one node causes problems that look like random bugs. If an application cache is backed by a file store or an APCu store on web node A, node B cannot see the entries node A writes, and invalidation events sent after a setting change or course update may not reach it. Users then see a changed setting on one page and the old value on the next, or they report errors that disappear after a refresh. The symptoms depend on which node the load balancer selects, so they are hard to reproduce in a single-server test. Illustrative example: a teacher saves a course change, the next request lands on a node with a stale copy, and the page shows the old structure until the entry expires or the cache is purged.

Session storage has a similar effect during login spikes, such as the first minutes of an exam or a start-of-term enrolment wave. If sessions are written to local files on each node, a user who is routed to a different node loses the session unless the load balancer keeps them on the same node, which is called session affinity. Database sessions avoid that problem but add writes to the database at the moment it is busiest. Shared key-value stores can carry session data across nodes, but they need enough capacity, a monitored connection, and a plan for restarts, because a session store outage logs out every active user. Confirm the session handler, the session timeout, the lock timeout behaviour and whether the load balancer uses affinity before the load test is designed.

Verify these items in the administration interface and the infrastructure, not from memory of defaults. In the Caching configuration page, list every store, confirm which are enabled, run the store test for each, and check the mappings for each application cache definition that is used by your plugins. Confirm that every node points to the same shared store endpoints through the same configuration, and that a purge from one node is visible on the others. Check the session handler and its connection settings on every node, the load balancer affinity setting, and the behaviour during a store restart. Record the results in the change log, because a later plugin install or configuration change can add definitions that map to a local store. Ask any implementation partner to show these checks in the written scope and to repeat them after the load test.

What makes Moodle tuning take longer or cost more

This table lists the factors that lengthen Moodle performance work or raise its cost, with a way to keep each one under control. Read each row as a driver: the first column names it, the middle column explains why it matters, and the last column gives the step that reduces the effort. The main takeaway is that baseline measurements and early load tests cost far less than tuning under pressure during an exam period.

DriverWhy it adds effort or costHow to keep it down
Concurrent users at peakPeak logins, quiz attempts and video playback set the load target. The higher the target, the more web nodes, database capacity and cache tuning are needed.Ask the institution for historical peak figures from the previous exam period, and agree the target load profile in writing before any test is designed.
Course and file volume in moodledataLarge numbers of courses, files and backups slow file serving, backup jobs and storage checks. Growth tends to surface only after go-live.Record current course, file and moodledata sizes as a baseline, and plan archiving or retention rules before the next migration or term start.
Number and quality of pluginsEach installed plugin can add database queries, cron tasks or cache definitions. Poorly maintained plugins are the most common source of unexplained slowdowns.Inventory every installed plugin with its version and maintenance status, remove unused ones, and profile the heaviest plugins before tuning core settings.
Integrations creating load (SSO, HR sync, web services)Scheduled HR syncs, enrolment imports and web service calls compete with learners for database and PHP resources, often at the same hours.Map each integration's schedule and call volume, move bulk syncs off peak hours, and test them together with learner traffic rather than in isolation.
Environment parity (dev, test, production)If the test environment differs in PHP version, database engine, cache stores or hardware, load test results do not predict production behavior.Keep the test stack matched to production in PHP, database, cache and web server settings, and document every known difference that remains.
Custom code and reporting queriesCustom reports and unindexed queries can scan large log and grade tables. A single report run during an exam can slow the whole site.Review custom code and report SQL during build, add indexes where justified, and restrict heavy reports to off-peak windows during assessment periods.
Compliance evidence of testsAssessors and internal audit may ask for documented test plans, results and retained evidence. Producing this after the fact takes extra time and can be incomplete.Agree the evidence format early, record test scripts, environment details and results with dates, and keep baseline numbers under version control.
Timing of the first load testTesting late in the project leaves little room to fix bottlenecks. Problems found days before an exam often force rushed, higher-risk changes.Schedule a first baseline test after the core build and plugin set is stable, then repeat it after each major change and before each exam period.

How tuning differs on a single server, several nodes or Kubernetes

On one server, the web server, PHP, Moodle and the database usually share one host, so file-based sessions and a local moodledata directory work without extra components. Tuning focuses on PHP workers, OPcache, database memory and the choice of cache store. The main risk is that a load test also consumes the CPU, memory and disk that the database depends on.

  • Cache stores: the default file caches are simple to run, but a local in-memory store such as Redis or Memcached on the same host often reduces database reads as concurrent users rise. Confirm which stores your Moodle version and plugins support.
  • Sessions: file sessions on local disk are usually adequate at this scale, provided the session directory sits on fast local storage.
  • Cron: run Moodle cron from the system scheduler every minute, and run ad hoc task runners so queued work does not wait for the next cron cycle.
  • File storage: keep moodledata on local disk and back it up together with the database, because files and database records must match.
  • Document root: from Moodle 5.1, the web server must point to the /public directory in the Moodle code.

Check the single-node profile against your expected peak concurrency and exam schedule, and ask the platform team whether the host can absorb a load test without affecting other services.

Security controls that stay in place while tuning

Performance work often touches the same settings that security depends on, such as web server paths, cache network exposure, credentials and debug output. The controls below are the ones to verify before and after every tuning change, not only at go-live.

Serve the /public document root

From Moodle 5.1 onward, the web server document root must point to the new /public directory rather than the main Moodle folder. Pointing it at the wrong folder can expose directory listings or produce errors. When you change PHP-FPM pools, web server virtual hosts or load balancer targets during tuning, confirm the root still resolves to /public and that the main code folder is not reachable over HTTP.

Keep cache and session backends private

Redis or Memcached often sit behind the Moodle cache stores and session handling that make tuning effective. These services should listen only on a private network interface, be reachable only from the Moodle web and cron nodes, and require authentication where the software supports it. Scan the host from outside the application network after each change to confirm the cache port is closed to other networks.

Protect database credentials

Tuning frequently means editing config.php, connection pool settings, read replica endpoints or environment variables. Store database credentials in a secrets mechanism your platform controls, restrict file permissions on config.php, and avoid copying credentials into shared tuning scripts or tickets. Rotate the database account password after any tuning contractor or engineer leaves the project.

Lock down the moodledata path

The moodledata directory holds uploaded files, backups and cache files, and it should never be served directly by the web server. Confirm that its path sits outside the web root, that the web and cron processes have only the permissions they need, and that any shared storage mount used for performance is not world-readable. Recheck this when file storage or caching paths are moved.

Control who runs load tests

Load tests against production can slow exams, fill queues and create large volumes of test data. Agree in writing who may start a test, which environment it targets, the time window and the stop condition. Run most tests against a staging copy that matches production configuration, and record every production test with its operator and purpose so the audit trail is complete.

Turn off debug settings after tuning

Profiling, developer debugging and verbose error display help during tuning but leak paths, query details and stack traces if left on. Before release, check the debug display setting, developer mode, and any profiling or query logging switches in the site administration and configuration files. Ask the implementation partner or internal team to attach this check to the change record.

How to load test Moodle before an exam period

A load test tells you whether Moodle will hold during an exam window only if the test resembles the live site. Before any tool is started, agree on the workload, the environment and the pass criteria in writing. Without those three, a green result proves very little, and a red result leads to arguments about whether the test was fair. Start with a representative workload. Ask the teaching team which quizzes will run during the exam period, how many questions and attempts each has, whether questions are randomized, and whether they use essay or file upload responses. Model course activity too: forum posts, assignment submissions, gradebook views and completion checks. Add login spikes that match the timetable, for example several thousand students signing in within the first ten minutes of a scheduled quiz. Ask the institution for its real peak figures from the previous exam period rather than inventing a profile.

The test data must match production in volume as well as shape. A course with twenty users and a database with ten thousand users will not reveal the same query plans, cache hit rates or table locking behavior. Confirm with the site administrator the approximate size of the database, the number of enrolments per course, the size of the logstore table and the amount of data in moodledata. Seed the test copy from a sanitized production backup where possible, and record the seed size so the results can be read later. The test environment should match production in PHP version and settings (OPcache, memory limit, max execution time), the database engine and its configuration, the cache stores used for application and session caches, and the web server document root. For Moodle 5.1 and later, the document root must point to the /public directory, and a test that serves from the wrong path can produce misleading errors. Hardware and network paths between web nodes, cache and database should also be comparable. Write down every difference that remains, because each one weakens the conclusions. Agree pass criteria before the first run. Typical criteria cover response time at a stated concurrency, error rate, database connection limits, and whether scheduled cron and ad hoc tasks finish inside their expected window. The thresholds are a business decision made with the institution, not a number the tool chooses. Also decide what happens on failure: which tuning change is tried next, and who signs off on a go or no-go decision. Repeat the tests after every upgrade, plugin change or configuration change to caching or sessions, and again before each exam period. A minor release can alter query patterns, so a baseline from the previous version is only a starting point. Keep the scripts, seed data and results under version control so the next run can be compared directly with the last one.

What to monitor, back up and document after tuning

This table lists what operators check after Moodle performance tuning, what each signal tells them, and what to back up and record. Read each row as a recurring check or a standing requirement, and use the right-hand column to decide who owns it. The main takeaway is that a tuned site drifts unless someone watches queues, storage and configuration on a schedule and retests after every Moodle or PHP upgrade.

AreaWhat operators checkWhy it matters after tuning
PHP-FPM and web tierWorker pool saturation, queued requests, slow request logs and memory per workerTuning changes pool sizes; saturation shows up as slow logins and timeouts during exam peaks
DatabaseConnection counts, lock waits, slow query log entries and replication lag if a replica is usedQuery plans shift as course data grows, so slow queries often appear months after tuning
Cache hit behaviourHit and miss rates for each cache store and definition, plus eviction and memory pressure on shared storesA cache that misses often moves load back onto the database without any visible error
Cron and adhoc task queueTime since the last cron run, count and age of queued adhoc tasks, and task failure reportsGrowing queue lag delays grade syncs, backups, notifications and reports that users notice
Moodledata disk growthFree space, growth per week, and size of the filedir, temp and cache foldersUploaded course files grow without a fixed ceiling and can stop writes, including session and cache files
Error and slow logsPHP error log, web server error log, and Moodle's own logs for repeated failuresRepeated warnings after an upgrade often point to plugin or configuration faults before users report them
BackupsDatabase dump and moodledata copy taken at the same point, with a tested restore to a separate hostA database restored without matching moodledata produces missing files and broken course content
Configuration recordChanges to PHP settings, cache stores, cron timing, server limits and Moodle admin settings, with date and ownerWithout a record, operators cannot tell whether a slowdown followed a tuning change or a plugin update
Load test rerunRepeat the exam-period load profile after each Moodle major or minor upgrade and each PHP version changeUpgrades can change query patterns and cache use, so earlier results no longer predict production behaviour

Questions teams ask before tuning Moodle performance

How much effort does Moodle performance tuning involve?

Effort depends on how far the current site is from its target load and how many layers are in scope. A one-time tuning project usually includes an assessment of the current stack, changes to PHP and database settings, cache store and session configuration, cron and ad hoc task worker design, a file storage review, and load test runs with a written report. Cost splits between parties: a partner's fee covers analysis, configuration changes and testing, while your organization pays for infrastructure changes, any larger servers or managed services, and staff time for access and sign-off. Recurring effort comes from retesting before exam periods and after upgrades. Ask any quote to separate one-time work from recurring retest work.

How long does Moodle performance tuning take?

Duration depends on the factors that set how much analysis and testing the site needs. The main drivers are peak concurrent users, the gap between current and target performance, the number of environments available, installed plugins and custom code, whether database or file storage changes are needed, and how quickly access and a load test window can be scheduled. A site with clean configuration and a test environment that matches production usually moves faster than one with no baseline data. Your change approval cycles also add elapsed time. Treat any schedule as an output of the written scope, and ask the partner to show which steps wait on your access, data or test window.

Can our internal team tune Moodle performance without a partner?

Yes, many internal teams can tune Moodle if they have working skills across Linux, the web server, PHP, the database and Moodle administration. Moodle's public documentation covers many of the settings involved, and the core method is measurable: collect a baseline, change one thing, then test again. The common gaps are load test design, reading database query profiles, and choosing cache and session architecture for several web nodes. Also check whether the team can run tests without affecting live users and repeat them before each exam period. Staff time is the main cost of doing this internally, so compare available hours against the testing cycle and the risk of changing a production system during term time.

What do we need to provide for Moodle tuning work?

Most tuning work depends on access and inputs that only your organization can supply. Plan for:

  • Access: read access to web, application and database servers, monitoring and log sources, and an administrator account in Moodle.
  • A test environment: ideally sized and configured like production, with the same PHP, database and cache components.
  • Test data: course, user and enrolment volumes that reflect real usage, with personal data removed or replaced with synthetic records.
  • A load test window: an agreed period when the test environment or a controlled production window can take heavy traffic without affecting users.
  • Sign-off contacts: named people who approve configuration changes and accept test results.

If any of these is missing, the schedule usually moves, so confirm each item in the written scope before work starts.

Do we need to retune Moodle after every upgrade?

Not every upgrade needs a full tuning project, but each major upgrade needs a performance check. Moodle ships major releases every six months and minor point releases every two months, and requirements change between versions. For example, Moodle 5.1 requires 64-bit PHP 8.2 or later and supports PostgreSQL 15, MySQL 8.4, MariaDB 10.11 or SQL Server 2017 or later. From 5.1, the web server document root must point to the public directory, and a wrong setting can cause directory listings or errors. These changes can alter PHP-FPM behavior, database load and caching, and plugins can change query patterns. Confirm the target version's requirements early, then re-run key scenarios after the upgrade.

How do we ask a partner for a fixed-scope tuning quote?

Send the partner a written brief that lets them scope the work without guessing. Include an inventory of the current environment, target concurrency and peak events such as exam periods, and the layers you want covered: PHP, database, cache stores, sessions, cron and ad hoc task workers, file storage and load testing. Name any exclusions, such as hardware purchases or changes to third-party systems. Ask for deliverables in writing, for example configuration changes, test reports and a runbook for retesting. Ask the partner to list client responsibilities, assumptions and the dependencies on your access and test window. DeployOpen plans most engagements as fixed scope, with scope, deliverables and timelines agreed in writing before work starts, and it does not publish a price list, so the quote follows from that written scope.

Which parts of Moodle usually need tuning first?

The usual starting points are cache stores and session handling, cron and ad hoc task workers, PHP-FPM and database configuration, and file storage for moodledata. Start by collecting measured data: web server and PHP-FPM logs, database slow query logs, and Moodle's own performance information on the admin pages. Look for slow pages under concurrent load, long-running tasks that delay cron, and cache misses that send heavy queries to the database. Session storage matters most when several web nodes share users. File storage matters when large uploads or media are served through the site. Change one area at a time, record the result, and keep the change only when the measurements show it helped.

How DeployOpen works on this

DeployOpen treats Moodle performance tuning and caching as a fixed-scope engineering task inside infrastructure the client controls. The work starts with a written scope that names the load profile, the Moodle version and the components in play, then moves through tuning, testing, documentation and handover.

How we scope

  • Written scope names the Moodle version, PHP and database versions, and the hosting layout in use
  • Load profile covers expected concurrent users, peak periods such as exam windows, and current response times
  • Scope lists which cache stores, session handling, cron and task workers, and file storage are in or out
  • Fixed-scope engagements agree deliverables and timelines in writing before any tuning begins
  • Ask the vendor or your environment to confirm supported PHP and database combinations for your target release

How we build

  • Baseline measurements of page response, database load and PHP worker usage are taken before any change
  • PHP, database and web server settings are tuned one area at a time, with each change recorded and reversible
  • Cache stores and session handling are configured against the topology the client actually runs
  • Cron and ad hoc task workers are set up so background jobs do not compete with learners during peaks
  • Load tests are run against a staging copy before the agreed exam period, with results compared to the baseline

How we hand over

  • Documentation records every tuned setting, its reason, and the test result that justified it
  • Runbooks cover cache purges, worker restarts, slow query review and what to check after a Moodle upgrade
  • Knowledge transfer sessions walk the client's administrators through monitoring and the load test procedure
  • Handover includes a list of settings that must be re-checked when plugins or Moodle versions change

How we support

  • Ongoing support and upgrade testing are available as a retainer that starts after go-live
  • Retainers can include repeat load testing before each exam period and review after each Moodle minor release
  • Support scope, response expectations and reporting are agreed in writing, so the client knows what is covered
  • Ask any provider to confirm how performance regressions are reported, triaged and retested

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.