Moodle customization

Moodle customization covers the changes that go beyond configuration: custom plugins, themes, reports and workflows. This page explains how to choose the right method for each need, what drives cost, and how to keep changes working through every release.

On this page

What Moodle customization covers

Moodle customization is any change to the platform that goes beyond what an administrator can set in the Moodle interface. Turning on a feature, changing a role assignment, editing a site-wide setting or adjusting a course format is configuration. Writing a new report, adding an approval step to a course request, altering how a template renders or building logic that calls an external system is customization. This page treats those changes as their own body of work. Installing and configuring Moodle for the first time, moving data in from another system and upgrading between releases are covered in their own sections, although customizations affect each of them.

Customization usually starts from one of four triggers. The first is a requirement that core Moodle and existing contributed plugins cannot meet, such as a grading rule or enrolment logic specific to your institution. The second is a reporting or approval workflow the institution must run, where auditors, faculty committees or administrators need outputs and sign-offs that the standard tools do not produce. The third is a branded or accessible front end, which usually means theme work tested against accessibility requirements. The fourth is an integration that needs custom logic on top of a standard connector, for example when a student information system sends data in a shape that Moodle's default import does not expect.

Teams usually handle small, well-documented changes in-house and bring in a partner for larger or riskier ones. The deciding factors are whether your staff can write PHP against Moodle's own APIs, who owns each release and its upgrade cycle, and how many changes exist. A single report built on an existing plugin is a different job from forty local modifications that must survive every six-month release. Before you decide, list each planned change, note which Moodle API or plugin type it would use, and name the person who will fix it after the next upgrade.

What the work includes

A customization engagement usually moves through a register, a decision per item, build work, and handover. Each workstream below ends with artifacts your team keeps, so the site can be upgraded without rediscovering what was changed.

Requirements and customization register

A single register lists every requested change, its business owner, the Moodle area it touches, and its acceptance criteria. For each entry, check whether the need is already met by core settings, which keeps custom code limited to gaps that remain after configuration is reviewed.

Decision record for each item

Each register item gets a short decision record stating whether it is solved by configuration, a contributed plugin, or custom code, with the reason and the upgrade risk accepted. Ask for these records before build starts, since they show later why a change exists and whether it can be retired.

Custom plugins by type

Custom functionality is built as plugins of the type that fits the need, such as local plugins for site-wide features, report plugins for data views, block plugins for dashboard content, admin tools for maintenance tasks, or activity modules for new course content. Confirm the plugin type list against the Moodle plugin types documentation for your target release.

Theme changes and workflow logic

Brand and layout changes are delivered as a child theme or theme overrides, not edits to core files, so updates do not overwrite them. Workflow logic such as enrolment rules, completion triggers, or approval steps is implemented through supported APIs and events. Check that each override is listed in the register so reviewers can find it at upgrade time.

Reports and data extracts

Reports are built against Moodle's database access and reporting APIs, with queries documented and reviewed for performance on large course and log tables. Ask for a list of every report's data source, its permission model, and the schema tables it reads, since schema changes between major releases are a common cause of broken reports.

Tests, packaging and documentation

Deliverables include a test suite covering custom code, packaged plugins in your repository with install and upgrade notes, and a list of known upgrade risks per item. Ask that the source sit in your own version control, that tests run against the Moodle releases you plan to use, and that the upgrade risk list is updated at each release.

What drives cost and duration

This table lists the factors that make a Moodle customization larger or slower to build, and how to keep each one contained, so you can compare scope options in a quote.

DriverWhy it mattersHow to keep it down
Requirements not met by configurationEach need that core settings, roles and contributed plugins cannot meet becomes custom code to write, test and maintain.Map every requirement against core and existing plugins first, and change the process where a standard feature covers most of the need.
Number of plugin types touchedActivity modules, blocks, local plugins, reports, enrolment and auth plugins each have their own structure and review needs, so spreading work across types widens the test surface.Consolidate related features into one plugin type where possible and confirm the plugin type fits the job before build starts.
Reliance on core internals versus documented APIsCode that calls undocumented core functions or edits core files breaks on upgrade and often needs rework for every major release.Build against documented core APIs and the plugin developer docs, and avoid patching core files.
Reports against large data setsCustom reports over large course, grade or log tables can slow the site and need query tuning and load testing before exam periods.Agree the data fields and reporting frequency up front, and ask for query review and a test on production-sized data.
Workflow complexity and approval rulesMulti-step approvals, conditional routing and notifications multiply states, roles and edge cases that must be tested.Limit each workflow to the states the business actually uses and document the rules in a single approved specification.
Theme depthHeavy template overrides, custom SCSS and layout changes must be re-checked after each Moodle release and each theme update.Use a child theme, keep template overrides few, and limit visual changes to brand elements and layout needs.
Number of environments and test casesEach environment needs deployment and data refresh, and each test case must be rerun for every change and upgrade.Agree the environments needed (for example development, test and production) and a prioritized set of regression tests.
Accessibility requirementsCustom pages and themes must be checked against the accessibility standard your organization adopts, which adds design review and assistive technology testing.State the accessibility target in writing and ask for testing against it as part of acceptance.
Number of supported Moodle versionsRunning custom code on more than one release line, such as during a staged upgrade, roughly doubles compatibility work for each version.Plan to support one target version at a time and confirm the upgrade window before adding new features.
Number of external systems involvedEach integration, such as SSO, HR feeds or grade return, needs its own contract, error handling, test data and monitoring.Confirm which external systems exchange data with Moodle and whether a standard plugin or web service already covers the exchange.

Project phases and outputs

The sequence turns a Moodle customization request into tested, documented changes that survive the next release, with a recorded decision for every item.

  1. Fix the target release and its requirements

    Before any design, the team confirms the Moodle release the site will run and its platform requirements from the release notes, including PHP version, database engine and version, and the upgrade starting point. Your team and DeployOpen agree the target in writing. Output: a short target statement listing release, PHP, database, web server document root and support end dates, signed off by the client's technical owner.

  2. Gather requirements and run gap analysis

    DeployOpen collects the requirements from business owners, teachers, administrators and integration owners, then compares each one against the target release. Each need is marked as already met by core, reachable by configuration, or a gap. Output: a requirements register and a gap list that your stakeholders have reviewed and accepted as complete for the scope.

  3. Record a decision for each item

    For every gap, the team writes a decision record stating whether it will be solved by configuration, a contributed plugin, or custom code, with the reason, the maintainer or support status of any plugin, the expected upgrade impact and the owner. Output: a decision register approved by your team, which becomes the basis for the quote and the design.

  4. Design plugins, reports and workflows

    The approved custom items are designed in detail: plugin type and core APIs to use, data model, report definitions, capabilities and roles, workflow triggers and the test cases that prove each behavior. Output: a design document and test plan that your administrators and data owners sign off before build begins.

  5. Build with automated tests

    Developers build the configuration, plugins and code against the target release, with unit and behavior tests, code review and version control. Configuration changes are exported so they can be reproduced. Output: a tagged build in your repository, passing test results and a list of any deviations from the design, each approved by the client.

  6. Test on a staging copy of the target release

    The build is deployed to a staging environment running the exact target release, web server layout and database version, with a copy or representative sample of production data. Users run the acceptance scripts, and the team checks performance, cron, and logs. Output: a signed acceptance report listing passed tests, open defects and a go or no-go recommendation.

  7. Hand over with documentation and an upgrade checklist

    DeployOpen delivers the code, configuration exports, decision records, admin and user guides, and an upgrade checklist that lists each customization, its plugin or core dependency, its test cases and the steps to re-test on the next release. Your administrators are trained on the handover material. Output: a handover package accepted by your operations owner.

What stays in-house and what to outsource

This table shows who usually owns each part of Moodle customization work and which skills that work requires, so you can see where a partner adds capacity and where your own team must keep control.

Work areaUsual ownerSkills needed
Requirements and process ownershipIn-house: academic and administrative owners with the Moodle administratorKnowledge of course, grading and enrolment rules, plus the ability to decide which requirements justify custom code
Configuration-first reviewIn-house, with partner support for options the team has not used beforeMoodle administration, role and capability configuration, familiarity with core settings and existing plugins
Contributed plugin vettingShared: in-house decides, partner reviews code and maintenance historyPHP code reading, Moodle plugin APIs, checking plugin support for the target Moodle versions, security review
Custom plugin buildPartner builds, in-house reviews and accepts the codePHP, Moodle plugin APIs for the chosen plugin type, unit and behat testing, packaging for upgrades
Theme and report workPartner for build, in-house for brand and content decisionsTheme development with Mustache templates and SCSS, accessibility checks, SQL for reports, Moodle report builder and APIs
Upgrade testing across Moodle releasesShared: partner runs test cycles, in-house signs off each releaseRelease testing, PHP and database version checks, plugin compatibility checks, rollback planning
Ongoing ownership of the custom code registerIn-house, always, with the partner documenting each changeMaintaining a list of every custom and contributed plugin, its version, its owner and its target Moodle release

What usually goes wrong

Most Moodle customization problems come from a small set of decisions made early and never revisited. Each card names one failure mode and the check that prevents it.

Custom code for solved needs

Teams often write a block or local plugin for a requirement that a core setting, a role change or a maintained contributed plugin already meets. Every custom line then needs testing and maintenance for each release. Before any build, check core settings, the plugins directory and the plugin's release history for the target Moodle version.

Direct edits to core files

Changing files inside the core Moodle folder turns every upgrade into a manual merge and makes security patches harder to apply cleanly. Custom behavior should live in plugins, child themes or local overrides that sit outside core. Ask the team to show that no core file differs from the official release for the installed version.

Calls to internal functions

Code that relies on undocumented internal functions or on the current shape of database tables can break silently after a minor or major release. Build against the documented core APIs for the plugin type and review each call during upgrade testing. Where no documented API exists, record the dependency so it is reviewed first at each upgrade.

Unmaintained contributed plugins

A contributed plugin that has no release for the target Moodle version can block an upgrade or stop working after a security fix. Check the plugin's listed supported versions, last update and issue activity before adopting it. Plan a replacement or a fork owner for any plugin that lacks support for the release you intend to run.

Theme overrides that drift

Copied and edited templates or styles break when Moodle changes the markup or stylesheets they were copied from. Keep overrides small, use a child theme and list every overridden template with its source version. Review those overrides at each upgrade, since the Classic theme was removed from core in Moodle 5.3, showing how a base theme can disappear between releases.

Reports that slow under load

Custom reports that work on a test course can time out on production data with years of logs, grades and enrolments. Query design, indexes and report scheduling decide whether the report runs at all. Test each report against a production-sized copy of the database and agree on which reports run on a schedule instead of on demand.

Custom code without an owner

After handover, custom plugins often have no named maintainer, no test suite and no record of why each decision was made. The next upgrade then stalls or the code is left on an old release. Agree who owns each customization, where its source lives, and how it is tested and reviewed before the project closes.

How the work differs by starting point

When the site has not launched, customization can be designed alongside the course structure, roles and integrations, so most decisions are made before any learner depends on them. The work centers on fixing requirements first and choosing the simplest mechanism for each one.

  • First step: list every requirement and map each one to configuration, a contributed plugin, or custom code, then record the choice and the reason.
  • Approach: prefer settings, roles and existing core features, and reserve custom code for gaps that remain after that review.
  • Plugin vetting: confirm each contributed plugin lists support for the Moodle release you plan to run, before it enters the build.
  • Main risk: scope creep during build, where ad hoc requests add plugins or theme overrides that nobody later owns or tests.
  • Ask your partner: how the requirement register will be kept current and who approves additions before go-live.

What the client needs to provide

A fixed-scope quote for Moodle customization is only as firm as the inputs behind it. Before a partner can write one, the client should assemble a written requirements list in which every item states the business reason it exists, such as a teacher workflow, a compliance report or a brand requirement. Requirements without a reason tend to be cut or rebuilt late, and the reason is what lets a reviewer choose between configuration, a contributed plugin or custom code.

Next, supply the technical baseline. That means the current Moodle version, a list of every installed plugin with its source (the plugins directory, a vendor, or an in-house repository), and any local code, theme changes or core edits. Ask each contributed plugin's maintainer which Moodle versions it supports before scoping, because a plugin that has no release for the target version changes the work. Also name the target Moodle release and its required PHP and database versions, since these decide whether the existing server stack can be reused.

Provide access to a staging environment that matches production in Moodle version, plugin set, web server document root and database engine. For report work, supply sample or anonymized data that reflects real course, enrolment and grade structures, so report logic can be tested without exposing personal data. Confirm with your privacy or data protection lead how that data is anonymized before it leaves your environment.

Finally, name decision owners for each requirement and a technical owner who will receive the code, documentation and administrator handover. Decision owners approve trade-offs such as a custom report versus a standard one. The technical owner must be able to review code, run upgrades and manage plugin updates after go-live, so their name should be recorded in the scope before work starts.

Common questions about Moodle customization

How much does Moodle customization cost and what drives the price?

Cost depends on how much of the requirement can be met by configuration, how many customizations are needed, and how much they must integrate with other systems. Most of the spend goes to requirements analysis, design, build, testing and documentation. Main drivers:

  • Number and complexity of custom plugins, themes or reports
  • Integrations with HR, SSO or student information systems
  • Testing scope, including each target release
  • Data and accessibility requirements

Ask for a fixed-scope quote that lists each deliverable, the assumptions behind it, and any recurring costs for maintenance and upgrades. DeployOpen does not publish a price list, so the written scope determines the quote.

How long does a Moodle customization project take?

Duration depends on the scope agreed in writing, the number of customizations, and how many external systems must be connected. Plugin and theme work usually moves faster when requirements are settled before the build starts. What changes the timeline:

  • Late changes to requirements or approval workflows
  • Dependencies on third-party systems and access approvals
  • Upgrade timing, such as a target release that is not yet available
  • Accessibility and security review cycles

Ask for a timeline with milestones, named client dependencies and a testing window, rather than a single end date.

Is a configuration change always cheaper than writing custom code?

Not always. Configuration is usually cheaper to build and easier to upgrade, but it can become expensive when many settings must be maintained by hand or when workarounds pile up. Custom code costs more up front and adds ongoing testing, yet it can be the simpler option when a requirement is core to how the organization works. Compare the cost of building, the effort to keep each option working after upgrades, and the number of administrators who must understand it. Ask the implementation partner to show which requirements are met by configuration and which need code.

How do you keep Moodle customizations working after an upgrade?

Keep customizations on Moodle's documented APIs, avoid editing core files, and test every custom component against each target release before the upgrade. Moodle ships major releases twice a year and point releases in between, so the upgrade path should be planned early. Practices that help:

  • Use the plugin types and core APIs documented by Moodle
  • Keep custom code in version control with a reproducible build
  • Run automated and manual tests on a staging copy of the production data
  • Confirm that each third-party plugin supports your target release

Always confirm plugin support for your target release with the plugin maintainer before scoping the upgrade.

Can an in-house team maintain custom Moodle plugins?

Yes, if the team has PHP and Moodle plugin experience, time for upgrades, and documentation that explains each component. Many organizations find that the hardest part is not writing the plugin but keeping it working after each release. Questions to answer before deciding:

  • Who reviews code and owns security patches?
  • Who runs upgrade tests each release cycle?
  • Is there cover when a key developer leaves?
  • Does the team have a test environment that matches production?

A partner can build, document and hand over the plugins, or provide ongoing support under a retainer. Decide based on the team's capacity, not only on the build cost.

Should we use a contributed plugin or write custom code?

Start with the contributed plugin when one meets the requirement, is actively maintained and supports your target Moodle release. Write custom code when no plugin fits the requirement, or when the available plugin adds features, dependencies or data handling you cannot accept. Check before deciding:

  • Support for your target release and the release history of the plugin
  • Maintainer activity and license terms
  • Permissions, data flows and security review results
  • How much local change the plugin would need

If you customize a contributed plugin heavily, you take on its maintenance, so weigh that cost against building a focused plugin of your own.

How DeployOpen delivers Moodle customization

DeployOpen plans, builds, documents and supports Moodle customizations inside your own infrastructure, starting from a written scope that decides whether each need is met by configuration, a contributed plugin or custom code. Engagements are fixed-scope, and ongoing support is available as a retainer.

How we scope

  • We list each requested change and classify it as configuration, contributed plugin or custom code before any build starts.
  • The written scope names the Moodle release, plugin types, themes, reports and workflows covered, and what is excluded.
  • We confirm the target PHP and database versions, and the upgrade path, against the release notes for your chosen Moodle version.

How we build

  • Custom plugins use Moodle core APIs and standard plugin types, so each one stays inside documented extension points.
  • Theme work uses child themes and standard templates and styles rather than edits to core files.
  • Every customization is kept in version control with a repeatable deployment process and test environment.

How we hand over

  • Handover includes source code, configuration records, admin notes and a record of each plugin version and its dependencies.
  • We document how each customization is upgraded and which checks must pass before a Moodle release is applied.
  • Administrators and course staff receive training on the workflows and reports built for their roles.

How we support

  • Support covers plugin compatibility checks and upgrade testing against each Moodle release in your planned upgrade window.
  • Ongoing support is available as a retainer, with scope, response expectations and release testing agreed in writing.
  • Changes after go-live follow the same scoping and version control process, so new work remains upgrade-safe.

Sources and further reading

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.