WordPress 7.0 wychodzi dziś bez real-time collaboration. Analiza błędu który wypadł w RC.

maj 20, 2026 | Cyberflux

WordPress 7.0 wydany dziś — bez real-time collaboration (RTC), funkcji której budowę core team anonsował jako główny cel cyklu. Decyzja o usunięciu zapadła 8 maja, po wejściu w fazę Release Candidate. To bezprecedensowe w historii projektu — żadna wersja WordPress nie cofnęła major feature po RC.

Oficjalny komunikat od release leads był krótki: "critical architectural issue," nowa tabela bazy danych, przesunięcie na WordPress 7.1 (sierpień 2026). Ten wpis opisuje mechanizm dokładniej.

Jak działał mechanizm synchronizacji i gdzie leżał problem

RTC w WordPress 7.0 synchronizował stan edycji przez post meta. Każda zmiana w edytorze — wciśnięty klawisz, przesunięty blok, dodany komentarz — trafiała jako wpis do tabeli wp_postmeta z metakluczem przypisanym do sesji synchronizacji.

Post meta to mechanizm który WordPress ma od wersji 1.5. Jest dobrze przetestowany, dostępny wszędzie, nie wymaga migracji schematu — oczywisty wybór dla MVP. Problem polega na tym, że wp_postmeta nie jest zaprojektowana pod zapis o wysokiej częstotliwości ze współbieżnych sesji.

Konkretnie: każde wywołanie update_post_meta() wywołuje wewnętrznie clean_post_cache(). Ta funkcja wywołuje wp_cache_delete( 'last_changed', 'posts' ).

Klucz last_changed w grupie posts jest wersją używaną przez WP_Query przy budowaniu cache key dla wyników zapytań. Każda zmiana last_changed sprawia że wszystkie dotychczas zbuforowane wyniki WP_Query stają się nieaktualne — bez względu na to czy dotyczyły edytowanego posta, czy zupełnie niezwiązanych zapytań.

Przy RTC synchronizującym stan co kilka sekund na każdą sesję edycji: last_changed jest aktualizowany ciągle, query cache nigdy nie zdąży się wypełnić. Każde żądanie do strony które wykonuje WP_Query (strona główna, archiwa, kategorie, wyszukiwanie) trafia bezpośrednio do bazy danych.

Dlaczego skala problemu zależy od środowiska

Na standardowej instalacji bez persistent object cache (Redis, Memcached, APCu), obiektowy cache WordPress resetuje się z każdym żądaniem HTTP. Invalidacja last_changed przez post meta dotyczy wtedy tylko cache w ramach bieżącego requestu — co ma znaczenie gdy ten sam request wykonuje wiele WP_Query, ale między requestami i tak nie ma state'u do invalidowania.

Problem ujawnia się w środowiskach z persistent object cache — a to jest dokładnie infrastruktura którą WordPress.com, Automattic Pressable, WP Engine, Kinsta i inne managed hostingi mają domyślnie włączoną dla wydajności. Na tych środowiskach wp_cache_delete( 'last_changed', 'posts' ) wysyła DELETE do Redisa lub Memcached — usuwając klucz który jest współdzielony między wszystkimi żądaniami.

Przy sesji RTC synchronizującej stan co dwie sekundy: w każdym dwusekundowym oknie każde żądanie do dowolnej strony listującej posty musi wygenerować zapytanie do MySQL zamiast trafić do cache. Na stronie z ruchem rzędu kilku tysięcy odsłon na godzinę: wzrost liczby zapytań do bazy danych jest bezpośrednio proporcjonalny do liczby równoczesnych sesji RTC.

Inna klasa problemu pojawia się w samym edytorze. WordPress ładuje metadane posta przez get_post_meta() przy inicjalizacji edytora i w trakcie operacji. Jeśli jednocześnie update_post_meta() jest wywoływany przez sync, clean_post_cache()invaliduje cache metadanych dla tego posta. Przy intensywnej synchronizacji: kolejne wywołania get_post_meta() w tej samej sesji wymagają ponownego zapytania do bazy zamiast trafić do cache.

Precedens RC → revert

Cykl wydania WordPress 7.0 przebiegał standardowo do 31 marca. Tego dnia release lead Mélodie Frenot-Nelson opublikowała wpis na Make WordPress Core anonsujący że wejście w RC wymaga przedłużenia — odkryto "performance issue requiring a deeper architectural fix."

Release Candidate to faza w której kod jest semantycznie zamrożony. Patche mogą dotyczyć tylko regresji i krytycznych bugów, nie nowych feature'ów ani przeprojektowań. Cofnięcie całej funkcji z RC nie ma precedensu w historii projektu od wersji 2.0 wzwyż — każda poprzednia sytuacja w której feature nie zdążył do wydania kończyła się albo przesunięciem daty, albo wyłączeniem przez feature flag z pozostawieniem kodu.

Tym razem kod został usunięty. Commit revert: remove real-time collaboration tables migration z 8 maja usuwa zarówno logikę synchronizacji jak i migrację schematu bazy danych która miała tworzyć nową tabelę — bo równolegle z decyzją o usunięciu zapadła decyzja o zmianie architektury.

Co zmienia architektura dedykowanej tabeli

Rozwiązanie dla WordPress 7.1: osobna tabela wp_collab_sessions (robocza nazwa z otwartego Trac ticket #63418) przechowująca stan synchronizacji oddzielnie od wp_postmeta.

Zapisy do własnej tabeli nie przechodzą przez clean_post_cache() — WordPress nie ma mechanizmu który automatycznie invalidowałby query cache przy zapisie do niestandardowej tabeli. Persistent object cache pozostaje nienaruszony niezależnie od intensywności synchronizacji.

Pojawiają się natomiast nowe pytania architektoniczne:

  • cleanup po porzuconych sesjach — jak usuwać rekordy z wp_collab_sessions gdy użytkownik zamknie okno bez explict zakończenia sesji
  • spójność przy równoczesnych zapisach — MySQL bez row-level locking dla wp_postmeta (który korzysta z transakcji WordPress) vs. własna tabela z własnym schematem transakcji
  • migracja na hostingach z restricted DDL — nie każde środowisko pozwala na CREATE TABLE w trakcie update

Ten ostatni punkt jest prawdopodobnie jednym z powodów dla których fix wymagał pełnego cyklu wydania zamiast patcha: migracja schematu przy update na środowiskach z restricted DDL (co dotyczy sporej części hostingów shared) jest operacją którą trzeba starannie przetestować.

Model zagrożeń po zmianie

Osobna tabela izoluje ryzyko invalidacji cache. Ale real-time collaboration otwiera nową powierzchnię której WordPress wcześniej nie miał: współdzielony mutowalny stan między sesjami użytkowników.

Klasyczna instalacja WordPress jest bezstanowa z perspektywy edycji — jeden użytkownik, jeden post, atomowe zapisy. RTC dodaje stan który jest współdzielony i ciągły: informację o tym kto edytuje, gdzie kursor każdego z nich się znajduje, jakie zmiany czekają na synchronizację.

Ten stan — w wp_collab_sessions lub innej strukturze — wymaga własnej analizy dostępu. Kto może czytać state synchronizacji dla danego posta? Czy contributor widzi gdzie w dokumencie jest admin? Czy state wyciekają między rolami? To pytania które Trac ticket #63418 ma otwarte na dzień dzisiejszy.

Architektura dedykowanej tabeli rozwiązuje konkretny problem cache invalidacji. Czy rozwiązuje model dostępu do session state — to będzie widoczne gdy 7.1 beta pojawi się w lipcu.