avatar
Артём Шумейко
@artemshumeiko
12.05.2026 06:56
Утечка памяти на фронтенде — да, такое бывает

Пару месяцев назад у нас в Солвите начал периодически умирать фронтенд. Просто в какой-то момент Docker-контейнер останавливался, и Nginx показывал 504 ошибку, т.к. некуда было вести пользователя.

Когда я полез разбираться, оказалось, что контейнер с фронтендом раздувался по памяти до 3–4 гигабайт, хотя должен был занимать около 1-1.5 гб. Из-за этого на сервере заканчивалась оперативка, и Docker-контейнер автоматически падал

Казалось бы, откуда на фронтенде утечка памяти? Он же вроде как "только в браузере" работает. Но у нас SSR (писал про него раньше), а это значит, что фронтенд запущен как отдельный Docker-контейнер, внутри которого крутится Node.js. В Солвите несколько тысяч задач с собеседований и вопросов для подготовки, и все эти страницы кэшируются для SEO-оптимизации* — и это довольно уязвимое место, где легко может возникнуть проблема с памятью. *SEO-оптимизация - это когда поисковики типа яндекса и гугла отображают твой сайт в поиске, для этого все страницы должны отдаваться сразу как готовый HTML код со всеми данными внутри.

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

В какой-то момент я даже докупил оперативки на сервер, и проблема вроде как отступила — утечка останавливалась где-то на 3,5–4 гигабайтах и дальше почти не росла. Но меня всё равно не покидало ощущение, что это какой-то бред и так быть не должно. И вот однажды меня это окончательно выбесило, и я решил сесть и разобраться до конца. Сделал специальные ручки для дебага на фронтенде, чтобы смотреть, сколько памяти занимают разные закэшированные страницы, и, конечно же, отправлял эти данные в ChatGPT, чтобы вместе разобраться, в чём проблема. Пару дней смотрел на них — и наконец понял, в чём дело.

Чтобы вы понимали контекст: перед тем как серверная сторона фронтенда сгенерирует HTML и отправит его в браузер, она должна получить из нашего внутреннего хранилища ссылку на OG-изображение для этой страницы, чтобы при шаринге ссылки картинка красиво отображалась. Так вот, проблема была в том, что в каждую страницу подгружалось не одно нужное изображение, а всё хранилище целиком — все три тысячи записей. То есть у нас было 3000 страниц, и в каждой лежало 3000 JSON-объектов с названием, путём и полной ссылкой на картинку — это 9 миллионов лишних записей, которых там быть не должно. Если прикинуть в байтах: один объект весит около 150 байт, а 9 миллионов × 150 байт ≈ 1.3–1.5 гигабайта лишних данных. Плюс, как оказалось, там ещё сохранялись другие данные, и суммарно всё это занимало лишние 2–2.5 гигабайта оперативки.

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

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


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

Расскажите в комментах, какие у вас были утечки памяти

🔥 — был опыт с утечками памяти
👍 — не сталкивался
👍 60
🔥 31
emoji 17
16
😁 2
🎉 2
6 35 8K

Обсуждение 6

Обсуждение не доступно в веб-версии. Чтобы написать комментарий, перейдите в приложение Telegram.

Обсудить в Telegram