Moodle 5.3 LTS review: what it changes for plugin code

Moodle 5.3 shipped on time with a first REST API, React navigation and dark mode. What breaks in custom plugins, what is new, and what is still missing for 6.0.

Drawing of a builder fitting a new blue door into an old stone building that is still surrounded by scaffolding.

Moodle 5.3 is the current release. It shipped on 5 October 2026, on schedule, as a long term support release.1 The next major release, 6.0, is set for 19 April 2027 in the tracker.2

Our verdict: 5.3 is a good LTS and a careful one. It does not add a new architectural layer. It finishes and connects the layers that 4.3 to 5.2 started: routing gets its first real REST API with OAuth 2, React moves from “available” to “rendering core navigation”, and dependency injection becomes the recommended way to write controllers. The bigger breaks are queued for 6.0.

We covered the history in Moodle’s architecture from 1.0 to 5.3 and the server requirements in our Moodle 5 post. This post is about the code: what 5.3 changes for custom plugins, and what it tells you about where Moodle HQ is going.

What is shipped, in progress or only announced?

The status of each item in this post:

ItemStatusSource
Moodle 5.3 LTSShipped 5 Oct 2026Release notes
REST API with OAuth 2 and personal access tokensFirst slice shipped; epics MDL-76834 and MDL-87215 still openRelease notes, tracker
React rendering primary and secondary navigationShippedUPGRADING.md
Attribute-based DI, Symfony ConsoleShippedRelease notes
Boost dark modeShipped as experimental, off by defaultRelease notes
Classic themeRemovedRelease notes
Composer required to install MoodleIn development for 6.0 (MDL-89515)Tracker
Removing legacy lib.php and locallib.phpOpen epic, no fix version (MDL-84505)Tracker
LTI moved into coreIn development (MDL-79109)Tracker
Third-party AI actions and placementsOpen epic (MDL-89121)Tracker
Moodle 6.0Planned for 19 Apr 2027Tracker
Moodle Marketplace, Certified IntegrationsLaunched July 2026moodle.com

What changed in the architecture?

Five things matter for plugin code. Everything below is from the 5.3 release notes and the 5.3 section of core’s UPGRADING.md.34

A real REST API, finally. The routing system from 4.5 and 5.1 now carries a REST API with its own authentication. 5.3 ships an OAuth 2 server (MDL-89251), a client manager, token revocation, a Swagger UI with OAuth 2 support, and personal access tokens that users create on their own page, gated by a new moodle/api:createtoken capability (MDL-87706).34 Tokens carry scopes. They are separate from old web service tokens, and the “Enable web services” setting does not affect them.5 The catch is in the docs: “In Moodle 5.3, only a few parts of Moodle are available through the REST API. More will be added in later releases.”5

React is now how core renders navigation. In 5.2 React was an option. In 5.3 the primary and secondary navigation bars are React components built on the design system’s NavPill, and the edit mode switch is the design system Switch (MDL-87830, MDL-89294, MDL-89814).4 PHP gets a proper bridge: html_writer::react_component() and a react_component_renderable interface, so a renderer can hand props to a React component without writing the mount div by hand (MDL-89296). There is also a swizzle script that lets a theme eject or wrap a core React component (MDL-88509), and heavily used AMD modules were converted to ES modules (MDL-88762).43 Our React post covers how to build with it.

Dependency injection by attribute. #[\DI\Attribute\Inject] on a property now works, and UPGRADING.md calls it “the best practice and recommended approach for use in controllers” (MDL-89528).4 Core is following its own advice. Password and authentication plugin functions now delegate to DI-resolvable classes, \core\authentication\password and \core\authentication, and login checks moved into a new \core_auth\validate_user class (MDL-88580).4

More global functions become classes. Twenty-five functions from user/lib.php moved to new classes, almost all to static methods on \core\user (MDL-82650). The old non-namespaced \external_api, \external_value, \external_single_structure and friends are deprecated in favour of the \core_external versions (MDL-81225). Both still work with debugging notices, until a later release removes them. Separately, dozens of admin setting classes got autoloaded names under \core_admin\setting, and the old names are not deprecated yet.4

New hook for outgoing mail. email_to_user() now dispatches a before_email_to_user hook. A listener can change the content, add headers or block the email with a reason (MDL-69724).4 Blocking or rewriting mail used to mean a core edit or a custom message processor. Now it is a hook in a normal plugin.

The AI subsystem got plumbing, not a new architecture: an Anthropic Claude provider (MDL-88674), a course-level AI usage report (MDL-80893), and normalised AI action tables (MDL-89123).3

What will break in custom plugins?

Most 5.3 changes are deprecations that only emit debugging notices. These are the ones that can break things on day one:

  • Themes based on Classic. Classic is gone. On upgrade, customised Classic settings are copied to Boost and Classic is uninstalled. Block positions are not migrated: Boost has one block column, so blocks from Classic’s second column end up at the bottom of the default region. A $CFG->theme = 'classic' line in config.php must be removed by hand.4
  • CSS and JavaScript aimed at the navbar. The primary and secondary navigation no longer use .nav-link and .moremenu. They render a.mds-nav-pill items. Theme overrides of core/editswitch need reviewing too.4
  • Course format templates. Course index semantics for subsections moved, the collapse-all toggle lost its collapsesections id, and Boost’s drawer replaced the drawerheadercontent block with drawercontrols (MDL-88949, MDL-89050).4 Custom course formats that override these templates need checking.
  • Hard-coded colours, once dark mode is on. Dark mode is off until an admin turns on the experimental setting. When they do, a plugin that sets a light background but lets text follow the mode loses contrast. The notes ask plugins to use Bootstrap and design system custom properties.4
  • Direct SQL on AI tables. prompttokens and completiontokens moved from the action child tables to ai_action_register. Reports that query them directly will fail (MDL-89123).4
  • Modal headings. Modal titles are now <h2>, not <h5>. Headings inside your modal content should start at <h3>. Behat steps that find headings by level can fail.4
  • Bootstrap imports. Importing theme_boost/bootstrap/* from AMD is deprecated. On 5.3 the import is bootstrap. Code that must also run on 5.2 can use theme_boost/index, which is supported until 7.0 (MDL-88766).4

Also worth knowing: uninstalling a block plugin now deletes its instances in a background task instead of during the uninstall (MDL-89289), and NO_MOODLE_COOKIES is now only the starting value for new session manager methods (MDL-87174).4

The general upgrade checklist still applies on top of this list.

What is newly possible?

  • Integrations without the old web services. An external system can sign users in through an OAuth 2 flow, or a user can hand a script a personal access token, both scoped and revocable.5 Machine-to-machine flows and refresh tokens are in the scope of the still-open OAuth 2 epic.6 Today all of this only covers the endpoints that exist. The design is sound, though, and new endpoints a plugin adds through the router get the same authentication.
  • React from PHP. A plugin renderer can return a React component through $OUTPUT->render() with typed props. Mixed pages, part Mustache and part React, are now a supported pattern rather than a workaround.
  • Mail control as a plugin. Filtering, rewriting or blocking outgoing email (for compliance rules, test sites, or tenant branding) fits in a hook listener.
  • Cleaner CLI and controllers. Symfony Console for CLI scripts and attribute injection for route controllers make new plugin code look like any modern PHP project.
  • Faster plugin CI. PHPUnit database snapshots (MDL-88495) landed in 5.3. We covered the numbers in our developer experience post.

What is coming in 6.0?

Moodle 6.0 is planned for 19 April 2027.2 Its requirements are still being decided in MDL-88696, which was open on 31 October 2026.7 Nothing below is promised. These are open tracker epics updated in the last few months:

  • Composer becomes mandatory. MDL-89515: “we are looking to require and mandate the use of Composer from Moodle 6.0 onwards.”8 Hosting and deploy scripts that copy a zip and run the installer will need a composer install step.
  • lib.php callbacks on the way out. MDL-84505 wants to “deprecate all of these uses by Moodle 5.2 and remove the legacy files in 6.0 per deprecation policies”.9 The 5.2 target has passed and the epic has no fix version, so treat 6.0 as the start of this, not the end.
  • More REST endpoints. MDL-90030 is the first reference endpoint, covering everything you can do with a user, with an OpenAPI spec published as a draft during development.10
  • LTI in core. MDL-79109 moves most of mod_lti into a core subsystem so LTI tools can appear in other placements. Eight slice epics for it were filed on 30 October 2026.11
  • AI that plugins can extend. MDL-89121 aims to let “third-party plugins extend AI subsystem actions” and placements.12 Today plugins can add providers and placements but not new action types.
  • Deprecations come due. Under the deprecation policy, code deprecated in a non-LTS release reaches final deprecation in the first release of the next series, and final deprecation removes the function body.13 The policy’s own example puts 4.5 LTS deprecations at final deprecation in 6.0 too. Deprecation notices from 4.5 to 5.2 in your logs are your 6.0 failure list.

One proposal in MDL-88696 is to drop Microsoft SQL Server in 6.0. It is a comment, not a decision.7

What else did Moodle HQ announce?

Not much for developers. The 5.3 announcement leads with “learning with intent” and mentions OAuth 2 for web services in one line.14 HQ’s partner summit write-up from Barcelona, published 30 October 2026, reports that Moodle Marketplace and the Certified Integration programme launched in July 2026, and quotes CEO Scott Anderberg that open source “gives organisations the transparency, flexibility and control they need to make confident choices”.15 There is no roadmap detail in it.

MoodleMoot Global was renamed MIX, the Moodle Ideas Exchange, in September 2025.16 We found no primary source with a date or venue for a MIX in 2026.

Where is Moodle HQ heading?

Three directions are now clear from shipped code and open epics, not from marketing:

  1. Moodle as an API platform. The REST API, OAuth 2, scopes, OpenAPI specs and Swagger point at Moodle as a backend that other systems, including mobile apps, call through standard HTTP. Moving LTI into core fits the same picture.
  2. A standard PHP and React stack. Composer, PHP-DI, Symfony Console, Slim routing, React and a design system. Each release removes a Moodle-only mechanism.
  3. AI as a product feature with admin controls. Every release since 4.5 added providers or reports. The next step on the tracker is extensibility for plugins, not anything for developers.

What is missing, slow or half done?

The REST API took a long time. MDL-76834 was opened in January 2023 and says “Targetted at Moodle 4.4”. The first usable slice arrived in 5.3, nearly four years later, with “only a few parts of Moodle” covered.175 It looks well designed. It is not yet something you can build an integration on without falling back to the old web services.

YUI is still in core. The META issue to migrate YUI3 has been open since January 2023, and the one for YUI2 since November 2012.18 5.3 even updates YUI dialogue SCSS variables for dark mode. Core is shipping React navigation and YUI dialogues on the same page.

Dark mode is half done by design. It is experimental and off by default, and every plugin with its own colours must be fixed before an admin can safely turn it on. The upgrade notes explain the rules well. The work still falls on plugin authors.

Nothing new for AI-assisted development. On 31 October 2026, moodledev.io/llms.txt still returns 404 and moodle/moodle still has no AGENTS.md. A tracker text search for “Model Context Protocol” returns one match, a closed task from an internal AI project sprint, and no issue proposing an MCP server.19 Our inference, not HQ’s: a scoped OAuth 2 REST API is exactly what an official MCP server for Moodle would sit on, and that would be a better use of this work than another provider plugin. Our developer experience post has the full scorecard.

Testing tooling is drifting. MDL-89129, to scope a Behat 4 upgrade “target: Moodle 5.3”, was still open after 5.3 shipped.20 Behat 3 cannot support Symfony 8, and Moodle now uses Symfony components itself.

DevLMS updates custom Moodle plugins for 5.3 and builds new ones on the routing, DI and React APIs. If you need a plugin moved to 5.3, hire a Moodle developer for a fixed price.

Sources

  1. Moodle HQ, Releases. ↑

  2. Moodle Tracker, MDL versions (6.0 release date 19 April 2027, checked 31 October 2026). ↑ ↑

  3. Moodle HQ, Moodle 5.3 release notes. ↑ ↑ ↑ ↑

  4. Moodle, UPGRADING.md, MOODLE_503_STABLE. ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑

  5. MoodleDocs, REST API tokens (5.3). ↑ ↑ ↑ ↑

  6. Moodle Tracker, MDL-87215: Add support for OAuth2 for routed web services. ↑

  7. Moodle Tracker, MDL-88696: Decide Moodle 6.0 requirements. ↑ ↑

  8. Moodle Tracker, MDL-89515: Require Composer for Moodle installation. ↑

  9. Moodle Tracker, MDL-84505: Deprecate the legacy lib.php and locallib.php. ↑

  10. Moodle Tracker, MDL-90030: Implement REST endpoints for User interactions. ↑

  11. Moodle Tracker, MDL-79109: Migrate the bulk of the mod_lti plugin to Moodle core. ↑

  12. Moodle Tracker, MDL-89121: Make AI subsystem extendable. ↑

  13. Moodle HQ, Deprecation policy. ↑

  14. Moodle.org, Announcing Moodle LMS 5.3 LTS: Learning with intent (5 October 2026). ↑

  15. Moodle, Moodle Global Partner Summit 2026: highlights from Barcelona (30 October 2026). ↑

  16. Moodle, MoodleMoot Global becomes MIX: Moodle Ideas Exchange (19 September 2025). ↑

  17. Moodle Tracker, MDL-76834: Web service modernisation. ↑

  18. Moodle Tracker, MDL-76864: META: Migrate all use of YUI3 and MDL-36373: META: Migrate use of YUI2 in core. ↑

  19. Moodle HQ, moodledev.io/llms.txt (404 on 31 October 2026); Moodle, moodle/moodle. ↑

  20. Moodle Tracker, MDL-89129: Scope Behat 4.x upgrade for core. ↑

Need a Moodle plugin built or rescued?

Tell the scoping assistant what you need. You get a fixed price and a timeline in a few minutes, and an engineer reviews it within one business day.

Get a fixed quote