Infrastructure · We do not build on it
A language runtime or framework version whose maintainers have stopped issuing security fixes — still running, still serving traffic, no longer receiving patches.
This is the one refusal on this page that is not a matter of taste at all. A supported runtime gets a fix when a vulnerability is found. An unsupported one does not, and no amount of care by the team running it changes that.
01
End of life is a published date, not an opinion. PHP 7.4 stopped receiving security support on 28 November 2022 and PHP 8.1 on 31 December 2025; as of September 2026 only 8.2 and later are supported upstream. A decision that turns on a calendar is not a technology preference, and framing it as one is how it gets deferred.
02
The exposure is not theoretical, and it is measurable. WordPress publishes what its installations run: 17.2 per cent report PHP 7.4, unsupported for nearly four years, and 38.8 per cent report 8.1 or older. Those are live sites, taking real traffic, on runtimes that will not receive a fix for whatever is found next.
03
The reason estates end up there is structural rather than negligent. Upgrading is the risky operation — it is the step that breaks things in production — so the rational response of anyone burned once is to stop, and the security model quietly inverts: the safest-feeling action becomes the dangerous one. Naming that out loud is more useful than blaming an operator.
04
A legacy framework is usually a hostage rather than a codebase. The problem is rarely the language and almost always a dependency that pinned it: one library that never released for the new major, and the whole estate is held at the old one. So the honest first move is to find that pin and cost it, which is a day of work and is what we do before quoting anything larger.
05
Where the answer is genuinely to leave it alone: a system with no route in from the public internet, no personal data and a known retirement date is not worth modernising for its own sake. Migration has a cost and a risk of its own, and spending both on something being switched off next year is worse engineering than leaving it. We say so rather than selling the rewrite.
06
What we will not do is add to it. Building a new feature onto an unsupported runtime means the new work inherits the old exposure and extends the life of the thing that should be retiring, which converts a scheduled problem into a permanent one.
An entry that cannot point at something you can open, run or read does not compile. That is a property of the type, not a promise in a paragraph.
Invariant
This argument is about runtimes past a published end-of-life date, and it does not stretch to “anything old”. Software that is boring, stable and still supported is usually the correct choice, and mistaking age for risk is how a working system gets rewritten for nothing. The question is always whether a fix would arrive if one were needed, not how long the thing has been running.