Laravel 13.38 лечит чтение с устаревшей реплики
20 октября 2026 года вышел Laravel 13.38 с middleware PreventStaleDatabaseReads и методом usingWritePdo(): классическая проблема read-реплик — «я только что сохранил форму, а на следующей странице вижу старые данные» — теперь решается без кастомных обёрток в каждом контроллере.

20 октября 2026 года в релизе laravel/framework 13.38.0 появилось два связанных изменения для приложений, которые читают данные с реплик базы: middleware PreventStaleDatabaseReads и метод DB::usingWritePdo(). Разбор механики с примерами кода опубликовал Laravel News — независимое издание, которое много лет курирует релизы фреймворка и регулярно сверяется с официальными changelog и PR-ами мейнтейнеров.
Что вышло
PreventStaleDatabaseReads — это middleware, которое после любой записи сохраняет в сессии пользователя метку времени. В течение короткого окна (по умолчанию 2 секунды, настраивается) последующие чтения этого же пользователя идут не через read-реплику, а через write-соединение — то, которое только что приняло запись. Как только окно истекает, чтения снова уходят на реплики. usingWritePdo() решает ту же задачу точечно: внутри callback все запросы принудительно идут через write-соединение, без привязки к сессии и глобальному middleware — удобно для одного проблемного участка кода, а не всего приложения.
В чём проблема реплик
Схема master-реплика — стандартный способ горизонтально масштабировать чтение: один write-узел принимает все изменения, несколько read-реплик обслуживают запросы на чтение и синхронизируются с задержкой в десятки-сотни миллисекунд. Для большинства сценариев это незаметно. Но ровно после записи — пользователь сохранил профиль, оформил заказ, отправил комментарий — следующий же GET-запрос рискует попасть на реплику, которая ещё не получила свежую строку. Результат пользователь видит как баг: «я же только что это сохранил, а оно пропало». До 13.38 эту проблему в Laravel закрывали руками — либо временным переключением на write-соединение в конкретном контроллере, либо принудительным redirect с задержкой, либо вовсе игнорированием, пока на это не пожалуются достаточно громко.
Кому это реально нужно
Если проект работает с одной базой без реплик, изменение ничего не меняет — PreventStaleDatabaseReads актуален только там, где read/write уже разделены. Но появление встроенного решения в ядре фреймворка — само по себе сигнал: раз Laravel включает такой middleware в стандартную поставку, значит разделение чтения и записи стало достаточно частым сценарием даже для проектов среднего размера, а не только для систем с миллионами пользователей. Архитектурное решение «когда пора заводить реплики и как не словить на этом баги консистентности» — ровно то место, где самодеятельность дороже всего обходится: поставить реплику легко, а не затопить приложение гонками чтения-записи — отдельная инженерная задача.
Что делать команде
- Если у проекта уже есть read-реплики — обновиться до 13.38 и заменить самодельные обходы стандартным middleware, это меньше кода для поддержки
- Если реплик пока нет, но трафик на чтение растёт — держать это изменение в уме как готовый кусок архитектуры на момент, когда разделение понадобится
- Проверить таймаут по умолчанию (2 секунды) на своих сценариях: для операций с более долгой асинхронной обработкой перед записью в базу его может не хватить
Когда дело доходит до реального разделения чтения и записи в продакшене, вопросов обычно больше, чем просто включить middleware — нужно продумать схему репликации, мониторинг лага, поведение при отказе одной из реплик и миграции без простоя. Для команд без выделенного архитектора под рукой разумнее не экспериментировать на проде, а привлечь подрядчика, который уже проектировал такие схемы: команда YUSMP Group ведёт разработку под ключ, включая архитектуру баз данных и масштабирование на этапе роста нагрузки.



