This is the final part of a six-part series. [Part 1] made the case for splitting WordPress into Classic and Next. [Part 2] talked about the kernel. [Part 3] talked about the admin and editor. [Part 4] covered performance and security. [Part 5] talked about the plugin economy and the contracts that hold it together.
This post is about the part that ultimately makes or breaks everything else in this series. How do Classic and Next actually coexist? How do existing sites move? What’s the timeline? Who pays to keep Classic alive? And what about the constraints WordPress has spent twenty years protecting?
I want to be honest, this is the part I’ve thought hardest about, because I watched the aftermath of Drupal’s choice from inside Acquia, and the costs were real.
What Drupal got right and wrong
Drupal 8 (2015) was a full Symfony rewrite. The architectural direction was unambiguously correct. It’s why Drupal 9, 10, and 11 have been smooth incremental upgrades, and why Drupal’s developer ergonomics today are ahead of where WordPress is, in a lot of ways.
But the ecosystem migration was brutal. Most Drupal 7 contributed modules took 2 to 3 years to port. Some never ported. A substantial fraction of Drupal 7 sites simply never migrated. D7 support ran until January 2025, a ten-year twin track. I joined Acquia in 2023 and even then there were still customers running D7 sites that couldn’t or wouldn’t make the jump, and there was a whole industry built around extended D7 support.
The “burn it down and rewrite” posture also cost Drupal mindshare that went to headless-friendly alternatives. People who might have been Drupal developers in 2016 became Strapi or Sanity developers in 2018. That bleed never fully reversed.
The post-8 playbook (semantic versioning, deprecations in minors, removals at majors, drupal-rector) is the part to copy cleanly. The “everything is different now, good luck” posture is the part to avoid.
What Python, Angular, and Perl teach
I’ve been thinking a lot about other ecosystem-wide migrations and what made them succeed or fail.
Python 2 to 3 (2008 to 2020) is the good case. Twelve years of dual support. six as a compatibility layer. 2to3 and pyupgrade as tooling. Eventual hard cutoff via PEP 373 that the community actually respected because by the time the cutoff came, the ecosystem had migrated.
AngularJS to Angular is the cautionary mid-case. Full rewrite. ngUpgrade as the incremental migration path (running both together). Market share lost to React during the transition. Angular eventually stabilized, but the transition years were brutal for adoption.
Perl 5 to Raku is the failure case. Started in 2000. Renamed Raku in 2019 to acknowledge it would never replace the original. Never replaced the original. Perl 5 is still the production language. Raku is a curiosity.
The lesson, as far as I can tell: if you can’t commit to a cutoff, you end up with two languages forever. Python committed. Angular committed. Perl never did. The result is what you’d expect.
I want to underline this because I think it’s the most important thing I’ll say in this whole series. The migration only works if there’s a real, public, dated commitment to Classic eventually entering long-term support and then end-of-life. Without that commitment, every plugin author hedges, every host hedges, every site owner hedges, and you end up with a permanent two-track maintenance burden that sucks all the oxygen out of Next.
The Classic/Next architecture
Here’s the concrete proposal. Shared kernel, different application layers. Not two forks. Not a full rewrite. A strangler-fig migration where:
wp-kernelis a new package that provides the container, middleware pipeline, typed events, query builder, cache, queue, logger, config, CSRF, OAuth, CLI. It’s Composer-installable. It has no UI.- WP Classic continues as the current
wordpress/wordpresscodebase. It getswp-kernelas an optional bootstrap. Whenwp-kernelis present, core’s internals (WP_Http, WP_Query, WP_Object_Cache, WP-Cron, etc.) delegate to kernel equivalents where possible. Classic code keeps working. Classic plugins keep working. - WP Next is the new application layer on top of
wp-kernel. PHP 8.2+ required. Object-oriented and dependency-injected throughout. Typed APIs. Persistent object cache required. No$wpdbglobal. No$postglobal. Noclass-foo.php.composer.jsonat the root. - The compat shim is a Classic-mode-in-Next module. A Next site can enable
Compat\Classicto load a Classic plugin, which runs in a sandboxed bootstrap with the old globals polyfilled. The shim has explicit performance and security penalties (undeclared permissions, extra memory, some features unavailable). It’s a bridge, not a destination.
Plugin authors target one of three things:
- Classic-only. Existing plugins, no changes.
- Both. Plugins that declare
targets: [classic, next]and use the subset of APIs common to both (thewp-kernelinterfaces, all available from Classic via the optional bootstrap). - Next-only. Plugins that want enums, typed events, the query builder, the permission manifest, etc. These don’t run on Classic at all.
The .org repo surfaces all three. The plugin search filter includes a “Works on Next” badge. WP-CLI has wp plugin:compat to report compatibility state.
The reason this architecture works (and the reason it’s different from what Drupal 8 did) is that Classic doesn’t have to change to enable Next. Drupal 7 ended the moment Drupal 8 shipped. Drupal 7 sites had nowhere to go except “stay on D7 indefinitely” or “rewrite for D8.” With this architecture, a Classic site keeps working, keeps getting security updates, and eventually moves when the site owner is ready, with wp-kernel quietly modernizing things underneath the whole time.
The migration path for sites
A Classic site upgrades to Next by:
- Running
wp next:audit, which reports every Classic-only API used by the site’s plugins and theme. - Upgrading plugins to Next-compatible versions where available.
- Replacing incompatible plugins (with suggested alternatives in the audit).
- Running
wp next:migrate, which moveswp_options,wp_usermeta,wp_postmetainto the Next schema (config vs. kv split, typed post metadata), regenerates the permissions table from the serializedwp_user_rolesoption, rewriteswp-config.phpconstants into.envplusconfig/. - Enabling Next mode, which switches the active kernel.
This is a one-way migration by default. A rollback mode exists for 30 days post-migration.
I want to flag something here from my agency-side experience at Fueled. The single biggest determinant of whether a site migration goes well is the quality of the audit step. If wp next:audit is honest, exhaustive, and gives the site owner a clear picture of what they’re walking into, migrations succeed. If it’s optimistic and underreports, migrations fail and people get burned. The audit tool is more important than the migration tool.
Who pays to keep Classic alive
This is the question I’ve owed an honest answer to since part 1, and I want to give it the space it deserves rather than waving at it.
The bargain Classic offers is: your site works, gets security patches, gets very small UX improvements, for a decade or more. That’s a promise to roughly 43% of the web. It is not a promise that maintains itself. Open-source maintenance runs on corporate sponsorship and contributed labor, and if the professional tier and the premium plugin economy migrate to Next, the funding base for Classic gets thinner at exactly the moment its security surface needs the most attention.
So here is the model.
The WordPress Foundation operates Classic LTS as a structured program. Not as a vague community effort. As a named, funded, staffed program with a published security response policy, a dedicated maintainer team, a public CVE pipeline, and a quarterly transparency report. Drupal’s official extended-support programs (myDropWizard, Tag1 Quo, and the unofficial-but-tolerated commercial ecosystem around D7’s last years) showed both the demand for paid LTS and the chaos of having it run by competing third parties. The right structure for WordPress is to do this once, centrally, properly. The Foundation is the institution that can credibly do that.
The major hosts underwrite the program proportionally. Automattic/wp.com/Pressable/VIP, Newfold (which owns Bluehost, HostGator, and more), WP Engine, Kinsta, GoDaddy, Cloudways, Rocket.net, and the rest of the managed-host tier contribute to the LTS program in proportion to the revenue they derive from Classic-hosted sites. The Foundation administers the formula and the council that governs it. Hosts get a seat at the table, a public commitment to multi-year stability for their customers, and the ability to advertise “Officially Maintained Classic LTS” as a tier above generic shared hosting.
I want to be direct about the leverage here, because it matters. Hosts profit enormously from Classic’s existence. They have profited from Classic’s existence for fifteen years on largely volunteer-maintained code. If Classic’s LTS depends on host contributions and the hosts don’t fund it, then Classic’s LTS goes away on the published cutoff date, and those hosts have to migrate their customer base to Next on a hosting infrastructure that may not be ready for it. The threat is real and it should be. The professional tier of WordPress hosting has been free-riding on this codebase for a long time. The bill comes due.
Enterprise extended support sits on top of the floor. Organizations with regulatory requirements, larger CVE scope, or guaranteed-response SLAs can purchase enterprise-tier support from the Foundation directly, or from accredited partners operating under the Foundation’s standards. This is what Red Hat does for Enterprise Linux. This is what Acquia does for Drupal. The revenue from enterprise contracts subsidizes the floor that everyone else gets for free, and it gives the Foundation a sustainable funding source that doesn’t depend purely on host goodwill.
This is the Linux Foundation model adapted to WordPress’s specifics. The Linux Foundation has sustained Linux LTS at much larger scale, for longer, with this exact three-layer structure (foundation-administered program, corporate contributors underwriting the floor, enterprise tier subsidizing the rest). The pattern works because all three layers are aligned around the same thing: keeping the platform stable for the people who depend on it, while distributing the cost across the parties that profit from it.
What I want to be clear about, because this is where similar proposals usually wave their hands: this is not a “the community will figure it out” structure. It’s a “the Foundation will run it, the hosts will fund it, and the enterprises will pay extra for tiered support” structure. Names, roles, accountability. If any of those three layers fails, Classic LTS fails, and the timeline below has to compress accordingly.
Timeline, concretely
Year 1. wp-kernel ships as a Composer package, consumable from Classic. New features in Classic (object cache primitives, queue, typed events) land as delegating to kernel. Classic is unchanged semantically. Foundation establishes the LTS program structure and begins host underwriting negotiations.
Year 2. WP Next 1.0 beta. Single-site only. Small plugin ecosystem. The core team, Automattic, the major hosts, and roughly 50 committed plugin authors target Next-compat. Host underwriting commitments published.
Year 3. WP Next 1.0 GA. Multisite. Full admin. Classic continues with security plus minor feature parity.
Year 5. Next has the majority of new installs. Classic enters long-term-support mode: security patches only. LTS program operating at full capacity, funded by the established host pool and growing enterprise contracts.
Year 8. Classic end-of-life announced with two-year warning (so year 10 cutoff). This is the commitment that prevents a Perl 6 outcome.
That’s a ten-year arc. I want to be honest, it might need to be longer. Drupal’s twin-track was effectively fifteen years. The right answer for WordPress is probably somewhere between ten and fifteen, depending on how aggressive the Year 8 announcement is. The point isn’t the specific years. The point is the commitment to a cutoff, the public dating of it, and the funded structure that makes the LTS years credible rather than aspirational.
What dies in Classic
Nothing new dies. Classic is frozen. It gets security patches and very small UX improvements. No new architectural features. The bargain with the 43% is “your site works forever, but we stop churning the foundations.”
I want to call this out because I think it’s actually a feature, not a sacrifice. A lot of WordPress users don’t want their CMS to keep changing under them. They want stable, predictable software that does what it did yesterday. Classic, properly framed, is a love letter to those users. It’s saying “we hear you, we’re not going to break what’s working, and here’s a multi-year commitment that you can plan around.”
That’s a much better deal than what those users get today, where every minor release introduces new editor patterns they didn’t ask for and have to learn around.
What ships first in Next, what comes later
I think it’s worth being concrete about sequencing, because the order matters.
Ships in the 1.0 foundation release (prioritized):
- PHP 8.2+ requirement, Composer-first, PSR-4,
wp-kernelwith container plus middleware plus PSR-14 events plus PSR-18 HTTP plus PSR-3 logger. - Typed Post/User/Term/Comment value objects. Enums for statuses/roles/types.
- Persistent object cache as hard dependency, with tags and locks.
- Query builder plus repositories.
WP_Querycompat shim available. - Real queue contract (Action Scheduler-shaped), real cron runner.
- OAuth 2.1 plus OIDC server. WebAuthn/passkeys two-factor in core.
- CSRF middleware (replacing nonces) plus automatic CSP nonces.
.envplus compiledconfig/.wp-config.phpcompat shim.- First-party logger with structured output.
- The Classic admin shell, unchanged in user-facing behavior, modernized underneath. Same React investment, same screens, same editor. The work happens beneath the surface, not in the chrome.
Ships in 1.x after GA:
- Content Schemas (first-party field API) with both a code-defined surface and a visual builder in the admin, as equal peers.
- First-class page cache with tag purge.
- Early Hints, streaming responses, Interactivity API islands with edge caching.
- Plugin permission manifests (declared-but-not-enforced phase).
- Signed plugin releases via Sigstore, first-party advisory DB,
wp plugin:audit. - Fiber-based concurrent HTTP.
- The new media service.
Ships in 2.x:
- Resource-scoped permissions (Zanzibar-shaped).
- API-level enforcement of plugin manifests.
- Block editor performance rewrite with the Interactivity API as primary.
- GraphQL as a first-class content API alongside JSON:API.
- Full a11y re-audit with a published remediation plan.
Research track bankrolled but not committed:
- WebAssembly-isolated plugin runtime via Playground’s PHP.
- React Server Component-style server-rendered blocks on PHP.
- Full-site static export for the “own your content” story.
The reason I’m putting the kernel-and-types stuff in the foundation release and the schemas-and-page-cache stuff in 1.x is that the foundation has to be solid before the visible features land. It’s tempting to lead with the user-facing wins because they’re the ones that get attention. But if Schemas ships before the typed APIs underneath are stable, you’ve just built another ACF-shaped thing on top of a wobbly foundation, and you’ll regret it inside a year.
Wrapping up the series
The bet of Classic/Next is not that WordPress is broken. The bet is that WordPress is two products being served poorly by one codebase. A durable, accessible, maintenance-mode publishing tool for the long tail. And a modern framework for the professional agency and product world that currently defects to Craft, Sanity, Payload, Strapi, and headless Next.js because the floor is too low.
Classic wins the first bet by doing less and promising more stability. Next wins the second bet by competing on the axes professional developers actually evaluate: typed APIs, dependency injection, Composer, real queues, real caches, real security, real tests.
The friction is everywhere. It’s in the build pipeline, in the security review, in the handoff to the operations team, in the conversation with the client about why a “WordPress site” can’t really be treated like a commodity once it’s load-bearing. A meaningful chunk of that friction would simply go away if Next existed.
The cost of the split is real and measurable. Two to three years of painful ecosystem work. Some hosts will not make the cut. Some plugin authors won’t port. Some sites will stay on Classic forever and that’s fine. The cost of not splitting is that the slow bleed of professional mindshare that has been accelerating since 2020 continues, and in ten years WordPress is where Drupal feared it would be in 2015 but isn’t, because Drupal made the call.
I’d rather we make the call.
Thanks for reading!
Glossary (for the whole series)
Technical terms and acronyms used throughout this series, defined for readers who haven’t spent their careers in PHP.
ACF (Advanced Custom Fields). A WordPress plugin, acquired by WP Engine and later brought back into Automattic’s orbit as SCF (Secure Custom Fields), that lets developers define custom fields and content types through a UI rather than code.
APM (Application Performance Monitoring). Tools like New Relic, Datadog, and AppDynamics that trace request execution, database queries, and external calls to diagnose performance issues.
APCu. A PHP extension providing in-memory key-value caching scoped to a single server. Used as a lightweight object cache backend.
BigPipe. A rendering technique originally from Facebook that streams page chunks as they become available, rather than waiting for the full page to render.
Block Bindings. A WordPress 6.5+ API that connects block attributes to dynamic data sources, so a core Paragraph block can display content from a custom field, for example.
CDN (Content Delivery Network). Distributed servers that cache and serve static assets closer to users. Cloudflare, Fastly, Akamai.
Composer. PHP’s dependency manager. The equivalent of npm for JavaScript or pip for Python.
CSP (Content Security Policy). An HTTP header that tells the browser which sources of scripts, styles, and other resources are trusted.
CSRF (Cross-Site Request Forgery). An attack where a malicious site tricks a user’s browser into making an authenticated request to another site. Mitigated by tokens, SameSite cookies, and origin checks.
DBAL (Database Abstraction Layer). A library providing a database-agnostic interface, usually referring to Doctrine DBAL in the PHP world.
Dependency Injection. The pattern of passing a class’s dependencies in through its constructor rather than having the class create or fetch them itself. Enables testability and loose coupling.
Doctrine. A family of PHP database libraries, including DBAL (low-level) and ORM (object-relational mapping).
Eloquent. Laravel’s ORM and query builder.
ESI (Edge Side Includes). A markup language that tells CDNs and edge caches how to compose a page from multiple cacheable fragments with different TTLs.
ECMAScript Modules. The modern JavaScript module format, replacing CommonJS and AMD.
FSE (Full Site Editing). WordPress’s initiative to make the entire site (headers, footers, templates, not just post content) editable in the block editor.
Gutenberg. The codename for WordPress’s block editor, introduced in WP 5.0 (2018).
Hot Module Replacement. A development feature where changed code is pushed into a running browser without a full page reload.
HPOS (High-Performance Order Storage). WooCommerce 8+’s replacement for storing orders as custom post types. Uses proper database tables instead.
HTMX. A library that adds AJAX, WebSockets, and other dynamic behaviors to HTML via attributes, enabling server-rendered apps with single-page-app-like interactivity.
Islands architecture. A rendering pattern where most of the page is static HTML with small interactive “islands” of JavaScript, rather than hydrating the entire page.
JIT (Just-In-Time compilation). PHP 8.0+’s optional feature that compiles hot code paths to machine code at runtime.
JSON:API. A specification for how to build JSON APIs, adopted by Drupal as its default.
Laravel. A popular PHP web framework. Known for its developer experience.
Long-Term Support. A maintenance commitment where a version receives security and bug fixes for an extended period, usually several years.
Monolog. The de facto standard PHP logging library, implementing PSR-3.
mu-plugins. “Must-use” plugins. WordPress plugins that auto-load from a special directory and can’t be deactivated through the UI. Used by hosts for platform-level code.
N+1 query problem. The anti-pattern of running one query to fetch a list, then one additional query per item to fetch related data. Solved by eager loading.
OAuth (2.0 / 2.1) and OIDC (OpenID Connect). Standards for delegated authorization (OAuth) and authentication (OIDC). What “Sign in with Google” uses.
ORM (Object-Relational Mapper). A library that maps database rows to objects and vice versa. Eloquent, Doctrine ORM, Cycle ORM.
PSR (PHP Standards Recommendations). Interfaces and standards published by PHP-FIG. PSR-3 (logging), PSR-4 (autoloading), PSR-7 (HTTP messages), PSR-11 (containers), PSR-14 (event dispatcher), PSR-15 (middleware), PSR-17 (HTTP factories), PSR-18 (HTTP client).
Playground. WordPress’s project that compiles PHP to WebAssembly, letting WordPress run entirely in a browser tab with no server.
Redis, Memcached, Valkey. In-memory key-value stores used as object caches and queue backends. Valkey is a community fork of Redis.
REST API. In the WordPress context, the /wp-json/ endpoint that exposes content over HTTP.
RFC (Request for Comments). A formal proposal document for a change, often reviewed publicly before implementation. Used by PHP, Python (as PEPs), Rust, and many other projects.
Rector. A PHP tool that automates codebase upgrades through rule-based refactorings. drupal-rector is Drupal’s flavor.
SameSite cookies. A cookie attribute that controls whether cookies are sent on cross-site requests. Mitigates CSRF.
SBOM (Software Bill of Materials). A list of all dependencies and components in a piece of software, used for supply-chain security.
SCF (Secure Custom Fields). WordPress’s in-house fork of ACF.
Semver (Semantic Versioning). A versioning scheme where MAJOR.MINOR.PATCH signals the nature of each release (breaking, feature, bugfix).
Sigstore. A project for cryptographically signing software artifacts without managing long-lived keys. Used by npm for provenance attestations.
Site Editor. WordPress’s FSE admin interface.
Single-Page Application. A web app where navigation happens client-side without full page reloads.
Strangler fig pattern. A migration pattern (named by Martin Fowler) where new functionality gradually replaces old functionality piece by piece, rather than in one cutover.
Symfony. A PHP framework and collection of standalone components. Laravel, Drupal, and many others use Symfony components under the hood.
theme.json. WordPress’s declarative file for design tokens (colors, typography, spacing) used by block themes.
Transients. WordPress’s API for short-lived cached values. Backed by the object cache if present, or options if not.
Trusted Types. A browser API that prevents DOM-based XSS by requiring DOM sinks to receive typed values, not raw strings.
Turbo (Hotwire). A set of libraries from the Rails ecosystem for building single-page-app-like experiences with server-rendered HTML. Considered as an alternative admin architecture earlier in this series and ultimately not adopted.
WebAssembly. A binary instruction format that runs in browsers (and increasingly servers) at near-native speed. Playground compiles PHP to WebAssembly.
WebAuthn / Passkeys. The modern web standard for phishing-resistant authentication using public-key cryptography.
WPackagist. A community project that mirrors the .org plugin/theme repo as a Composer repository.
WPGraphQL. A third-party plugin adding a GraphQL endpoint to WordPress.
Zanzibar. Google’s internal authorization system, described in a 2019 paper. The theoretical gold standard for fine-grained, relationship-based permissions at scale.
Links and references
WordPress core and direction
- WordPress Developer Resources, Block Editor Handbook.
- WordPress Playground.
- Interactivity API announcement.
- Data Liberation in 2024.
- Block Bindings API guide.
- WordPress loading sequence walkthrough.
- WordPress PHP Coding Standards.
- WordPress Hooks reference (Techidem).
PHP and the PSRs
Framework comparisons
- Laravel vs. Symfony analysis.
- Laravel vs. Symfony side-by-side.
- Laravel Eloquent vs. Drupal Entity API.
Build tooling
- Vite vs. Webpack in 2026.
- Vite vs. Turbopack vs. Webpack.
- Vite Block (experimental WP block build).
- How webpack and WordPress packages interact.
Bedrock and Composer-first WordPress
- Roots Bedrock.
- Introducing WP Composer (WPackagist replacement).
- Installing WP plugins and themes with Composer (Upsun).
Gutenberg, performance, and accessibility
- Better Gutenberg (performance optimization layer).
- Big performance degradation in WP 6.6 editor (GitHub issue).
- Rian Rietveld’s resignation as a11y lead.
- WPCampus Gutenberg accessibility audit.
Media and assets
Playground and WebAssembly
- Build in-browser WordPress experiences with Playground (web.dev).
- How WebAssembly is powering WordPress (Wasmer).
Migration and LTS precedents
AI Disclosure: Featured image generated by Gemini, and Claude assisted with the refinement of my choices, arguments, and editing of this post and series.
Check out all of the parts:
Part 1 – The Case for the Split
Part 2 – The Kernel
Part 3 – The Admin and Editor
Part 4 – Performance and Security
Part 5 – The Plugin Economy
Part 6 – The Migration – You are on this one

Leave a comment