Upgrading Magento 2.2 to 2.4: The Problem Is 2.3, Not 2.4
There is a version of this project that goes badly, and it starts with someone reading the release notes for 2.4 and scoping the work from them. The notes for 2.4 are not wrong. They are just not the part that is going to cost you money.
If you are on Magento 2.2, the release that reshapes your store is 2.3. It is not your destination and nobody is going to leave you there, but your database and every custom module you own have to go through it. Two changes shipped in 2.3.0 that you cannot route around, and neither of them appears in a comparison of 2.2 against 2.4 because they are not visible from either end.
Where 2.2 actually stands
Support for the Magento 2.2 line ended in December 2019. No official security patches have shipped since.
That is close to seven years. It is longer than Magento 1 has been unsupported, which surprises people, because 2.2 still feels modern in a way that Magento 1 does not. The admin looks familiar. The code looks like Magento 2 code. Nothing about running it feels like running abandoned software, and that is precisely the problem — the store gives you no signal that anything is wrong until it very much is.
The compliance position is the same one that applies to any end-of-life platform. PCI DSS requires critical patches within a defined window; a version that receives no patches makes that impossible to satisfy rather than merely difficult.
Why 2.3 is not optional
Adobe's guidance is to upgrade incrementally through minor versions, and in practice Composer will not resolve a 2.2-to-2.4 jump cleanly anyway. But dependency resolution is the small reason. The real one is that two structural changes landed in 2.3.0, and both of them modify things you own rather than things Adobe owns.
Declarative schema
Before 2.3, a module that needed a database table wrote InstallSchema.php and UpgradeSchema.php — PHP scripts that ran in sequence and made changes imperatively. From 2.3.0, Magento reads a db_schema.xml file that describes the tables a module wants, and works out the difference itself.
Two consequences, and the second one is the one that catches people:
Every custom module you own that creates or alters a table needs converting. Magento ships a conversion command that generates a starting db_schema.xml from your existing install scripts, and it does a reasonable job on straightforward tables. It is a starting point, not an answer — anything conditional, anything that manipulated data rather than structure, and anything clever needs a human.
The way back closes. Once declarative schema has applied its changes, downgrading to 2.2 is not a realistic recovery path. This changes your rollback plan from "revert the deploy" to "restore the database," which is a different exercise with a different time budget. Work out how long a full restore takes on production-sized data before the maintenance window, not during it.
Multi-Source Inventory
MSI also arrived in 2.3.0, and it changed where stock lives. Instead of a quantity per product, Magento gained sources and stocks in their own tables, with salable quantity computed from them.
For compatibility the legacy inventory tables are kept in sync, which is why plenty of stores upgrade and see nothing break on day one. The risk is not in the checkout — it is in everything around it:
- ERP and WMS integrations that write stock levels straight into the legacy tables. These often keep appearing to work while the two models drift apart.
- Custom code and extensions that read stock directly rather than through Magento's stock registry.
- Reports and exports built against the old table structure.
- Anything that assumed one warehouse, which is most things written before 2018.
Grep for direct references and treat every hit as a decision:
# Custom code reaching into inventory tables or the legacy stock item
grep -rn "cataloginventory_stock_item\|StockRegistryInterface\|getStockItem" \
app/code/ --include="*.php"
# Install/upgrade schema scripts that need converting to db_schema.xml
find app/code -name "InstallSchema.php" -o -name "UpgradeSchema.php"
Those two commands take a few minutes and tell you more about the shape of this project than a week of planning meetings.
The PHP distance
A 2.2 store is running PHP 7.1 — 7.0 on the earliest releases in the line. Current 2.4 releases require PHP 8.3 or 8.4, with 2.4.9 moving to 8.4 or 8.5.
That is further than it sounds. A store coming from 2.3 crosses one language major version. You are crossing one major version and most of the 7.x line on the way, including 7.2's stricter behavior and 7.4's deprecations, before you get to the 8.0 breaking changes everybody talks about.
The useful part is that PHP work can be isolated. Move as far up the PHP range as each Magento version supports before changing Magento versions, so language breakage surfaces against a codebase you still recognize.
The staged path
Six moves, and none of them should be combined to save time:
Stage 1 — get current within 2.2. Move to the final 2.2 patch level. Same-line work, low risk, and it gives you a known-good starting point.
Stage 2 — take the inventory. Run the two commands above, plus the extension list. This is your actual risk profile:
bin/magento --version
composer show | grep -v "^magento/"
Stage 3 — convert your schema. Do the db_schema.xml conversion work as its own piece, reviewed properly, before it is on the critical path of an upgrade window.
Stage 4 — cross into 2.3, and stop there deliberately. Land on the final 2.3 patch level, then run the store on it long enough to find the inventory problems. This is the stage people compress, and it is the one where MSI drift shows up. Give your ERP integration a full stock cycle to prove itself.
Stage 5 — cross into 2.4. From here you are on the same path as any 2.3 store, and it is a substantial path in its own right: PHP 8, a mandatory search engine you have never run, the Zend-to-Laminas replacement, and two-factor authentication on the admin. We wrote that leg up separately in upgrading Magento 2.3 to 2.4, and everything in it applies to you.
Stage 6 — regression test the revenue paths. Checkout first and hardest, every payment and shipping method, guest and logged in. Then stock accuracy specifically, because that is the thing this upgrade is most likely to have quietly changed. The broader methodology is in our Magento 2 upgrade guide.
Pick 2.4.8, unless you have a reason
The instinct from this far back is to go straight to the newest release and buy the longest runway. It is usually the wrong call.
2.4.8 is the right target for most 2.2 stores. Its edge cases have been found by other people, extension compatibility is broad, and it means crossing one framework migration rather than two. 2.4.9 makes sense if you have few third-party extensions or you are rebuilding enough of the store that the extra disruption is absorbed anyway. The trade-off between them is laid out in 2.4.8 versus 2.4.9.
Coming from seven years behind, landing on proven code beats landing on new code. You can take 2.4.9 as a planned project later, by which point it will be the mature line.
What this realistically costs
Scope it as a project rather than a maintenance task, and expect the estimate to be dominated by things that are not Magento.
The extension audit is the critical path, and seven years is long enough that several of your vendors no longer exist. Each of those is a build-or-replace decision that nobody outside your business can make. The schema conversion is proportional to how many custom modules you own. The inventory work is proportional to how much of your operation runs through an ERP.
The engineering is knowable. What is not knowable until you look is how much of your store depends on assumptions that stopped being true in 2018.
What we would do
Run the two greps today. InstallSchema.php and direct stock access are the two findings that separate a contained upgrade from a partial rebuild, and twenty minutes tells you which one you are looking at.
Then stage it so that each change can fail on its own terms, sit on 2.3 long enough to trust your stock numbers, and target 2.4.8. The thing that keeps you from repeating this in 2033 is not the size of this jump — it is ongoing support and patching between versions, so the next one is a routine release rather than a project.
Emyrix upgrades stranded Magento stores — schema conversion, extension audits, and the Magento 2 development work when a module has to be rebuilt rather than replaced. If you are on 2.2 and want to know what your upgrade actually involves, get in touch.
Version support dates and platform requirements come from Adobe's software lifecycle policy and release notes, which are the authoritative sources and worth checking directly for your edition and license type.
Frequently asked questions
When did Magento 2.2 reach end of support?
Support for the 2.2 line ended in December 2019. No official security patches have shipped since, which puts a store still running it close to seven years behind on published vulnerabilities. Adobe's lifecycle policy is the authoritative source for exact dates by edition.
Can I upgrade from Magento 2.2 straight to 2.4?
Not as a single operation. Adobe's guidance is to upgrade incrementally through minor versions, and in practice Composer will not resolve the jump cleanly. More importantly, the 2.3.0 release changed how schema is declared and where inventory data lives, and your database has to go through those changes rather than around them.
What is declarative schema and why does it matter for this upgrade?
Magento 2.3.0 introduced declarative schema, where a module describes its tables in a db_schema.xml file instead of running InstallSchema and UpgradeSchema PHP scripts. Every custom module you own that creates or alters tables needs converting, and it is the change that makes downgrading impractical afterwards.
What does Multi-Source Inventory change for an existing store?
MSI arrived in 2.3.0 and moved stock into its own inventory tables with sources and stocks, rather than a single quantity per product. The legacy tables are kept in sync for compatibility, but any custom code, extension, or ERP integration that reads or writes stock directly needs checking, because the source of truth moved.
Should I target 2.4.8 or 2.4.9 coming from 2.2?
For most stores, 2.4.8. Coming from this far back the extension estate is already the critical path, and 2.4.8 means crossing one framework migration rather than two. Landing on proven code matters more here than the extra year of support runway.