There is a kind of software nobody gives conference talks about: the inventory system from 2009, the customer portal from 2011, the shop built by an agency that no longer exists. A surprising share of it runs on Zend Framework 1. Today, in production, with revenue behind it.
Zend Framework 1 reached its end of life on 28 September 2016. For almost ten years there have been no fixes, including no security fixes. This article is for everyone responsible for such a system who wants to know where they stand: what the end of support actually means, what community forks can do, why there is no migration tool and which three ways out are honest. If you already know you want to leave, the Zend Framework migration page has the concrete starting point.
I am not writing this as a bystander: I used Zend Framework back when it was current, and today I replace systems that were built on it.
Why it is still running in 2026
Zend Framework 1 appeared in 2007 and was, for years, one of the most obvious answers to the question of how to build professionally in PHP. Agencies and in-house teams built booking systems, portals, shops and back offices on it. These were not experiments but business applications, and that is exactly why they are still alive: they work. Software does not die of old age, it dies of missing demand, and the demand for a working inventory system does not end with the framework underneath it.
Then there is the human part. The agency from back then no longer exists or has long since moved on. The developers who knew the system are two employers further down the road. What remains is a system with a bus factor close to zero that nobody wants to touch any more. "Never touch a running system" becomes a strategy without anyone ever having decided on it.
A misunderstanding often keeps it alive on top of that. Anyone searching for Zend Framework today reads about the transition to Laminas: the project has been continued under a new name since early 2020, and for versions 2 and 3 there is an orderly path over. That sounds reassuring, but it only applies to ZF2 and ZF3. By that point, Zend Framework 1 had already been past the end of its support for over three years. The Laminas transition made nothing better and nothing worse for ZF1; it simply has nothing to do with it.
What has been missing since 28 September 2016
On 29 September 2016, no ZF1 application was any less secure than the day before. That is not how an end of life works. It means something more gradual: every vulnerability found in framework code since then stays open, and nobody is responsible for even looking for one any more. The burden of checking has rested entirely on you ever since, without anyone ever saying so out loud.
The second problem is the coupling to the language. ZF1 applications almost always sit on old PHP versions, often ones that no longer receive security updates themselves. That is a double end of life: an orphaned framework on an orphaned language version. The PHP upgrade is overdue, but the framework stands in the way, and so both keep ageing together.
The third is the ecosystem. ZF1 predates Composer. The libraries and extensions of that era are as orphaned as the framework itself, and the conventions ZF1 works with exist nowhere in later frameworks. Every developer who takes over the system learns things they will never need again, and the market of people who already know them shrinks every year.
And finally the part that is not technical: at some point, somebody asks. An audit, a cyber insurer, a customer with a security questionnaire, a buyer in a due diligence. "Our framework has had no support since 2016" is then no longer a developer topic but a business risk, the way technical debt always ends up becoming one. The most uncomfortable property of this risk: it does not become visible through an incident but through a question, and other people choose when the question comes.
What community forks can do, and what they cannot
Anyone who looks into the topic quickly finds community forks such as zf1-future that keep ZF1 code running on newer PHP versions. That is honourable and useful work, and it solves a real problem: it decouples the PHP question from the framework question. An application that runs on a maintained PHP version thanks to a fork has closed one of the two support gaps and bought time.
Bought, not been given. A fork does not turn a discontinued framework into a maintained product. There is no organization giving security commitments, no release cycle you can build contracts on, and no guarantee that the handful of volunteers will still be there in five years. The architecture of 2007 remains the architecture of 2007, the hiring market stays the same, and the audit now reads "community fork of a framework discontinued in 2016" instead of "framework without support". That is better, but it is not an answer.
A fork is a bridging loan: exactly right for not having to decide under time pressure, and dangerous the moment you mistake it for repayment.
Why there is no migration tool
For ZF2 and ZF3 there is an official tool that handles the migration to Laminas largely mechanically: namespaces and package names are replaced across the whole codebase, and what remains is manual work around the edges. According to its own documentation, the tool explicitly covers versions 2 and later.
That boundary is not carelessness, it has technical reasons. ZF1 predates Composer and brings its own MVC, its own database layer and its own conventions, none of which have a counterpart in today's PHP world. There is no target that would be "the same thing, but new" for a tool to translate into automatically. That is why even the phrase "ZF1 migration" is misleading: what is a migration on ZF2 is a replacement on ZF1. Anyone promising you a mechanical migration for ZF1 has either not looked at your application or is using the word differently than you are.
The three honest ways out
The way I see it, there are exactly three ways of dealing with a ZF1 application that you can defend in front of yourself and in front of an audit.
First: consciously leave it as it is. That is a legitimate decision, as long as it is a decision and not a state of affairs. It includes writing the risk down and reducing it: make the application as unreachable from the outside as possible, defuse the PHP question via a fork or an intermediate version, monitor what goes in and out, and define the criteria that end this arrangement when they occur. The difference between this option and what most companies do is exactly one document, but that document changes everything: it turns a blind spot into a risk decision with an expiry date.
Second: replace it step by step. In most cases this is the right way, and it follows the strangler fig pattern: a routing layer in front of the application redirects one area after another to a maintained stack, and the old system shrinks until it disappears. Before the first change, a net of characterization tests records what the system does today, because a ZF1 application almost never has tests. And the PHP version is changed separately from the framework, never at the same time: touch both at once and you no longer know where any error comes from. Every step goes to production on its own and can be rolled back on its own. There is no moment where everything depends on one big cut.
Third: rebuild in one go. For a small, sharply bounded application whose behaviour is fully known, this can be the shortest path. For everything else, what I wrote about full rewrites applies: the rebuild has to reproduce behaviour nobody fully knows, it delivers nothing for months, and the old system keeps running and changing in the meantime. The cases where a one-shot rebuild is the right answer to ZF1 are considerably rarer than the proposals promising one.
What the first step looks like
Whichever of the three ways it turns out to be: the first step is the same, and it is small. It starts with an assessment. Which version is actually inside the application, how clean is the boundary between framework code and your own code, which dependencies are orphaned, where does your own code sit on framework internals. From this inventory follows what a replacement would cost and in what order it would run, in steps that go to production individually. Only after that is a number serious. Any number before that is a guess, because between a cleanly layered ZF1 application and one with business logic scattered across controllers and views lie orders of magnitude.
The urgency always comes from the same four directions: the PHP version underneath falls out of support. An audit or a certification is coming up. The last person who knows the system hands in their notice. Or new requirements pile up because nobody dares to change the system any more. If you see one of these four movements in your company, do the assessment before the question arrives from outside, because then you still set the pace yourself.
Zend Framework 1 was good software. The applications running on it often still are. That is exactly why they deserve something better than the two extremes they usually hang between: years of looking away, or a rebuild proposal with seven digits. The path in between is unspectacular, incremental and proven for years. It starts with someone taking a proper look.

