Integrals: где я научился веб-разработке на практике
Небольшая веб-студия в Тбилиси, множество встреч с клиентами и два года разработки сайтов — с 2016 по 2018 год.

Скриптовый язык общего назначения
Небольшая веб-студия в Тбилиси, множество встреч с клиентами и два года разработки сайтов — с 2016 по 2018 год.
Консьюмер очереди на PHP, который раньше раз в пять-шесть часов падал по OOMKilled. Сообщения при этом не терялись: Kubernetes поднимал под, и консьюмер дочитывал очередь, так что снаружи проблема была почти незаметна. Но регулярное падение по памяти — не норма, и мы решили докопаться до причины...
Я провёл бенчмарки различных серверов и режимов запуска PHP: PHP-FPM + Nginx, FrankenPHP (классический и worker-режим), Rapira (классический, worker, dispatcher), OxPHP (классический, worker), RoadRunner, FreeUnit, Swoole.
Сделал калькулятор налога для самозанятых на Laravel + Inertia + Vue с SSR и выложил на обычный shared-хостинг. Сам калькулятор написал за пару вечеров. Всё остальное время ушло на то, чтобы поисковики увидели сайт так же, как браузер.
За два месяца: SSR-демон падал с EPERM, порт оказывался занят «через раз», главная месяц уходила в кэш пустой страницей, а проверка SSR в CI была зелёной, потому что не могла упасть в принципе. Плюс месяц блокировки хостером, о которой я не знал, и фильтр «малоценных страниц» от Яндекса.
Разбираю грабли по порядку — может, кому-то это сэкономит месяц.

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

Раз в минуту четыре фоновые команды обходят таблицу на сотни тысяч чатов и решают, кому бот напишет первым: у кого обновились суточные лимиты, кто начал разговор и замолчал, у кого кончилась подписка.
Год назад выяснилось, что за один проход каждая обслуживает ровно половину тех, кого сама же выбрала. Ошибок при этом нет, лог чистый, метрика отправленных растёт. Виноват chunk(), который листает выборку через OFFSET: обработанная строка из этой выборки выпадает, и окно уезжает.
Разбор на живом проекте с 300 тысячами пользователей в месяц: как chunk() теряет строки и чем его заменить, почему withoutOverlapping() по умолчанию блокирует команду на сутки, откуда берутся дубли рассылки и зачем пришлось переворачивать порядок колонок в составном индексе.

Разбираемся, как дать AI-ассистенту доступ к документации API, не загружая в контекст всю спецификацию. Импортируем Swagger PetStore в PostgreSQL и собираем на официальном пакете laravel/mcp сервер с четырьмя инструментами: поиск по документации, детали операции, именованная схема и список операций по тегу. Проверяем контракт в MCP Inspector и подключаем сервер к Claude Code.

Привет, Хабр! Меня зовут Владимир Аламов, я инженер по информационной безопасности и комьюнити-лидер сообщества Security Champions в Авито.
Недавно AvitoTech совместно с SPbCTF организовали соревнование по спортивному хакингу HoneyBadger CTF. Участникам нужно было найти в системе дыру и через неё дотянуться до спрятанных данных. Лиги сделали две: «Медовую» для новых игроков и «Барсучью» для продвинутых.
В этой статье я расскажу про одно из самых сложных заданий «Медовой лиги» — МёдХантер. Это игрушечный сервис для поиска работы. В нём нужно пройти целую цепочку и достать из одной системы сразу три флага. Начинается всё с безобидного импорта резюме по ссылке, а заканчивается запуском своего кода на чужом сервере.
Мы занимаемся веб-разработкой, CRM-системами и интеграциями. В одном из текущих проектов имеем CRM, где Telegram используется не просто для уведомлений, а как один из каналов взаимодействия с пользователем.
Наш telegram бот перестал работать.
Причём перестал весьма интересно: Telegram прекрасно принимал наши исходящие обращения через API, бот мог отправлять сообщения пользователю, но в обратную сторону — Telegram → наш webhook — запросы практически перестали доходить

Каждое нажатие кнопки в телеграм-боте — это HTTP-запрос от Telegram к вам. Около трёхсот тысяч человек в месяц, у каждого в сессии десятки нажатий, и всё это приходит в один POST-эндпоинт, у которого нет ни права на пятисотку, ни права подумать.
Пропускная способность считается до обидного просто: max_connections, делённое на время ответа. Отвечаете за 200 мс при сорока соединениях — двести апдейтов в секунду. Отвечаете за две секунды — двадцать. И ждёт при этом не абстрактный клиент, а конкретный пользователь, у которого следующее нажатие просто не доедет.
Что осталось внутри вебхука и что уехало в очередь, почему дедупликация по update_id обязана быть атомарной, зачем в ответ на вебхук можно вернуть вызов метода API — и четыре бага, которые нашлись в собственном коде, пока я это писал.

В прошлый раз я вытащил Active Record из Yii1 в отдельный composer-пакет и показал, что код Yii1 умеет жить без фреймворка. Но интереснее другое — насколько хорошо он это делает рядом с остальными. Поэтому я поднял четыре ORM на одной схеме, одних данных и одном железе и прогнал их через phpbench — код и данные лежат на GitHub. В клетке: Eloquent (Laravel), Yii2, Yiisoft Active Record (Yii3) и мой форк Active Record из Yii1 — yii1x/active-record, далее в статье — просто Yii1x.
Можно подумать: раз в предыдущем абзаце прозвучало «мой форк», то и замеры предвзяты. Признаюсь, изначально такой план и был — а потом я всё-таки постарался сделать всё максимально честно. Насколько получилось — судите по цифрам.

255 — столько у нас было пар «экран × язык» в телеграм-боте, и каждая строчка текста лежала внутри PHP-класса. Чтобы поправить запятую в немецком, нужен был PR, ревью и деплой.
Рассказываю, как мы выносили экраны и переходы бота из кода в YAML на живом проде, без окна обслуживания: почему \n в PHP не равен \n в YAML, зачем понадобилось экранирование поверх экранирования, как 64 байта callback_data определили схему базы и почему стек навигации из JSON-колонки пришлось мигрировать совместимостью, а не конвертацией. Плюс чеклист из 12 пунктов.

Очереди задач — одна из тех вещей, которые настраивают один раз и больше не трогают. Конфиг описывает известные потоки фоновых работ, деплой раскатывает его, воркеры поднимаются и делают своё дело. Так работает в подавляющем большинстве проектов. А что если появляется необходимость запускать максимально изолированные задачи, которыми должен управлять пользователь, а не разработчик: создавать, запускать, останавливать? Это единица, которую надо изолировать, появляется и исчезает между деплоями, а единственный способ рассказать об этом системе — отредактировать конфиг и раскатать всё заново.
В Laravel Horizon документация заканчивается на конфиге и паре artisan-команд про то, как поднять супервизоры, настроить воркеры, их масштабирование и указать очереди. А что, если нам нужно создать свои собственные очереди и их воркеры в рантайме? Об этом документация молчит. Но если прочитать исходники, выясняется, что конфиг — не единственный источник истины.
Эта статья на примере платформы для email-рассылок расскажет про построение динамических очередей поверх статического конфига Laravel Horizon, используя внутренние недокументированные механизмы, которые Horizon сам использует внутри себя. Про архитектуру с автоматическим восстановлением консенсуса, разрешением ошибок и оптимизацией памяти для долго живущих очередей.

Знаменитый тезис Мартина Фаулера «Anemic Domain Model — это Antipattern» знаком многим.
Тезис простой и звучит убедительно: если модель — это просто набор геттеров и сеттеров, а бизнес-логика живёт в сервисах, то это анемичная модель, процедурный код в объектной обёртке, шаг в сторону от объектного ориентирования. Звучит так себе. Правильнее — переносить поведение внутрь объекта, рядом с данными. Заказ должен уметь рассчитывать свою сумму, добавлять предметы и применять скидку. Данные и поведение живут вместе, инкапсуляция работает, сервисы превращаются в тонкие оркестраторы. Объекты — во главе вашего дизайна.
В статье порассуждаем, почему всё не так просто, как реальность иногда вмешивается в стройную теорию и что с этим можно сделать с примером реализации на PHP.

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

Всем привет! Меня зовут Антон Рыков и я backend-разработчик в компании "Исходный Код".
Пять CRUD-эндпоинтов. К обеду я понял: бизнес-логика заняла минут двадцать. Остальные два часа ушли на UUID вместо автоинкремента, одинаковые DTO с валидацией и ручную уборку временных файлов на стейджинге. Пальцы работали. Голова — нет.
Почти любая команда на Symfony рано или поздно упирается в ту же стену: фреймворк перестаёт быть помощником и превращается в конвейер. make:entity → вырезать integer id → прикрутить трейт дат → руками разобрать $request в контроллере. Снова. И снова.
DX — это не красивая тема в терминале. Это меньше трения между архитектурным решением и кодом. Правильная лень — точечная автоматизация того, что вы и так делаете каждый день.
В статье — четыре уровня, которые убрали это трение у меня. Настроите PhpStorm так, чтобы скелет JSON-экшена появлялся по Tab. Уберёте ручной json_decode и isset через MapRequestPayload и строгие DTO. Научите MakerBundle сразу генерировать сущности с UUID и вашими трейтами. Перенесёте cron в PHP через Scheduler - расписание

Больше года назад я запустил SVG4 — каталог векторных иконок. Сейчас в нём больше 500 000 SVG‑файлов.
Первая версия была написана на Laravel. На тот момент выбор был простой: Laravel я хорошо знал, на нём можно было быстро собрать рабочий проект и проверить, нужен ли он вообще кому‑нибудь.
Проект вырос. Вместе с ним выросли база, количество страниц, поисковый трафик и нагрузка. Старая версия работала на сервере с 4 ядрами и 6 ГБ оперативной памяти. После переписывания на Go весь проект работает на 2 ядрах и 2 ГБ RAM.
При этом я не ставил задачу доказать, что Go быстрее PHP. За время переписывания изменилась не только технология, но и сама архитектура приложения. Именно об этом переходе и хочу рассказать.

Библиотека для PHP, которая сканирует и подключает Wi-Fi, поднимает хотспот и держит на связи Raspberry Pi без монитора: если сеть пропала, watchdog переподключается сам, а если не выходит, поднимает точку доступа для настройки с телефона. Под капотом nmcli, wpa_cli и hostapd. Каждый релиз прогоняется на настоящем Pi, логи в репозитории.

Поехали.
Вообще говоря, я всегда делал бэкенд исключительно на PHP. Я считаю его отличным языком для бэкенда, вернее не только для бэкенда, а отличным языком. Некоторые не любят PHP за малый порог вхождения. Типа через этот малый порог вхождения входит очень много непрограммистов, которые потом пишут говнокод. Но я придерживаюсь мнения, что PHP никак не виноват в этом. Скорее наоборот. На PHP логика просыпается даже у тех, кто кроме говнокода ничего написать не может. Поэтому в любом случае это отличный язык программирования, который каждый год хоронят, но никак похоронить не могут. И в 2026 году он живее всех живых и показывает отличные результаты.
Вторым в списке для сравнения я решил поставить Дарт. Дело в том, что самое узкое место применения Дарта — это как раз-таки применение на серверах. Потому что в мобильной разработке он уже как стандарт, веб, фронтенд мало-мальцевски он тоже подтягивает. Но вот на серверах пока что его используют очень мало. Одна из причин на то, что его мало используют на серверах, — это отсутствие библиотек, таких как, например, есть у PHP. Но, тем не менее, это совсем не значит, а тем более сейчас в эпоху LLM, это совсем не значит, что Дарт негоден на серверах. Как покажет сравнение, он очень-таки годен.
Третий кандидат для сравнения — это C++. Это его фреймворк Drogon, который в каком-то там 2014 или 2015 годах взлетел как самый быстрый фреймворк для серверов на бэкенде по скорости. Если честно, я ни разу не писал бэкенд на C++, поэтому это была первая попытка. Просто хотелось посмотреть, как C++ уничтожит двух других оппонентов со своей 100x производительностью.
Разбираем переезд интернет-магазина с OpenCart 2 на Next.js и PostgreSQL. Магазин оптовый, электронные компоненты, сайту двадцать лет, в каталоге 4 751 товар. Если у вас OpenCart и вы думаете уезжать, то будет полезно почитать, что может всплыть в самый неожиданный момент.
Магазин запущен в боевом режиме, поэтому всё ниже про то, что уже перенесено и работает. Про трафик после переключения домена говорить рано, замера ещё нет. Обмен с учётной системой - отдельная большая тема, и здесь его нет.