How to audit third-party Magento extensions before an upgrade
A step-by-step way to check every third-party Magento 2 module against your target 2.4.x and PHP version: inventory, Composer constraints, static scans, staging tests and a decision per extension.
To audit third-party Magento extensions before an upgrade, list every module the store really runs, check each one's declared Composer constraints against the target Magento and PHP versions, and confirm the vendor supports that release. Then scan the code for patterns that break between 2.4.x releases, run the full build on a staging copy, and decide for each extension whether to update, replace, remove or rewrite it. Our Magento 2 upgrade checklist covers the whole upgrade project; this post goes deeper on the extension audit.
Why are extensions the main upgrade risk?
Adobe documents the backward incompatible changes in each release precisely so that third-party modules can keep working1. Core modules change with the release; third-party code changes only when its author updates it. A few examples from that page: 2.4.6 replaced the outdated Zend_Validate library with laminas-validator, with Zend_Filter and Zend_HTTP replaced in the same way; 2.4.8 notes that after the move to PHP 8.4 some modules and extensions hit breaking changes; and 2.4.9 replaced the deprecated Zend_Cache implementation with the symfony/cache component1.
PHP is the second pressure point. Each 2.4.x release line supports a narrow set of PHP versions. Adobe's system requirements list PHP 8.3 and 8.4 for 2.4.8 and PHP 8.5 for 2.4.9, for example2.
Step 1: which modules are installed, and which are actually used?
Start with Magento's own view of the module list. module:status accepts --enabled and --disabled filters3:
bin/magento module:status --enabled
bin/magento module:status --disabled
Then compare it with what Composer installed and what was copied in by hand:
composer show --direct
ls app/code
composer show --direct restricts the list to your direct dependencies4, which is usually the set of extensions someone chose to install. Anything under app/code that is not your own code was copied in, so Composer will not update it and you have to track its version yourself.
Look hard at two groups:
- Disabled but installed modules. A disabled module's code still sits in the codebase and its package still takes part in Composer's dependency resolution, so it can block an upgrade it adds nothing to. If it is not needed, remove it properly rather than carry it forward.
- Enabled but unused modules. A payment method switched off in configuration, a feed nobody downloads, an integration you have dropped. Check configuration and recent orders before you assume something is in use.
Step 2: do the declared constraints allow the target version?
Each package declares its needs in the require section of its composer.json, typically php, magento/framework and the Magento modules it extends:
cat vendor/<vendor>/<package>/composer.json
Composer can do the cross-check for you. The prohibits command (alias why-not) "tells you which packages are blocking a given package from being installed", and it also accepts platform requirements such as php4. For Magento Open Source the metapackage is magento/product-community-edition5:
composer why-not magento/product-community-edition 2.4.8
composer why-not php 8.3
Add --tree (or -t) to see the nested chain of packages behind each conflict4. An empty result for an extension does not prove it works; it only means its author did not declare a conflicting constraint. Treat this step as a fast filter, not a verdict.
Step 3: what does the vendor say about the target release?
For each extension that survived step 1, find out:
- whether a release exists that states support for the target Magento version and the target PHP version;
- what changed in that release, from the vendor's changelog or release notes;
- whether the module is still maintained at all.
Record the answer and its source. No statement for the target version means unknown, not compatible.
Step 4: what can static checks catch before you install anything?
Upgrade Compatibility Tool (Adobe Commerce only). Adobe's Upgrade Compatibility Tool checks a customised Adobe Commerce instance against a specific version by analysing all modules and core code6. Adobe states that it "is available for Adobe Commerce instances only"6, and you need Adobe Commerce access keys to download and use it7. On Magento Open Source it is not an option. On Adobe Commerce, the target version is set with -c, and --ignore-current-version-compatibility-issues limits the report to new issues introduced by the upgrade8:
bin/uct upgrade:check <dir> -c 2.4.8
bin/uct upgrade:check --ignore-current-version-compatibility-issues <dir>
Magento coding standard. Adobe's magento/magento-coding-standard package is a PHP_CodeSniffer ruleset. Its README installs it with composer require --dev magento/magento-coding-standard and asks you to register its path in PHP_CodeSniffer; then you run it against a module9:
vendor/bin/phpcs --standard=Magento2 vendor/<vendor>/<package>
PHPCompatibility for the target PHP version. The PHPCompatibility standard checks code against a PHP version you set with testVersion10. Its README installs version 10 with Composer:
composer config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true
composer require --dev phpcompatibility/php-compatibility:"^10.0.0@dev"
vendor/bin/phpcs -ps vendor/<vendor>/<package> --standard=PHPCompatibility --runtime-set testVersion 8.3
Without a testVersion you only get notices about deprecated or removed features10. Consider installing both in a separate tools directory rather than in the store's composer.json.
Dependency injection compilation. bin/magento setup:di:compile generates factories, proxies and interceptors for every enabled module11. Run it on the staging branch with the target version installed (step 6), where missing classes and mismatched constructors surface.
Step 5: which risky patterns should you look for by hand?
Search each extension for these patterns and check each hit against the backward incompatible changes for every release between your current and target versions.
| Pattern | Where to look | Why it matters |
|---|---|---|
| Preferences on core classes or interfaces | etc/di.xml, etc/*/di.xml | A preference node sets the default implementation of a type12; replacing a core class means its whole implementation has to follow core changes |
| Plugins on core methods | <plugin> nodes in di.xml | Plugins cannot be used on final classes or methods, non-public or static methods13; a signature change in core can break them |
| Around plugins | methods prefixed around | Adobe advises avoiding them when not required because they increase stack traces and affect performance14 |
| Overridden core templates and layouts | view/*/templates, view/*/layout | The copy does not pick up changes made upstream |
| Direct SQL | raw queries through the database connection | Adobe's guidelines require prepared statements for SQL queries15; queries also depend on a schema that can change |
| Non-API and deprecated code | use statements, calls to core classes | Only @api code of a module should be referenced by other modules15; removed classes and methods are listed per release16 |
Zend_ classes | grep for Zend_ | Several Zend components were replaced in 2.4.6 and 2.4.91 |
A quick grep finds most of these:
grep -rn "Zend_" vendor/<vendor>/<package>
grep -rn "<preference" vendor/<vendor>/<package>/etc
grep -rn "function around" vendor/<vendor>/<package>
Check frontend code (RequireJS configuration, JavaScript mixins, jQuery widgets) against the release notes too. Adobe's backward incompatible changes reference covers layouts, system configuration, DI configuration and XSD files as well as PHP classes and interfaces16.
Step 6: how do you prove it on staging?
Run the real upgrade on a staging copy with production-like data. After updating the packages, the deployment steps are the usual ones511:
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento setup:static-content:deploy -f
setup:static-content:deploy runs only in production mode by default; -f lets it run in default or developer mode17. Then smoke test what each extension touches: its admin pages, the storefront pages it changes, checkout, and its cron jobs, imports or API calls. Read var/log/exception.log and var/log/system.log after each test run18, and fix or record every new entry.
How do you decide what to do with each extension?
Use one row per extension.
| Extension | Installed version | Vendor support for target | Constraint check (why-not) | Static scan result | Decision |
|---|---|---|---|---|---|
| Yes / No / Unknown, with source | Pass / Blocked by ... | Clean / Warnings / Errors | Update / Replace / Remove / Rewrite |
The four decisions:
- Update when the vendor has a release for the target versions and staging passes with it.
- Replace when the vendor has stopped supporting it but the feature is still needed and another maintained module does the job.
- Remove when the module is disabled, unused or duplicated by core functionality. Uninstall it cleanly before the upgrade.
- Rewrite when the feature is specific to your business, no maintained alternative exists, or the original depends on patterns from step 5 that cannot survive. A rewrite that uses plugins and observers instead of preferences and copied core templates leaves less to re-check at the next upgrade.
Frequently asked questions
Does the Upgrade Compatibility Tool work on Magento Open Source?
No. Adobe states the tool is available for Adobe Commerce instances only, and downloading it requires Adobe Commerce access keys67. On Open Source, use the coding standard, PHPCompatibility, Composer's why-not and a staging build instead.
Why does Composer refuse to update even though the vendor says the module is compatible?
Composer only reads the constraints in the installed composer.json files. Run composer why-not magento/product-community-edition <version> to see which package declares the conflicting requirement4. If the vendor's compatible release is a new major version, your root composer.json has to allow it explicitly.
My module throws errors on PHP 8. Where do I start?
Run PHPCompatibility with testVersion set to the target PHP version10, then setup:di:compile on staging, and read var/log/exception.log18. Fix what they report before any functional testing.
Is a clean static scan enough to go live?
No. Static checks find code-level issues; only staging tests show whether checkout, integrations and cron jobs still behave correctly.
What to do next
Build the inventory and the table first; you may find modules you can drop before any code work starts. Then read our Magento 2 upgrade checklist for the rest of the project. If an extension has to be upgraded or rewritten as a custom module, see our Magento module development and upgrade work.
Sources
- Adobe Commerce Developer documentation, "Backward-incompatible changes", https://developer.adobe.com/commerce/php/development/backward-incompatible-changes/, checked 8 October 2026. ↩1 ↩2 ↩3
- Adobe Experience League, "System requirements", https://experienceleague.adobe.com/en/docs/commerce-operations/installation-guide/system-requirements, checked 8 October 2026. ↩
- Adobe Experience League, "Enable or disable modules", https://experienceleague.adobe.com/en/docs/commerce-operations/installation-guide/tutorials/manage-modules, checked 8 October 2026. ↩
- Composer documentation, "Command-line interface / Commands" (show, prohibits/why-not), https://getcomposer.org/doc/03-cli.md, checked 8 October 2026. ↩1 ↩2 ↩3 ↩4
- Adobe Experience League, "Perform an upgrade", https://experienceleague.adobe.com/en/docs/commerce-operations/upgrade-guide/implementation/perform-upgrade, checked 8 October 2026. ↩1 ↩2
- Adobe Experience League, "Overview of the Upgrade Compatibility Tool", https://experienceleague.adobe.com/en/docs/commerce-operations/upgrade-guide/upgrade-compatibility-tool/overview, checked 8 October 2026. ↩1 ↩2 ↩3
- Adobe Experience League, "Upgrade Compatibility Tool requirements", https://experienceleague.adobe.com/en/docs/commerce-operations/upgrade-guide/upgrade-compatibility-tool/prerequisites, checked 8 October 2026. ↩1 ↩2
- Adobe Experience League, "Run the Upgrade Compatibility Tool", https://experienceleague.adobe.com/en/docs/commerce-operations/upgrade-guide/upgrade-compatibility-tool/use-upgrade-compatibility-tool/run, checked 8 October 2026. ↩
- Magento on GitHub, "magento/magento-coding-standard" README, https://github.com/magento/magento-coding-standard, checked 8 October 2026. ↩
- PHPCompatibility on GitHub, "PHPCompatibility" README, https://github.com/PHPCompatibility/PHPCompatibility, checked 8 October 2026. ↩1 ↩2 ↩3
- Adobe Experience League, "Code compilation", https://experienceleague.adobe.com/en/docs/commerce-operations/configuration-guide/cli/code-compiler, checked 8 October 2026. ↩1 ↩2
- Adobe Commerce Developer documentation, "The di.xml file", https://developer.adobe.com/commerce/php/development/build/dependency-injection-file, checked 8 October 2026. ↩
- Adobe Commerce Developer documentation, "Plugins (Interceptors)", https://developer.adobe.com/commerce/php/development/components/plugins, checked 8 October 2026. ↩
- Adobe Commerce Developer documentation, "Extension coding best practices", https://developer.adobe.com/commerce/php/best-practices/extensions/, checked 8 October 2026. ↩
- Adobe Commerce Developer documentation, "Technical guidelines", https://developer.adobe.com/commerce/php/coding-standards/technical-guidelines, checked 8 October 2026. ↩1 ↩2
- Adobe Commerce Developer documentation, "Backward-incompatible changes reference", https://developer.adobe.com/commerce/php/development/backward-incompatible-changes/reference, checked 8 October 2026. ↩1 ↩2
- Adobe Experience League, "Deploy static view files", https://experienceleague.adobe.com/en/docs/commerce-operations/configuration-guide/cli/static-view/static-view-file-deployment, checked 8 October 2026. ↩
- Adobe Experience League, "Write to custom log file" (default log handlers and files), https://experienceleague.adobe.com/en/docs/commerce-operations/configuration-guide/logs/custom-log-files, checked 8 October 2026. ↩1 ↩2