Moodle Upgrade Service

Upgrading Moodle is rarely the hard part. Working out what will break, proving it on staging, and having a way back if the cutover goes wrong is the hard part. This page explains how I do it, in enough detail that you could do it yourself.

In short: A Moodle upgrade is a sequence of constrained hops governed by each release's minimum upgrade version, its PHP floor and its database minimums, and it should always be rehearsed on a staging clone with a tested rollback before any cutover.

How teams end up stranded on an old Moodle

Nobody decides to fall four versions behind. It happens in small steps. The upgrade is deferred because term is running. Then a third-party plugin has no release for the next version. Then the person who built the server leaves. Two years later the site is on a line that stopped receiving security fixes, the PHP on the box is too old for anything current, and the jump is now big enough that nobody wants to be the one who starts it.

That is the normal case, not a failure of discipline. Moodle ships a major release roughly every six months and the support windows are shorter than most people assume. Falling behind is the default outcome unless somebody owns the calendar.

How Moodle's release lifecycle works

Moodle publishes a major release about every six months, in April and October. Most are standard releases. Roughly every two years one is designated long-term support.

A standard release gets general bug fixes for about twelve months, then security-only fixes for roughly another six. An LTS gets a much longer security window, about three years from release. Once the security date passes, nothing further is published for that line.

Here is where things stand as of 21 August 2026.

ReleaseReleasedGeneral support endsSecurity support endsLTS
4.128 Nov 202211 Dec 20238 Dec 2025Yes
4.39 Oct 20237 Oct 202421 Apr 2025No
4.422 Apr 202421 Apr 20258 Dec 2025No
4.57 Oct 20246 Oct 20254 Oct 2027Yes
5.014 Apr 202520 Apr 20265 Oct 2026No
5.16 Oct 20255 Oct 202619 Apr 2027No
5.220 Apr 202619 Apr 20274 Oct 2027No
5.35 Oct 20264 Oct 20271 Oct 2029Yes

Two things follow. Moodle 4.4 and anything older is out of security support entirely, including the old 4.1 LTS. And 4.5 LTS, released six months before 5.0, has a full year more security runway than 5.0 does: 4 October 2027 against 5 October 2026. That matters when you choose a target.

The 5.3 row is Moodle's published schedule rather than a shipped release; at the time of writing, in August 2026, it was still ahead. If you want the longest quiet period after the work, 5.3 is worth planning around rather than landing on 5.2 and repeating the exercise a year later. As the next section shows, that choice also changes which version you have to reach first.

Finding your own version and its status

The site footer usually shows the release. The reliable method is from the command line, run from the Moodle installation root as the web server user:

sudo -u www-data php admin/cli/cfg.php --name=release

That prints something like 5.1.6 (Build: 20260810). The first two numbers are your release line, which is what the support dates above apply to. The third is your point release.

Point releases land on a published schedule, roughly every eight weeks. The set published on 10 August 2026 was 5.2.2, 5.1.6, 5.0.9 and 4.5.13. If your third number is well behind, you have missed security fixes even though your major line is supported. That is a far smaller job than a version upgrade, and it should be done first.

Upgrade path rules, and why you cannot always jump to latest

Moodle's upgrade code only carries database migration steps back a limited distance. Every release states the oldest version it can upgrade directly from. Go back further and the migration steps you need are simply not in the codebase.

TargetMinimum version you can upgrade directly from
4.1 LTS3.9
4.44.1.2
4.5 LTS4.1.2
5.04.2.3
5.14.2.3
5.24.4
5.3 LTS4.5

The governing policy is that an LTS release must be upgraded from the previous LTS or later, and a standard release from whichever is higher: the lowest Moodle version that supports the new release's minimum PHP version, or the minimum required by the previous LTS. Moodle's own worked example is 5.0, which needs PHP 8.2, so its floor is 4.2.3, the first release that supported PHP 8.2. That is exactly the figure in the table above.

The policy has a consequence worth noticing before you pick a target. Moodle 5.2 accepts 4.4 or later. Moodle 5.3, being an LTS, accepts only 4.5 or later, because 4.5 is the previous LTS. A site sitting on 4.4 can therefore move straight to 5.2 but not straight to 5.3.

So a site on 3.11 cannot reach 5.2 in one move. A realistic chain is 3.11 to 4.1.x, then 4.1.x to 4.5.x, then 4.5.x to your final target. Landing on 4.5 as the waypoint is deliberate: it clears the floor for 5.2 and for 5.3, so the same intermediate hop serves either destination. Each hop is a complete upgrade with its own backup and its own verification pass. Skipping verification between hops is how people end up with a database that migrated cleanly and a site that does not work.

What actually breaks

The PHP jump

The PHP floor moves faster than people expect. Moodle 4.4 and 4.5 need PHP 8.1.0 minimum and support up to 8.3.x. Moodle 5.0 and 5.1 need 8.2.0 and support 8.3.x and 8.4.x. Moodle 5.2 raises the floor again to 8.3.0, with 8.4.x supported, and 5.3 holds the same 8.3.0 floor. Only 64-bit PHP is supported, the sodium extension is required, and max_input_vars must be >= 5000.

The failure mode is not Moodle core. It is a third-party plugin using syntax or a function removed in the newer PHP, which throws a fatal error on a page nobody tests until a learner opens it.

The database engine

Minimums rise per release, and they do not all rise at once. Moodle 4.5 accepts PostgreSQL 13, MySQL 8.0, MariaDB 10.6.7 and SQL Server 2017. Moodle 5.1 sits in between, at PostgreSQL 15, MySQL 8.4, MariaDB 10.11.0 and SQL Server 2017. Moodle 5.2 and 5.3 require PostgreSQL 16, MySQL 8.4, MariaDB 10.11.0 and SQL Server 2019. Oracle support was removed in 5.0, along with SQLite. If you are on Oracle, the upgrade is also a database migration.

Collation on MySQL and MariaDB

Older sites are frequently still on utf8 (really utf8mb3), which cannot store four-byte characters. Emoji and many Indic and CJK characters silently corrupt. Convert before the upgrade, not during it:

sudo -u www-data php admin/cli/mysql_collation.php --collation=utf8mb4_unicode_ci
sudo -u www-data php admin/cli/mysql_compressed_rows.php --list

The conversion script only handles InnoDB or XtraDB tables, and for utf8mb4 it needs Barracuda row format with innodb_file_per_table enabled. It attempts to set those itself and stops with an explicit error if it cannot, which is where the conversion halts on a server that was not already configured that way. Despite the name it covers MariaDB as well, because the MariaDB driver reports a database family of mysql.

Set character-set-server = utf8mb4 and collation-server = utf8mb4_unicode_ci on the database server, and set the matching collation in config.php. Note that this is not a top-level setting: it lives inside the $CFG->dboptions array, as 'dbcollation' => 'utf8mb4_unicode_ci'. Moodle's own config-dist.php notes that the option should be removed entirely for any database other than MySQL or MariaDB. On a large table set the conversion takes real time, which is exactly why it belongs in its own window.

Plugins removed from core

Moodle 5.0 removed a lot: the Atto editor, the Chat and Survey activity modules, the CAS authentication plugin, the mlbackend_php plugin, all MNet plugins, Oracle and SQLite database support, and support for the legacy subplugins.php format.

This is the single most dangerous item on the page. If those plugins are not reinstalled from their standalone repositories before the upgrade completes, their database tables are dropped as part of the upgrade. Chat logs and survey responses go with them. Decide deliberately whether you are keeping or discarding that data, and take the backup either way.

Moodle 5.2 continues the trend, removing MimeTeX as a TeX filter option, the Activities block and the YUI TreeView in the Folder module.

Custom themes

Moodle 5.0 moved the Boost theme to Bootstrap 5. Any child theme or custom template carrying Bootstrap 4 class names will render wrongly rather than fail loudly, which makes it easy to miss until a user reports it. On a job like this, the theme is usually the line item to budget for properly: if it was built by an agency that has since moved on and the source is not under version control, you are looking at a rebuild rather than a patch, and that should be decided before the upgrade starts, not during it.

The 5.1 directory restructure

Moodle 5.1 moved web-accessible code into a public directory. Your web server document root must change from the Moodle folder to the public folder inside it:

# Apache
DocumentRoot /var/www/moodle/public

# Nginx
root /var/www/moodle/public;

Your config.php stays at the installation root, alongside public, not inside it. The public/config.php shipped with Moodle is only a loader that requires ../config.php. Existing $CFG->wwwroot and $CFG->dirroot values keep working. Third-party plugins from the old layout must be relocated by hand into public/mod/, public/theme/, public/blocks/, public/local/ and so on. Plugins left in the old positions will not be found, and local/ is the easiest directory to overlook, because so much contrib code lives there.

The CLI scripts themselves do not move. admin/cli/ stays at the installation root alongside public, so every command on this page is still run from the installation root on 5.1 and later.

The pre-upgrade audit

Before touching anything, I want a written answer to each of these:

  • Current release and point release, from admin/cli/cfg.php --name=release.
  • PHP version, extensions and max_input_vars; database engine, version and collation.
  • Every installed plugin with its version, its maintainer, and whether a release exists for the target. Anything with no commits for two years is treated as abandoned until proven otherwise.
  • Theme: stock, child theme, or bespoke. If bespoke, whether the source is under version control and whether anyone can still build it.
  • Authentication and enrolment methods in use. LDAP, OAuth 2, SAML via a third-party plugin, or manual. Anything relying on a removed core plugin is a blocker, not a detail.
  • Integrations: WordPress, an SSO bridge, a CRM, web service tokens, LTI tool registrations.
  • Database size, moodledata size, and how long a full restore actually takes on that hardware.
  • The real quiet window. Not the theoretical one.

The output is a target version and a hop sequence, with the plugin decisions made in advance rather than discovered halfway through the cutover window.

Staging first, with a rollback that has been tested

Every upgrade is rehearsed on a clone before it touches production. The clone needs the same PHP and database versions as the intended production end state, otherwise it is not a rehearsal.

Take a full backup of all three components. They are only useful together:

sudo -u www-data php admin/cli/maintenance.php --enable
mysqldump --single-transaction --routines --triggers moodle | gzip > moodle-db.sql.gz
tar -czf moodledata.tar.gz /var/moodledata
tar -czf moodlecode.tar.gz /var/www/moodle

On PostgreSQL, use pg_dump -Fc instead. Then restore that backup onto the staging box and confirm the restored site actually loads. An untested backup is a hope, not a rollback. The rollback plan is the restore procedure you just ran, with the DNS or load balancer step written down.

Run each upgrade hop on staging non-interactively:

sudo -u www-data php admin/cli/upgrade.php --non-interactive

--non-interactive is the flag that matters: without it the script stops and waits for a confirmation, which is fine at a keyboard and useless inside a deployment script. If you are deliberately upgrading onto a build Moodle has not yet marked stable, add --allow-unstable as well, which the script requires in non-interactive mode for those versions.

Keep the full output. The warnings that scroll past during the first hop are usually the explanation for whatever misbehaves three hops later.

The cutover

The production run is the staging run repeated, with nothing improvised. Enable maintenance mode, take the fresh backup, swap the code, restore config.php to the correct location for the target version, adjust the document root if you are crossing 5.1, run the upgrade, then:

sudo -u www-data php admin/cli/purge_caches.php
sudo -u www-data php admin/cli/maintenance.php --disable

Caches must be purged explicitly. A stale cache after an upgrade produces symptoms that look exactly like a broken upgrade, which sends you diagnosing the wrong thing entirely.

Post-upgrade verification

Two commands do most of the work:

sudo -u www-data php admin/cli/check_database_schema.php
sudo -u www-data php admin/cli/checks.php -v

The first compares the live schema against what the installed plugins declare and exits non-zero on a mismatch, which catches a half-applied migration before your users do. The second runs Moodle's system checks; --filter=environment narrows the output to the server requirement checks, and --type selects a different set, such as the security or performance checks, instead of the default status set.

After that, the manual pass: log in as an administrator, a teacher and a learner. Open a course with each activity type you actually use. Submit an assignment. Open a quiz. Confirm the gradebook calculates. Trigger a cron run and confirm messages send. Check that scheduled tasks are not failing. Confirm any SSO or WordPress integration still round-trips a login.

Then check Site administration > Plugins > Plugins overview for anything flagged missing from disk, and clear it deliberately rather than leaving orphaned tables behind. The uninstall script runs in dry-run mode unless you tell it otherwise, so you get a preview first:

sudo -u www-data php admin/cli/uninstall_plugins.php --purge-missing
sudo -u www-data php admin/cli/uninstall_plugins.php --purge-missing --run

The first prints what would be removed. The second actually removes it. Read the first output properly before running the second, because this is not reversible without the backup.

If you are running IOMAD

IOMAD ships a version for each Moodle release line, but it is packaged separately and lands later. Its own stated target is three months after each Moodle release, and the lag has run longer than that: IOMAD 5.1 arrived in March 2026 against Moodle 5.1 in October 2025, and as of August 2026 the newest IOMAD line was still 5.1, with Moodle 5.2 out since April. So your target is an IOMAD branch rather than a Moodle tag, and the branch you want may not exist yet for the newest Moodle line. Plan the timing around IOMAD's calendar, not Moodle's.

Company structures, per-company themes and licence records all need checking after the upgrade, not just courses. If you are weighing platforms at the same time, I have written separately about multi-tenant Moodle with IOMAD and how it compares in IOMAD versus Moodle Workplace.

How I run an upgrade

I am Rohin Grover, and Hooknot Digital is a one-person studio. It is not a Moodle Partner and does not claim to be. You deal with the person doing the work, not an account manager.

The sequence is the one above: audit, target and hop plan agreed in writing, staging rehearsal, backup and rollback tested, cutover in a window you choose, verification pass, then a short period where I stay available for anything that surfaces once real users are back on the site.

Behind that is seven-plus years of hands-on Moodle administration: installation, day-to-day administration, migration, course building, reporting, theme adjustments and troubleshooting. The specific Moodle projects I can point to are few, and I would rather state them plainly than dress them up: an upgrade onto the 3.11 line, a migration from MoodleCloud to a self-managed AWS server, a WordPress and Moodle integration with single sign-on, and a Moodle training site built with the Edumy theme. There is more detail on the work page, and the services page covers the rest of what I do around Moodle.

What you need to provide

  • SSH access to the server, or a hosting control panel with shell and database access.
  • Database credentials, or a recent dump plus a copy of moodledata.
  • A Moodle administrator account.
  • Somewhere to put staging: a spare VPS, a subdomain, or approval for me to spin one up.
  • DNS or load balancer access if the cutover involves a switch.
  • A named person who can answer "is this how it looked before?" during verification.
  • Any theme or plugin source that is not publicly available.

If some of that is missing, say so early. Working around absent access is usually possible, but it changes the plan and it is better known at the start.

Start with the version, not the quote

The first useful thing is knowing which version you are on, which target makes sense, and how many hops sit in between. That is a short conversation, and you are welcome to take the answer and do the upgrade yourself.

Run the cfg.php command above, note the release string, and get in touch with it, or book a 30-minute session and we can look at it together. Email works too: rgrover@hooknot.com. I reply personally, usually within a working day, which is a habit rather than a service level agreement. If you would rather start with something small and scoped, I also take Moodle work through Fiverr.

Common questions

What is the latest version of Moodle right now?
As of August 2026 the current release line is Moodle 5.2, released on 20 April 2026. The point releases published on 10 August 2026 were 5.2.2, 5.1.6, 5.0.9 and 4.5.13. The long-term support release is Moodle 4.5, released October 2024, with security support running to 4 October 2027. The next LTS, Moodle 5.3, is scheduled for 5 October 2026 and will carry security support to 1 October 2029.
Can I upgrade from Moodle 3.11 straight to the latest version?
No. Moodle only carries database migration steps back a limited distance, and each release states the oldest version it accepts. Moodle 5.2 can only be upgraded from 4.4 or later, Moodle 5.3 only from 4.5 or later, and 5.0 and 5.1 only from 4.2.3 or later. From 3.11 you need intermediate hops, typically 3.11 to 4.1.x, then to 4.5.x, then to your final target. Landing on 4.5 is worth doing deliberately, since it clears the floor for both 5.2 and 5.3. Each hop needs its own backup and verification.
What PHP version does Moodle 5.2 require?
Moodle 5.2 requires PHP 8.3.0 as a minimum and supports PHP 8.3.x and 8.4.x. Moodle 5.3 holds the same 8.3.0 floor. Only 64-bit PHP builds are supported. The sodium extension is required and max_input_vars must be at least 5000. Earlier lines differ: Moodle 5.0 and 5.1 need PHP 8.2.0 minimum, while Moodle 4.4 and 4.5 need PHP 8.1.0 minimum.
Is Moodle 4.5 still supported in 2026?
Yes, but only for security fixes. Moodle 4.5 is the LTS line as of August 2026. Its general bug-fix support ended on 6 October 2025, and security support continues to 4 October 2027. That gives it a longer remaining runway than Moodle 5.0, whose security support ends on 5 October 2026. Moodle 4.4 and everything older, including the 4.1 LTS, left security support on 8 December 2025.
What database versions does Moodle 5.2 need?
Moodle 5.2 requires PostgreSQL 16, MySQL 8.4, MariaDB 10.11.0 or SQL Server 2019, and Moodle 5.3 requires the same. Those figures belong to 5.2 and 5.3 only. Moodle 4.5's minimums are lower: PostgreSQL 13, MySQL 8.0, MariaDB 10.6.7 and SQL Server 2017. Oracle and SQLite support were both removed in Moodle 5.0, so an Oracle-backed site faces a database migration as well as an upgrade.
What happens to Chat, Survey, Atto and CAS when I upgrade to Moodle 5.0?
They were all removed from core in Moodle 5.0, along with the MNet plugins, mlbackend_php, Oracle and SQLite database support. Critically, if those plugins are not reinstalled from their standalone repositories before the upgrade completes, their database tables are dropped during the upgrade and the data goes with them. Decide in advance whether you are keeping or discarding chat logs and survey responses, and back up either way.
Will upgrading Moodle break my custom theme?
Very likely if you cross Moodle 5.0 or 5.1. Moodle 5.0 moved the Boost theme to Bootstrap 5, so any child theme or template still using Bootstrap 4 class names renders incorrectly rather than failing visibly, which makes it easy to miss. Moodle 5.1 then moved web-accessible code into a public directory, so themes must be relocated to public/theme/ and the web server document root updated.
How do I check which Moodle version I am running?
Run this from the Moodle installation root as your web server user: sudo -u www-data php admin/cli/cfg.php --name=release. It prints a string such as 5.1.6 (Build: 20260810). The first two numbers are your release line, which determines your support dates. The third is your point release, which should always be the newest available on that line, since point releases carry security fixes. On Moodle 5.1 and later the admin/cli directory is still at the installation root, alongside public, not inside it.
Do I need to upgrade if my Moodle is working fine?
If your release line is still within its security support window and you are on the newest point release, there is no urgency. If it is past the security date, you are running an application with publicly documented vulnerabilities and no fixes coming, which is a compliance problem as much as a technical one. Check your line against the support dates first, then plan around the next LTS rather than upgrading twice.

Talk it through with Rohin

Bring the messy version of the problem. A free 30-minute session is usually enough to tell you whether it is a small fix or a real project, and what it would take either way.

Rohin's Brain
Ask about Moodle, IOMAD multi-tenant LMS, plugins, reports, support, or whether your project is a fit for Hooknot Digital.
Schedule time with Rohin