
Меня зовут Александр Вирочкин, я руковожу командой инфраструктуры мини-приложений ВКонтакте. За последние два года мы мигрировали один из ключевых сервисов с PHP на Go. Не всё получилось с первой попытки: мы столкнулись с типичными и не очень проблемами, зато по-настоящему оценили роль внутренней PaaS-платформы и экспертность коллег. Делимся опытом: уверены, что он будет полезен многим.
ВКонтакте сейчас трансформируется: мы постепенно переходим к сервисной архитектуре, создали единую платформу для разработки. Мой коллега Олег уже рассказывал на Хабре о PaaS. Наша команда одной из первых попробовала инструменты на реальных задачах и увидела, как с их развитием меняются и наши подходы к миграции.
В статье поделюсь, как мы дважды пробовали переписать сервис, как между попытками эволюционировала платформа для разработки и что нам это дало на практике. Возможно, наш опыт поможет вам избежать похожих проблем и вдохновит на технические эксперименты.
Знакомство с VK Mini Apps
Прежде чем перейти к основной истории, упомяну VK Mini Apps. Это открытая платформа для создания и использования приложений, которые запускаются внутри социальной сети ВКонтакте, а также на других площадках VK: Одноклассники, Mail. Мини-приложениями могут быть и небольшие виджеты вроде сервиса погоды, и приложения уровня VK Знакомств. Платформа открыта для разработчиков; чтобы создать своё мини-приложение, не требуется особых разрешений. Также нет ограничений, связанных с профессиональной деятельностью или статусом разработчика.
Наша задача — максимально упростить создание мини-приложений для сторонних разработчиков. Для этого мы постоянно развиваем платформу, снижаем порог входа и предлагаем инструменты, которые делают работу удобнее. В этой статье расскажу об одном из таких сервисов и том, как он упрощает жизнь внешним командам.
Хостинг статики
У любого мини-приложения есть набор статических ресурсов: изображения, CSS, JS-файлы, HTML-файлы. Чтобы пользователи могли работать с мини-приложением, нужно обеспечить хостинг статики. Популярный вариант — купить сервис хостинга или CDN, выложить на него статику и использовать его для раздачи. Но есть ряд «но»: дешёвые сервисы могут работать нестабильно, популярные промышленные CDN-решения могут быть дорогими. Для любительской разработки или домашнего проекта это становится камнем преткновения.
Поэтому в 2019 году мы запустили свой сервис хостинга статики. Он использует CDN-инфраструктуру ВКонтакте для быстрой и надёжной доставки статики пользователям. Более 150 узлов распределены по всей России и странам СНГ, поддерживаются раздача по HTTPS, автоматическая балансировка нагрузки и кеширование на периферии. Разработчику достаточно загрузить файлы через REST API — дальше вся маршрутизация, отказоустойчивость и масштабирование обеспечиваются внутри платформы. Такой подход оказался дешевле, надёжнее и проще интеграции с внешними провайдерами, особенно для MVP и небольших пет-проектов.

Рассмотрим работу сервиса подробнее. Глобально хостинг можно разделить на три части:
Клиентская библиотека. JS-библиотека предназначена для загрузки статических файлов на сервер — и вручную, и в автоматическом режиме. Передача данных реализована так: файлы статики архивируются, затем проходит авторизация и аутентификация пользователя. После этого архив отправляется на бэкенд для последующей обработки
Обработка архивов на бэкенде. Бэкенд написан на PHP. Воркеры загружают полученный архив в локальное хранилище сервера-обработчика и создают задачу на его обработку. Сервер-обработчик получает таск, перемещает архив в отдельную директорию, распаковывает и валидирует содержимое. Если всё успешно — заливает архив в наше хранилище статики, проверяет статус ответа и чистит за собой лишние файлы
Хранилище статики. Хранилище построено на базе Ceph и поддерживает версионирование, что позволяет тестировать различные версии статики в отдельных группах. Чтобы файлы выдавались корректно, мы реализовали алгоритм горячей замены. При загрузке новой статики система вначале проверяет статус загрузки, а затем обновляет последнюю версию, если все этапы завершены успешно. Хостинг интегрирован с нашими кеширующими фронтами на nginx, которые также используются для раздачи статики ВКонтакте и работают по аналогичной схеме
Первая попытка миграции
В 2023 году стало понятно: архитектура хостинга исчерпала себя. Количество пользователей быстро росло, возникали новые требования — поэтому мы начали работать над инфраструктурными ограничениями:
Архитектурная привязка к одному серверу. Архивы загружались на локальный диск, обрабатывались и распаковывались там же, что лишало нас гибкости в масштабировании и отказоустойчивости
Вертикальное масштабирование вместо горизонтального. Бэкенд был частью монолитной системы на PHP и не позволял развернуть несколько независимых инстансов без существенных доработок. Заранее заложенные ресурсы использовались неэффективно: сервер простаивал 95% времени
Зависимость от «здоровья» одной машины. Бэкенд зависел от надёжности конкретного сервера из-за локальной обработки архивов. Если сервер выходил из строя, мы не могли использовать хостинг статики и все необработанные архивы
Казалось, что часть проблем снимается переводом обработки архивов во временное облачное хранилище. Так нет зависимости от локального диска, можно удалять архивы по завершении операций, запускать дополнительные инстансы под нагрузкой. В этот момент к нам пришла команда PaaS и предложила протестировать облачные решения на нашем сервисе. Нам было нужно подготовить документацию для архитектурного ревью, посчитать мощность выделяемых виртуалок и обсудить всё с командой PaaS.
Выбор языка и инструментов
Мы начали с выбора языка программирования. Рассматривали только те, по которым у ВКонтакте уже были эксперты. Также было важно, чтобы язык не требовал доработок со стороны PaaS для интеграции и подходил под прикладные особенности задачи.
Остановились на трёх кандидатах:
KPHP был первым в списке: вся команда умеет работать с ним, есть активная поддержка и доработки со стороны core-департамента. Но при более глубоком погружении мы обнаружили, что язык не подходит для работы с файлами в продакшене. Оказалось, что в том числе поэтому исходный сервис был написан на чистом PHP. Любые проблемы потребовали бы изменений на уровне языка, а значит, мы зависели бы от чужого расписания
Python привычен аналитикам, есть инфраструктура в рамках PaaS, зрелая поддержка. Однако интеграция с Ceph, системой нотификаций и монолитом требовала пилить недостающие функции практически с нуля. Мы упирались в то, что могли создать набор инструментов, который нужен только нам, следовательно, и решение уникальных проблем придётся искать самостоятельно
Go. В компании были эксперты в этом языке, а в самом Go были все нужные инструменты: загрузчик файлов, библиотеки для работы с Ceph, пользовательскими нотификациями. Кроме того, язык умеет взаимодействовать с монолитными очередями. Нам не требовалось писать эксклюзивные инструменты, многое уже реализовали другие команды. Язык отлично масштабируется и работает с файлами. Единственная проблема — в нашей команде никто до этого не писал на Go, но мы были готовы экспериментировать
В общем, выбор очевиден: переписывать будем на Go. Дальше начали подсчитывать необходимые ресурсы. Избыточная стартовая конфигурация (12 ядер CPU, 120 ГБ RAM, 1 ТБ SSD) вскрыла очевидное: сервис большую часть времени потребляет мало вычислительных ресурсов, а узкое место — запись данных в Ceph. Для типовой нагрузки 2 ядер и 2 ГБ памяти оказалось более чем достаточно, а всплески трафика можно гасить масштабированием облачных инстансов. После подсчёта ресурсов мы начали готовиться к архитектурному ревью.
Особенности ревью
Хорошая практика — подготовить к встрече RFC по сервису с верхнеуровневыми С4-диаграммами архитектуры, последовательностью ключевых бизнес-процессов, примерными схемами обработки данных и оценкой по нагрузке. Стандартно на техническое ревью собираются админы, представители PaaS, смежные команды, чтобы валидировать интеграции и учесть зависимость сервисов друг от друга. Обсуждение выглядит как прожарка документации по сервису. Автор рассказывает про причины выезда, показывает текущее состояние кодовой базы и желаемый образ результата, а после презентации идёт секция вопросов и ответов. Если по итогу ревью нет конфликтов или открытых вопросов, оно считается пройденным, можно начинать работу над сервисом.
Ревью мы прошли успешно. Приступили к прототипу на Go в облаке: завели новую директорию, скопировали в неё структуру, makefile и dockerfile из нашего соседнего проекта, начали править переменные и писать код. Но приоритет работы быстро сместился на запуск спецпроектов и подготовку к новогодним релизам. В итоге сервис оказался на полке: MVP реализовать не успели, недописанный код оставили до лучших времён.
Restart 2024: почему нужно обязательно использовать второй шанс
«Лучшие времена» для недописанного сервиса наступили в 2024 году. В феврале мы столкнулись с проблемой: обработка архивов сервисом стала завершаться ошибкой в 100% случаев. Расследование показало простую причину. На сервере стояла тщательно пропатченная связка Debian + PHP ради Ceph. Очередное обновление случайно вернуло стандартную версию Debian, и интеграция с Ceph сломалась. Сервис суперстабильно работал уже четыре года, плюс это было первое крупное обновление, которое накатывали на сервер — и никто не вспомнил, что надо пропатчить Debian.
Эта ситуация стала драйвером полноценного перехода. Мы подняли приоритет задачи и вернулись к PaaS с запросом на возобновление разработки.
Повторно проходить ревью было не нужно, а вот кодовую базу из 2023 года пришлось полностью изменить. За полгода-год, пока переработка сервиса была на паузе, PaaS полностью обновили инструментарий. Появились release-кнопки, новые библиотеки, чаты поддержки по языку, кросс-ревью для новых команд и помощь с погружением в Go.
Какую помощь мы получили от команды PaaS:
Документация и поддержка. Весь путь от идеи до продакшена расписан по шагам: что делать, куда смотреть, на что обратить внимание. За это отдельный респект платформенной команде. Документация реально спасает, особенно когда ты с одного языка перепрыгиваешь на другой и невольно пытаешься тащить с собой старые привычки. Опытный коллега подскажет: «В Go так не принято, лучше сделать вот так».
Контроль качества и обучение. Перед релизом обязательно проходили контроль качества. Коллеги смотрят код, дают советы, делятся best practices.
Go-фреймворк. Всё, что от нас требуется — реализовать свою бизнес-логику, обо всём остальном фреймворк уже позаботился:
Он задаёт единый стиль для всех сервисов. Один раз написал — и уже примерно понимаешь, как устроены остальные: тут логи, тут метрики, вот тут лежат юзкейсы. Всё структурировано и предсказуемо
Из коробки поддерживается всё необходимое окружение — то, к чему мы привыкли в монолите, и даже чуть больше. Не нужно тратить время на настройку инфраструктуры или думать, как подружить сервис с остальными компонентами: всё уже готово, просто бери и используй
Благодаря такому подходу можно сосредоточиться на том, что действительно важно — бизнес‑логике, а не на бесконечной настройке и интеграциях.
Как выглядит обновлённая архитектура

Не буду останавливаться на полном описании схемы, сосредоточусь на том, какие ключевые изменения произошли по сравнению с исходной архитектурой:
Отвязались от локального хранилища. Архивы теперь лежат во временном хранилище, что позволило масштабировать сервис горизонтально и упростить обработку
Существенное сокращение потребления ресурсов. Вместо выделенного сервера с избыточными ресурсами большую часть времени сервис работает на мини-виртуалке (2 CPU/2 GB RAM). За счёт параллелизма и деплоя в облаке мы можем быстро нарастить мощности. По итогу сократили расходы на железо и освободили производительный сервер для других задач
Уход от костылей. Сервис на Go не требует отдельно патчить систему для работы с Ceph, все доработки описаны в конфигурациях деплоя сервиса
Краткое послесловие
Самый главный инсайт — не забрасывайте свои сервисы: пишите документацию, делитесь знаниями внутри команды. Если что‑то начинает пылиться в проде и кажется, что работает и ладно, не поленитесь провести аудит. Велика вероятность, что найдёте интересные моменты или потенциальные проблемы. Да, звучит банально: «пиши документацию», «делись экспертностью», но по факту именно с этим чаще всего и бывают проблемы. Если вы про это забудете, через пару лет вас ждёт неприятный сюрприз.
Выбирайте инструменты под задачу, а не по трендам. Мы выбрали Go не ради моды, а потому что он реально решает наши проблемы, и у компании есть ресурсы поддерживать этот стек. Не поддавайтесь трендам, если они не совпадают с вашими реальными требованиями.
Третий вывод — сильная core‑команда. Особенно если она такая же заряженная, как PaaS ВКонтакте. Это ребята, которые держат культурный и технический стандарт, выпускают гайды, следят за ревью и помогают не скатиться в хаос.
Эта история — про то, как можно пройти путь от сервиса, к которому были вопросы, до современного и эффективного решения, которое на голову выше того, что было.