Executive Summary
Upgrading a production Moodle instance from a legacy version 4.0.4 to 5.2 is not a single-click event. It is a coordinated, multi-layer infrastructure operation that touches your PHP runtime, your MySQL database engine, and the Moodle application itself — in a specific sequence, with mandatory intermediate stops along the way.
This white paper documents the systematic approach Ei Consulting applies to legacy Moodle upgrades of this scope. It covers the upgrade pathway, the dependency matrix that governs each step, the backup discipline required before touching anything, and the real-world gotchas that have derailed upgrades for teams who underestimated the operation's complexity.
If your institution or organization is running Moodle 4.0.4 and has deferred the upgrade conversation, this is the briefing you need.
Why This Upgrade Is Not Optional
Moodle 4.0.4 entered the end-of-active-support window in November 2023. Running it in 2026 means operating on a platform that no longer receives security patches, bug fixes, or community-maintained plugin compatibility. More critically, PHP 7.4 — the runtime that supported early Moodle 4.x — reached end-of-life in November 2022.
That combination — an unsupported PHP version running an unsupported Moodle release — is not a technical inconvenience. For institutions handling student records, assessments, or any regulated data, it is an active compliance risk.
Moodle 5.2 requires a minimum PHP version of 8.3, MySQL 8.4, and a minimum upgrade base of Moodle 4.4. None of those are directly compatible with a Moodle 4.0.4 environment running PHP 7.4 and MySQL 8.0. The gap requires a structured, staged approach — not a direct jump. GitHub
The Upgrade Pathway at a Glance
The following table maps the full dependency chain from the starting state to the target state:
| Stage | Moodle Version | PHP Version | MySQL Version |
|---|---|---|---|
| Start | 4.0.4 | 7.4 | 8.0 |
| Checkpoint 1 | 4.1.x | 8.0 | 8.0 |
| Checkpoint 2 | 4.4.x | 8.3 | 8.0 |
| Target | 5.2 | 8.3 / 8.4 | 8.4 |
Each row represents a validated, stable state. You do not move forward until the platform at each checkpoint is confirmed healthy and backed up. Skipping rows is how upgrades fail in production.
Before You Touch Anything: The Backup Discipline
This is not a boilerplate caution. It is the most operationally consequential section of this document.
A Moodle environment has three independently restorable assets. All three must be captured before any upgrade step:
1. The Database
Your Moodle database holds every grade, every enrolment, every completion record, every user account, every forum post. It is the most critical asset and the most commonly under-backed-up one on legacy systems.
bash
mysqldump -u root -p \ --single-transaction \ --routines \ --triggers \ --events \ moodle_db > moodle_db_backup_$(date +%Y%m%d).sql
Use --single-transaction on InnoDB tables to capture a consistent snapshot without locking the database. Compress the output — a production Moodle database of 50GB compresses to a fraction of that under gzip. Verify the dump file is non-zero and readable before proceeding.
2. The Moodledata Directory
The Moodledata directory stores every file that users have uploaded — course files, assignment submissions, profile images, backups. On systems that have been running for several years, this directory can easily reach hundreds of gigabytes or several terabytes.
bash
tar -czf moodledata_backup_$(date +%Y%m%d).tar.gz /var/moodledata/
If a full tar is impractical due to volume, at minimum use rsync to a secondary location as a pre-upgrade snapshot. The critical point is that this directory must be recoverable independently of the database.
3. The Moodle Application Code
Back up the current /var/www/moodle/ directory before upgrading code. This is your rollback path if the new codebase introduces a PHP fatal error or a plugin incompatibility that prevents the upgrade UI from completing.
bash
cp -a /var/www/moodle /var/www/moodle_backup_$(date +%Y%m%d)
Operational rule at Ei Consulting: No upgrade step is initiated without a verified, timestamped backup of all three assets. If a backup cannot be confirmed, the step does not proceed. This is not risk aversion — it is professional practice.
Stage 1: PHP 7.4 → 8.0, Moodle 4.0.4 → 4.1.x
Why PHP first, then Moodle?
Moodle's upgrade routine is executed by PHP. If you attempt to upgrade the Moodle codebase to a version that requires PHP 8.x while still running PHP 7.4, the CLI upgrade process will terminate with a fatal error before it begins, and you will have a partially unpacked codebase with no clean rollback unless your pre-stage backup is in place.
The correct sequence within each stage is: upgrade PHP → confirm PHP version → test existing Moodle on new PHP → then upgrade Moodle.
Gotchas at this stage:
- PHP extension breakage. PHP 8.0 removed several extensions that were deprecated in 7.x. Third-party Moodle plugins — especially older authentication or activity modules — may call deprecated functions. Run a plugin compatibility audit before this step using Moodle's built-in environment checks (/admin/environment.php).
- Strict type handling. PHP 8.0 introduced stricter type handling. Code that passed malformed arguments silently in 7.4 may now throw TypeError exceptions. On a vanilla Moodle core this is handled, but customized code or legacy plugins will surface issues here.
- PHP-FPM pool reconfiguration. If your stack uses PHP-FPM (and it should), upgrading PHP requires updating the FPM pool configuration to point to the new PHP binary. Missing this step leaves Apache or Nginx serving PHP 7.4 even after 8.0 is installed.
Verify the checkpoint:
bash
php -v # Confirms PHP 8.0.x /var/www/moodle/admin/cli/upgrade.php --non-interactive # Navigate to /admin/index.php to confirm upgrade completion
Stage 2: PHP 8.0, Moodle 4.1.x → 4.4.x
This is a critical intermediate stage for a specific structural reason: Moodle 5.2 requires Moodle 4.4.0 as the minimum upgrade base. You cannot skip directly from 4.0.x or 4.1.x to 5.2. The database schema migrations are sequential, and Moodle's upgrade engine will refuse to proceed if the version gap is too large. GitHub
Moodle 4.4 is also a Long-Term Support (LTS) release, meaning it is a well-documented, widely-tested platform state. Landing on 4.4 before the final push to 5.2 gives you a stable checkpoint to confirm data integrity, run user acceptance testing, and address any plugin incompatibilities before the major version boundary.
Gotchas at this stage:
- Database prefix length enforcement. Since Moodle 4.3, the maximum length for $CFG->prefix is 10 characters. If your legacy installation was configured with a longer prefix, the upgrade will refuse to proceed. This must be addressed in config.php before the 4.3+ upgrade runs.
- Plugin inventory. Moodle 4.4 is a major compatibility milestone. Any plugin that has not been updated by its maintainer to declare 4.4 support will be flagged during the upgrade pre-check. Each flagged plugin is a decision: upgrade the plugin, remove it, or accept the risk of proceeding with an incompatible plugin disabled.
- Gradebook and competency schema changes. The 4.x series introduced significant gradebook and competency framework schema migrations. On large installations with complex grading structures, these migrations can run for extended periods. Plan for a maintenance window, not a quick deploy.
Stage 3: MySQL 8.0 → 8.4
The MySQL upgrade deserves its own dedicated stage and its own backup cycle. Do not upgrade MySQL simultaneously with any Moodle or PHP upgrade. Isolate this change.
Moodle 5.2 requires MySQL 8.4 as the minimum database version. MySQL 8.4 is an LTS release with meaningful changes to default behaviors, particularly around authentication, group replication, and deprecated SQL modes. GitHub
Why this matters for Moodle:
MySQL 8.4 removed several SQL modes and deprecated functions that MySQL 8.0 still permitted by default. Moodle core is maintained against current MySQL behavior, but custom reports, custom blocks, or bespoke queries written against your 8.0 installation may use syntax that 8.4 no longer accepts. Audit custom SQL before the database upgrade.
The upgrade procedure:
bash
# Step 1: Full logical backup before touching MySQL mysqldump -u root -p --all-databases \ --single-transaction > full_backup_pre_mysql84_$(date +%Y%m%d).sql # Step 2: Put Moodle into maintenance mode php /var/www/moodle/admin/cli/maintenance.php --enable # Step 3: Upgrade MySQL via your package manager or via AWS\RDS # (Ubuntu/Debian example using MySQL APT repository) apt-get install mysql-server-8.4 # Step 4: Run mysql_upgrade to migrate system tables mysql_upgrade -u root -p # Step 5: Verify Moodle database integrity mysqlcheck -u root -p --all-databases # Step 6: Lift maintenance mode php /var/www/moodle/admin/cli/maintenance.php --disable
Gotchas at this stage:
- mysql_native_password deprecation. MySQL 8.4 defaults to caching_sha2_password. If your Moodle config.php database user was provisioned under mysql_native_password, the connection will fail after the upgrade until the user's authentication plugin is updated. This is one of the most common — and most surprising — failure points on this migration.
- InnoDB buffer pool sizing. MySQL 8.4's default InnoDB configuration is not optimised for Moodle's workload. Revisit innodb_buffer_pool_size (typically 60–70% of available RAM on a dedicated database server) and innodb_log_file_size before restarting.
- ROW_FORMAT compatibility. Verify that all Moodle tables are using DYNAMIC or COMPRESSED row format. Legacy tables in COMPACT or REDUNDANT format will generate warnings and may produce errors under strict 8.4 InnoDB settings.
Stage 4: PHP 8.0 → 8.4, Moodle 4.4.x → 5.2
With MySQL at 8.4 and the application confirmed healthy on 4.4.x, the final ascent to 5.2 follows the same discipline: upgrade PHP to 8.3 or 8.4 first, validate, then upgrade the Moodle codebase.
Moodle 5.2 requires a minimum of PHP 8.3.0, with PHP 8.4.x also supported. The PHP sodium extension is required, and max_input_vars must be set to 5000 or higher. Moodle Developer Resources
Gotchas at this stage:
- The /public directory restructure. Moodle 5.1 introduced a structural change that moved all web-accessible files into a /public subdirectory. This means your web server's document root must be updated to point to /var/www/moodle/public rather than /var/www/moodle. Failure to update this will result in directory listing errors or broken page loads after the upgrade. This is a commonly missed step in guides that focus exclusively on the application upgrade.
- The routing option is also introduced in this version. Be sure to configure your web server to support routing: https://docs.moodle.org/en/Configuring_the_Router
- sodium extension. PHP's sodium cryptography extension is now required, not optional. On many Ubuntu installations it is present but not enabled. Confirm with php -m | grep sodium before initiating the upgrade. A missing sodium extension will cause the Moodle environment check to fail hard.
- Oracle Database support removed. From Moodle 5.0 onwards, Oracle is no longer a supported database engine. This is not relevant for MySQL-backed installations, but worth noting for organizations that operate mixed environments.
- Plugin compatibility cliff. The 4.x to 5.x boundary is a major version jump. The Moodle plugin ecosystem takes time to catch up to major releases. Before upgrading a production environment, validate every installed plugin against the 5.2 compatibility matrix on moodle.org/plugins. Plugins that have not been updated are not merely a cosmetic problem — incompatible plugins can block the upgrade routine entirely.
Rollback: The Conversation Most Teams Avoid Until They Need It
Every stage in this pathway requires a defined rollback procedure, not just a backup file. Before initiating any upgrade step, answer these questions:
- How long will it take to restore the database backup to a running state?
- Is the old PHP binary still available on the system, or was it removed during the upgrade?
- Is the old Moodle codebase preserved, or was it overwritten?
- Can the application be restored to its pre-upgrade state within your acceptable downtime window?
If any of these answers is "I'm not sure," the upgrade is not ready to proceed.
The practical approach is to snapshot your entire VM or cloud instance before each stage. A filesystem-level snapshot restores in minutes. A mysqldump restore of a 100GB database takes considerably longer. Both should exist.
Key Results from a Properly Executed Upgrade
When this upgrade pathway is followed with discipline:
- Zero data loss — the database, Moodledata, and application code are preserved through every transition
- No version debt — the platform arrives at 5.2 with every intermediate migration cleanly applied
- Plugin inventory rationalized — the multi-stage process surfaces legacy or abandoned plugins that should have been retired years earlier
- Infrastructure modernized — PHP 8.4 and MySQL 8.4 deliver measurable performance improvements over the 7.4/8.0 baseline
- Compliance posture restored — the platform returns to a fully supported, actively maintained state
Technical Appendix: Dependency Matrix
| Moodle Version | Minimum PHP | Maximum PHP | Minimum MySQL |
|---|---|---|---|
| 4.0.x | 7.4 | 8.1 | 8.0 |
| 4.1.x | 7.4 | 8.1 | 8.0 |
| 4.4.x (LTS) | 8.1 | 8.3 | 8.0 |
| 5.0.x | 8.1 | 8.3 | 8.0 |
| 5.1.x | 8.1 | 8.4 | 8.0 |
| 5.2.x | 8.3 | 8.4 | 8.4 |
Conclusion
Upgrading a production Moodle environment from 4.0.4 to 5.2 is a multi-sprint infrastructure project, not a maintenance task. The PHP dependency chain, the MySQL engine upgrade, and the mandatory intermediate Moodle version stops mean that anyone attempting this as a single operation — or without verified backups at every stage — is accepting a level of risk that no production academic or enterprise environment should tolerate.
Ei Consulting executes these upgrades with a stage-gate discipline: each checkpoint is validated, documented, and backed up before the next transition begins. The result is an upgrade that arrives at 5.2 cleanly, with data integrity confirmed and a fully documented audit trail of every change made to the environment.
If your organization is running a legacy Moodle version and has been deferring the upgrade conversation, the time to begin planning is now — not when a security disclosure forces the issue.
Ei Consulting LLC provides Moodle infrastructure consulting, LMS migrations, and platform modernization services for higher education institutions and enterprise organizations. Get in touch at ei.consulting/contact-us-ei.