Once you and your company have concluded that migration is necessary, the first task is to be clear-eyed about the risks. On average, an in-house migration is expensive, slow, and has a significant impact on business operations. This is because most developers haven't migrated a project before — they fall into rabbit holes of legacy complexity and unfamiliar patterns.

The risk spectrum

Migration outcomes range from catastrophic to seamlessly smooth. The decisions you make must be pragmatic and calculated, constantly pushing the outcome toward the better end of the spectrum.

In practice, migrations run the entire range from worst to best case. The goal is to learn from each iteration, mitigate risks more effectively each time, and understand which approach is appropriate for each business context.

The risks are not to be understated. A failed migration can force an SME to downsize or even close. But the alternative — doing nothing — is rarely neutral.

When the cost of not migrating is higher

Consider a company running a Phalcon PHP project. Phalcon was a C-extension framework for PHP that gained traction around 2010–2015 but failed to achieve broader adoption. It announced a PHP-native rewrite (Phalcon 6) back in 2020. Years later, that version still hasn't been released.

This company will eventually have to migrate to a PHP-native framework or rebuild entirely. The longer they delay, the more incompatible and outdated their system becomes. The framework community is tiny, updates are rare, and finding developers willing to work on such a system gets progressively harder. In this case, the risk of not migrating outweighs the risk of migrating — from both a technology and a talent acquisition standpoint.

It's impossible to predict exactly how long an application can continue without an upgrade. It could be a year, it could be ten. But unexpected behaviour will eventually appear: crashes, unknown bugs that weren't there before, and steadily increasing development cost just to maintain the status quo. That unpredictability is bad for business.

Test coverage is a force multiplier

One of the biggest issues in any migration is knowing where things break. With low test coverage you're fishing in the dark — any change could break any number of features and you'd have no idea.

Decent test coverage reduces migration risk substantially. If you know where things break, you can fix them faster, which means faster overall delivery. Many applications have few or no tests; if that's the case, it must factor into your risk analysis and time estimates.

A practical approach to managing migration risk

The process breaks into three stages:

  1. Understand the current state of the project — the good, the bad, and the ugly. Run Migrator to get a structured assessment:
composer require kerrialn/migrator
vendor/bin/migrator analyse

This produces a report that frames the risks clearly and gives you something concrete to show stakeholders. It removes "we think it's bad" and replaces it with "here's exactly how bad, and here's why."

  1. Develop a realistic and achievable roadmap based on the current project state. Each item on the roadmap should be small enough to be completed and merged independently. Large, monolithic upgrade branches are high-risk and hard to review.

  2. Implement in iterations and adapt — each iteration produces real production improvements and real learnings. Requirements change; your approach should too.

Migration is a tough but deliberate decision

Migration brings both risk and opportunity. A failed migration can have serious consequences; delaying it can make your system more outdated and more expensive to maintain. For some businesses, the decision is clear — remaining on legacy systems leads to bigger problems down the road.

The key is to treat migration as a structured engineering process, not a heroic one-time effort. Assessment first, roadmap second, incremental delivery third. Small steps that compound into a modern, maintainable codebase.