PHP 8.6 lands on November 19, 2026, and I already know which feature every conference talk will open with: partial function application. Write str_replace(' ', '-', ?) and you get a callable with the last argument left open, ready to drop into the pipe operator. It's genuinely lovely, and after years of fn($x) => wrapper closures cluttering our collection pipelines, I'll take it gladly. But here's my actual thesis: PFA is the fireworks, not the construction site. The parts of 8.6 that will matter most in three years are the ones that look boring today — the reserved words, the deprecations, and a polling API that deliberately ships without the thing everyone wants.

Start with the identifiers PHP is now warning you away from: let, is, namespace as certain names, readonly as a function name, and the lone underscore _. A language doesn't fence off words like let and is for fun. That's the core team reserving parking spots for future syntax — pattern matching is the obvious guess for is — and doing it a full major version early so the eventual RFC doesn't break half of Packagist. If you've ever watched a language try to retrofit a keyword after the fact, you know how much pain this quiet move avoids.

The new polling API tells the same story. It gives PHP internals — PHP-FPM, signal handling, ZTS — a proper abstraction over epoll and WSAPoll, and it's exposed to userland so ReactPHP and Amp can retire their stream_select() gymnastics. Crucially, it does not ship async/await and it does not ship an event loop. I've seen people read that as timidity. I read it as sequencing: you don't pour the concrete and hang the drywall in the same afternoon. If PHP ever gets first-class async, it will stand on exactly this kind of unglamorous plumbing, and high-concurrency apps get better scalability in the meantime.

The deprecation list reads the same way once you squint. Returning from finally — that little footgun where a return [] in the finally block silently swallows the return $value in the try — is finally on notice. Constructors and destructors returning values, which never meant anything, are now officially deprecated too. Reflection is being tightened: setting properties on unrelated objects and calling static methods through instances are both marked for removal. Each of these closes a door that some future feature would otherwise have to tiptoe around. And yes, is_double(), is_integer(), is_long() and doubleval() are heading out in favor of is_float(), is_int() and floatval(); if that breaks your codebase, your codebase was overdue for a rector run anyway.

Let me concede the strongest counter-argument, because it's a good one: for a working developer, the immediately useful stuff is what pays the bills, and 8.6 has plenty of it. clamp($value, 0, 100) replaces the max(0, min(100, $value)) incantation we've all mistyped, and it works on strings, DateTime, anything comparable. Readonly properties can carry default values now. Reflection gains isReadable() and isWriteable(), which framework authors dealing with property hooks and private setters will use on day one. ReflectionParameter::getDocComment() puts annotations right next to the parameter they describe. Enums get __debugInfo(), so var_dump() output stops being archaeology. If your definition of a good release is 'things I use this sprint', 8.6 clears the bar without any of my architectural romanticism.

But I still land where I land, and the session defaults are why. session.use_strict_mode = 1, session.cookie_httponly = 1, session.cookie_samesite = Lax — out of the box. Nobody will blog breathlessly about ini defaults, yet this single change will quietly kill a class of session fixation and cookie-theft bugs across thousands of apps whose maintainers never read the changelog. That's the pattern I'm pointing at: the unsexy decisions compound. The SortDirection enum is another tell — shipped before core sort functions even accept it, purely so the ecosystem can standardize now and the language can catch up later. That's a project planning in decades, not release cycles.

Practical upshot for your upgrade: don't treat 8.6 like a feature buffet you can graze whenever. Run it in CI with deprecations surfaced as failures the week it drops. The finally returns, the legacy type helpers, the reflection tricks in that one ancient serializer you vendored in 2019, spl_object_hash() calls, mysqli::stmt_init() — every one you fix now is a migration you don't do under pressure when PHP 9 arrives. And check whether anything in your stack depends on cross-site POSTs hitting sessions or JavaScript reading session IDs, because the new cookie defaults will bite exactly those setups first.

So here's where I want pushback, because I know this room contains people who disagree. Is a release best judged by what it lets you write today, or by what it makes possible in three years? Put differently: which 8.6 change will still matter in 2029 — PFA and the pipe operator, or the day PHP reserved the word is? Tell me I'm wrong in the comments; bring code.