Разработка бэкенда на PHP Laravel: оптимизация и масштабирование

Проект на Laravel растёт, и там, где раньше хватало одной машины, начинаются задержки и отказы под нагрузкой. Мы берём бэкенд на Laravel и приводим его в порядок: оптимизируем запросы, очереди и кэш, выносим тяжёлые сервисы. После переработки типовые операции ускоряются в разы, а пиковая нагрузка перестаёт валить сервис.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Разработка бэкенда на PHP Laravel: оптимизация и масштабирование
Средний
от 1 недели до 3 месяцев
Часто задаваемые вопросы

Разработка бэкенда Laravel: где ломается проект на росте

Разработка бэкенда Laravel редко ломается в момент запуска — первые симптомы появляются, когда рост числа обращений перестаёт быть линейным. Отдельные страницы начинают отвечать медленнее, затем время ответа под нагрузкой скачет на пиках, и кэш уже не маскирует проблему. Узкое место серверной части почти всегда одно и то же: приложение упирается в базу и в порядок внутри кода, а не в количество серверов.

Самая частая причина — тяжёлые запросы к базе: выборки без индексов, обращения внутри циклов вместо пакетной загрузки связей, агрегаты по всей таблице на каждый показ страницы. Под нагрузкой к ним добавляются блокировки — транзакция, открытая на время внешнего вызова, держит строки и выстраивает очередь остальных запросов.

Вторая точка отказа — дублирование логики в контроллерах. Один и тот же расчёт статуса или стоимости живёт в нескольких методах, постепенно расходится по поведению, и любая правка становится регрессом, который ловится уже на проде.

Отдельно проявляется падение фоновых задач: очередь растёт быстрее, чем её разбирают обработчики, повторы упираются в те же заблокированные строки, а зависшая задача молча держит выборку и тормозит остальных.

Симптомы связаны между собой: медленный запрос в контроллере бьёт и по веб-ответу, и по задаче в очереди. Дальше разбираем, как мы находим такие места и что меняем — с замерами до и после.

Что меняется после переработки: измеримые эффекты

Сокращение времени ответа

Основной выигрыш даёт перестройка работы с данными: тяжёлые выборки заменены кэшем и подготовленными представлениями, связи между таблицами переписаны так, чтобы обходиться без полных сканирований. Замеры снимаем до и после на одном и том же профиле нагрузки — на Laravel видно, где время уходит в запросы, а где в промежуточные слои. Время ответа типовых страниц сокращается в разы, а не на проценты, и это фиксируется графиками в отчёте.

Предсказуемость на пиках и обработка очередей

Рассылки, выгрузки и пересчёты уходят из пользовательского запроса в очереди и выполняются обработчиками с ограничением параллелизма. Длительные задачи больше не держат соединение и не забирают память у страниц, которые обслуживают людей. Потребление ресурсов становится ровным — на графике полка вместо пилы, а число одновременных операций задаётся заранее и не растёт вместе с трафиком. Пик нагрузки больше не превращается в отказ.

Уход класса отказов из-за деградации базы

Основная причина падений — не ошибка в коде, а перегруженная база: соединения заканчиваются, запросы ждут и падают по таймауту. Мы ограничиваем пул соединений, разводим чтение и запись, ставим таймауты и повторы на идемпотентные операции, а тяжёлые отчёты переносим на отдельный контур. Отказы, вызванные деградацией, уходят как класс: в мониторинге остаются единичные события вместо регулярных аварий.

Форматы работ: оптимизация, переписывание, вынос сервисов

Формат работ выбирается не по размеру кодовой базы, а по профилю узкого места: где именно деградация — в запросах к базе, в разросшемся коде контроллеров или в одном модуле, который тянет за собой весь монолит. Ниже — три реальных пути и их ограничения.

Вариант Когда подходит Ограничения
Оптимизация существующего кода Замедление точечное: тяжёлые выборки, дубли запросов, нет кеша Не спасает, если упирается в общий разделяемый ресурс
Переписывание слоя доступа к данным Логика выборок расползлась по контроллерам, модели разрослись Нужны тесты до начала работ, иначе нет безопасного отката
Вынос нагруженного модуля в отдельный сервис Один участок держит трафик и требует своего масштабирования Появляется сетевое взаимодействие, отдельные сборка и наблюдаемость

Оптимизация кода и слой доступа к данным

Оптимизация существующего кода идёт первой, когда проблемы локальны: снимаем дубли выборок, добавляем индексы, кешируем тяжёлые ответы. Такой путь самый быстрый по времени до результата и не меняет структуру приложения — но он не поможет, если узкое место архитектурное.

Когда доступ к данным размазан по контроллерам и моделям, дешевле переписать слой доступа к данным: собрать выборки в репозитории, привести запросы к единому виду и покрыть тестами. Это больше работы, зато следующий виток нагрузки уже не потребует переписывания логики заново.

Вынос модуля и рефакторинг без остановки

Вынос нагруженного модуля оправдан, когда участок требует собственного масштабирования и своего цикла выпуска. Плата — усложнение эксплуатации: сетевые вызовы, отдельные сборка, логи и развёртывание, обработка частичных отказов.

Рефакторинг без остановки ведём за переключателем: новая ветка кода включается признаком на часть трафика, старая остаётся для мгновенного отката. Формат фиксируем после замера профиля нагрузки — опишите задачу, и мы вернёмся с оценкой и планом.

Этапы работ: от аудита узких мест до передачи команде

Работы начинаются не с переписывания, а с замера. Пока нет цифр «до», любое изменение — вопрос веры: сначала фиксируем состояние системы, потом трогаем код.

  1. Аудит кодовой базы Laravel. Дублирующиеся запросы, обращения к базе внутри циклов, отсутствующие индексы и места, где соединение держится дольше, чем нужно.
  2. Снятие метрик производительности. Профилируем ключевые сценарии: время ответа, число запросов на операцию, потребление памяти, доля времени в базе и внешних сервисах. Это база для сравнения «до» и «после».
  3. Схема взаимодействия. Приложение, кэш, очередь, база и внешние сервисы на одной схеме — видно, где теряется время и отказ какого узла утягивает за собой остальные.
  4. План изменений. Приоритеты по соотношению эффекта и риска: сначала правки, дающие выигрыш без переписывания, затем структурные.
  5. Изменение конфигурации и точечная оптимизация. Пул соединений, индексы, кэширование повторяющихся вычислений, вынос тяжёлых операций в фоновую очередь.
  6. Проверка на нагрузке. Повторный прогон тех же сценариев с теми же метриками, сравнение результатов и поведение системы при отказе отдельного узла.
  7. Передача команде. Документация, регламент выката, дашборды метрик и разбор с вашими инженерами — система остаётся управляемой и без нас.

Артефакты проекта: схемы данных, регламенты, документация

Готовый бэкенд — это не только работающий код, но и набор артефактов, по которым систему можно развернуть, изменить и починить без авторов. Передаём их в репозитории рядом с исходниками, в том же формате, что и код, чтобы правки проходили общее ревью и документ не расходился с реальностью через месяц.

  • Схема сервисов — какие процессы поднимаются, как проходят запросы, где стоят кэш, очередь и база, от каких внешних поставщиков зависит приложение и в каком порядке окружение собирается с нуля.
  • Схема данных — таблицы, связи, индексы и осознанные денормализации с пояснением, зачем они сделаны; рядом миграции, по которым видно переход базы на каждом релизе.
  • Описание очередей — какие задания уходят в фон, сколько попыток и с каким интервалом им даётся, где требуется идемпотентность, как найти зависшее задание и безопасно перезапустить его.
  • Правила доступа — роли и права в интерфейсе администратора и программном интерфейсе, где хранятся ключи, как они меняются, кто и по какой процедуре получает доступ к рабочему контуру.
  • Регламент выкладки — порядок сборки релиза, прогон миграций, прогрев кэша, проверки после выпуска и пошаговый откат на предыдущую версию, если поведение разошлось с ожидаемым.
  • Документация по поддержке — типовые отказы и их симптомы, какие метрики и журналы смотреть первыми, на какие оповещения реагировать сразу, а какие разбирать в рабочее время.

Отдельным пунктом идёт описание окружений: переменные, отличия тестового контура от рабочего, вынесенные из репозитория секреты. Вместе этот комплект сокращает ввод нового инженера до дней и снимает зависимость от разработчиков бэкенда на Laravel, которые вели проект.

Кейс: Laravel-проект под растущей нагрузкой, метрики до и после

Проект — сервис обработки заказов: Laravel за обратным прокси, база и очередь в отдельных контурах. На пике до 900 одновременных обращений время ответа выросло с 0,4 до 3,5 секунды, доля ошибочных запросов дошла до 12%, а падения обработчиков очереди давали до 40 минут простоя в сутки. Часть задач умирала по таймауту, клиенты видели пустые списки вместо истории заказов.

Профилирование показало три узких места. На одну карточку заказа уходило до 300 запросов к базе — связанные сущности тянулись по одному. Отчёты и рассылки считались синхронно в том же процессе, что и веб-запросы, и блокировали приём новых заказов. Кэш конфигурации и маршрутов не собирался, каждый запрос заново разбирал файлы.

Что изменили в коде и конфигурации

Связи перевели на предзагрузку, добавили составные индексы под фактические условия фильтрации, агрегаты вынесли в кэш с инвалидацией по событиям модели. Тяжёлые операции ушли в очередь на отдельные обработчики с ограничением попыток и повтором упавших задач. Приложение запустили в нескольких экземплярах, сессии и кэш вынесли в общее хранилище, статику — на внешний слой отдачи.

Через месяц на том же профиле пика: время ответа — 0,3 секунды, доля ошибок — 0,4%, внеплановый простой — ноль, окно плановых работ — несколько минут. Контур выдержал трёхкратный рост одновременных обращений без новых серверов, а масштабирование дальше шло без правок кода.

Чем отличается кэширование в приложении от кэширования в базе?

Это два разных уровня ответственности, а не альтернативы. Кэш приложения хранит готовый результат рядом с кодом: собранный ответ, агрегат из нескольких выборок. Кэш на стороне базы ускоряет доступ к данным — план запроса, материализованное представление, страницы индекса. Разница видна, когда данные изменились.

Уровень Что хранит Когда даёт эффект Когда вредит
Кэш приложения Готовые результаты вычислений Тяжёлые агрегаты, повторные чтения, внешние вызовы Несколько инстансов с разными данными; частые правки записей
Кэш на стороне базы Планы запросов, представления, индексы Однотипные частые чтения Транзакционная запись: обслуживание дороже самого запроса

Решает инвалидация кэша. База сбрасывает свой кэш на уровне транзакции — устаревшие данные живут доли секунды. Приложение такой гарантии не даёт: при нескольких инстансах ключи помечают недействительными вручную, и пропущенная ветка кода возвращает клиенту устаревшие данные.

Выбор уровня кэширования диктует профиль нагрузки. Если время уходит на вычисления и сборку ответа — кэшируем в приложении: в Laravel это отдельный слой поверх хранилища. Если на ожидание запроса к базе — добавляем индексы, представления и реплики для чтения, не меняя логику приложения.

Технические сомнения: очереди, миграции, регресс

Сомнения обычно всплывают на этапе передачи проекта или первого релиза. Пять вопросов, которые задают чаще всего, с короткими практическими ответами.

Долгие рассылки и выгрузки блокируют интерфейс?

Нет. Всё, что длится дольше пары секунд, уходит в очередь и считается фоновыми обработчиками. Пользователь получает ответ сразу, а начатое задание не теряется при перезапуске службы.

Можно ли обновлять схему базы без остановки сервиса?

Да. Миграции идут безопасными шагами: сначала новые поля и индексы, затем перенос данных порциями и только потом переключение чтения и записи. Старая версия приложения работает всё это время.

Как убедиться, что доработка не сломала работающее?

Ключевые сценарии — оплата, вход, оформление заказа — закрыты автотестами и прогоняются перед каждой выкладкой. Изменение выходит только при зелёном прогоне, а критичные пути проверяем на копии рабочей базы.

Кто имеет доступ к базе и персональным данным?

Доступ выдаётся по ролям и только под текущую задачу, каждое подключение попадает в журнал. Чувствительные поля шифруются, копии хранятся отдельно и регулярно проверяются восстановлением.

Что если у нас нет своей команды разработки?

Проект ведём так, чтобы его можно было передать: схемы данных, инструкции по развёртыванию, описание окружений и политики доступа. Код хранится в общей системе контроля версий с полной историей — новому подрядчику не нужна археология.

Ниже — остальные вопросы, которые стоит закрыть до старта работ.

Обсудим вашу задачу: с чего начнём и что понадобится

Чтобы вернуться с оценкой и планом работ, а не с общими формулировками, инженерам нужен доступ к реальной картине: метрикам, логам и описанию пиковых нагрузок. Чем конкретнее вводные, тем точнее состав этапов и порядок работ — без «уточним по ходу».

Что прислать для оценки:

  • доступ к метрикам приложения: графики времени ответа, доля ошибок, загрузка базы данных за последние недели;
  • описание пиков — когда они случаются, во сколько раз растёт нагрузка, какой участок перестаёт отвечать первым;
  • текущие конфигурации: настройки веб-сервера, очередей, кеша, число соединений с базой;
  • схему развёртывания: сколько серверов, как распределяется трафик, где живут сессии и файлы;
  • перечень интеграций и внешних сервисов, к которым обращается бэкенд;
  • доступ к тестовому окружению или репозиторию — при необходимости под соглашение о конфиденциальности;
  • список жалоб пользователей с датами и временем, чтобы связать их с событиями в логах.

Первый разговор с инженером занимает около часа: разбираем узкие места, уточняем ограничения по срокам и совместимости, намечаем приоритеты. По итогу вы получаете оценку и план работ с последовательностью этапов и точками контроля на каждой итерации.

Опишите задачу — вернёмся с оценкой и планом.

Наши компетенции:

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1542
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1394
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1369
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1141
  • Разработка веб-сайта для компании ФИКСПЕР
    Разработка веб-сайта для компании ФИКСПЕР
    1060