15708
Присоединяйтесь к нашему каналу и погрузитесь в мир Backend-разработки Связь: @devmangx РКН: https://clck.ru/3FobxK
Этот трюк с GitHub PR надо знать
Просто добавь “0” перед словом “github” в URL любого Pull Request, и у тебя откроется полноценный PR-вьювер, который подсвечивает каждую строку diff’а цветом в зависимости от того, сколько внимания от человека она, скорее всего, требует.
Он ищет не только баги. Он подсвечивает всё, что заслуживает второго взгляда: захардкоженные секреты, странные крипторежимы, подозрительную логику или грязный код.
Очень полезный способ быстрее проводить code review и находить то, что обычно легко пропустить.
👉 @BackendPortal
Раньше у GitHub была монолитная база данных, которая держала 950 000 транзакций в секунду 🤯
Но по мере роста компании эта база превратилась в... сами понимаете что. Логичное решение = развалить монолит на несколько меньших баз. На деле все оказалось гораздо сложнее, чем они думали.
Я как раз нашёл видео, где разбирают весь их процесс: какие шаги они предпринимали, как сделали миграцию без даунтайма и при этом ничего не сломали в существующем функционале.
После просмотра ты поймешь, как в реальных проектах мигрируют базы без простоя, как подходить к таким сложным задачам по шагам, и получишь живой пример того, с какими проблемами сталкиваются при масштабировании баз данных и как их решают.
👉 @BackendPortal
Уроки по ИБ, белый хакинг, вирусы, социальная инженерия, безопасность
ИБ Книга — Более 1660 русскоязычных книг по ИБ и Социальной Инженерии можно найти на канале.
no system is safe // cybersec — один из древнейших ресурсов по информационной безопасности в рунете. Книги, курсы, полезные тулсы, уроки по Linux, новости клирнета и даркнета.
Python и 1000 программ — уроки по Python. Python мы будем использовать для создания хакерского софта.
Этичный Хакер — один из крупнейших ресурсов по информационной безопасности в СНГ.
Бэкап — канал с исходниками популярных проектов. Здесь вы найдёте исходные коды нейросетей, ботов, сайтов и других интересных проектов, которые дадут дополнительные знания
Весь материал на каналах в общем доступе. Ничего лишнего.
Тебя спрашивают на бэкенд-собесе.
Вопрос:
Как бы ты спроектировал распределенную систему cron-планирования, которая гарантирует, что задачи будут запускаться ровно один раз, вовремя, на нескольких нодах, без коллизий и дубликатов?
Я бы построил распределенный cron с централизованным управлением расписаниями, несколькими scheduler-нодами и распределенным локом, чтобы задача триггерилась ровно один раз. Выполнение вынесено в пул воркеров, каждый запуск логируется, ретраи координируются через очередь, и система остаётся консистентной даже при падении нод.
Оказалось, что контейнеры внутри одного Cloud Run инстанса могут общаться по локалке. Например через http://localhost:5000
Если задать контейнерам имена (например sidecar), то можно обращаться уже так: http://sidecar:5000
Полезно, когда нужно подключить sidecar-сервис или поделить задачи между контейнерами.
Репо с примером:
https://github.com/steren/cloud-run-multi-container-communication
👉 @BackendPortal
Крупные компании вроде Reddit перенесли бэкенд комментариев с Python на Go и в результате срезали критическую задержку почти вдвое.
Это хорошо показывает типичный выбор для команд разработки:
Python — быстрее в разработке (прототипы, богатая экосистема библиотек)
Go — быстрее в продакшене (низкая задержка, отлично держит высокую нагрузку)
Кому хочется выучить Go через практику и реальные проекты — можно глянуть это
👉 @BackendPortal
Когда готовишься к собесам в FAANG или просто техинтервью, обычно нужно решать тонну задач.
Но фишка в том, что не надо запоминать все решения.
Важно другое — научиться узнавать паттерны. 💊
Вот 25 основных паттернов, которые реально помогают проходить собеседования спокойно и без паники.
Базовые паттерны для массивов и поиска
1. Two Pointers — когда массив отсортирован или нужно найти пару элементов.
2. Sliding Window — задачи на подстроки и непрерывные подмассивы.
3. Prefix Sum — быстрый подсчет суммы диапазонов.
4. Merge Intervals — работа с пересекающимися интервалами.
5. Binary Search — всё, что касается поиска в отсортированных данных.
Сортировка, рекурсия и связанные списки
6. Sorting-Based — сортировка перед анализом данных.
7. Fast and Slow Pointers — поиск середины или цикла в связном списке.
8. Backtracking — генерация комбинаций, перестановок, рекурсивные обходы.
9. Divide and Conquer — разбиение задачи на подзадачи и объединение результата.
10. Linked List Tricks — разворот списка, удаление узлов, двойные указатели.
Стек, очередь и хеш-структуры
11. Stacks & Queues — задачи на LIFO/FIFO.
12. Monotonic Stack — поиск следующего большего или меньшего элемента.
13. Expression Evaluation — парсинг выражений, калькуляторы, скобки.
14. String Manipulation — палиндромы, анаграммы, работа со строками.
15. Hashmaps — быстрые lookup, подсчеты частот.
Деревья, кучи и продвинутые структуры
16. Binary Trees & BST — обходы, баланс, минимумы, максимумы.
17. Path Sum — поиск валидных путей или сумм в деревьях.
18. K-th Largest (Heaps) — получение k-го по величине элемента.
19. Top-K Frequent — задачи на частотность.
20. Merge K Sorted Lists/Arrays — объединение нескольких отсортированных потоков.
Алгоритмы и системное мышление
21. Dynamic Programming — оптимизация и задачи с пересекающимися подзадачами.
22. Greedy — локально оптимальные шаги для финального результата.
23. Graph Traversal — BFS/DFS, обходы, проверка связности.
24. Graph Algorithms — кратчайший путь, стоимость, маршруты.
25. Design Problems — структуры вроде LRU Cache, Rate Limiter, Trie и т.п.
👉 @BackendPortal
Вот небольшая анимация, которая показывает, как циклы искажают связь между исходным кодом и реально выполняемыми инструкциями. Думаю, новичкам это часто сложно понять, но по моему мнению, умение делать такие выводы — один из ключевых шагов к тому, чтобы научиться действительно хорошо читать код.
👉 @BackendPortal
Так что я, как обычно, копался в Docker и узнал, насколько круто у него работает сеть.
Когда создаешь контейнер, он по умолчанию использует bridge-сеть, и контейнер получает приватный IP через встроенный IPAM (IP Address Management) драйвер автоматически.
Но можно создать свою кастомную bridge-сеть (user-defined network), и тогда контейнеры смогут общаться по имени, если они в одной сети. В дефолтной bridge-сети контейнеры могут общаться только по IP.
Я попробовал собрать простую небольшую продакшн-эмуляцию, чтобы лучше разобраться. Там четыре контейнера: API-сервер, веб-фронтенд, база данных и reverse-proxy. И три bridge-сети: database, backend и frontend.
API-сервер подключен к database и backend сетям, а nginx-proxy подключен к frontend и backend, потому что ему нужно прокидывать трафик между портами. Контейнеры в одной сети могут пинговать друг друга, остальные — нет, пока ты явно не подключишь их к нужным сетям.
Сеть database изолирована и без доступа в интернет с флагом --internal. Это удобный способ защитить базу. Контейнеры внутри этой сети могут общаться друг с другом, но доступа наружу у них нет.
Остальные контейнеры получают доступ в интернет классическим способом - у каждого свой приватный IP, и они подключены к docker0 через veth-пары (виртуальные Ethernet-интерфейсы). docker0 работает как виртуальный свитч, который отвечает за маршрутизацию трафика между контейнерами и сетью хоста. Это выглядит круто, потому что фактически имитирует интернет в миниатюре, только вместо физических устройств тут контейнеры.
👉 @BackendPortal
TLS termination звучит просто, но это один из ключевых элементов современной инфраструктуры.
Вместо того, чтобы каждый бэкенд сам занимался шифрованием и расшифровкой, всю TLS-нагрузку берет на себя балансировщик на границе сети.
Когда клиент подключается, TLS-handshake происходит между браузером и балансировщиком. Балансировщик использует свой сертификат, устанавливает защищенный канал и расшифровывает входящий HTTPS-трафик.
Дальше он общается с бэкендами уже по обычному HTTP внутри приватной сети.
В результате сервера приложений не тратят CPU на криптографию, им не нужны сертификаты, и они занимаются только бизнес-логикой.
Плюс обновление сертификатов становится проще — все лежит в одном месте, а не разбросано по десятку сервисов.
Важно помнить:
незашифрованный трафик живет только внутри доверенной внутренней сети. Снаружи все остается зашифрованным до самого балансировщика.
Короткая заметка про k8s:
Оказалось, что можно настраивать лимиты пропускной способности для пода или деплоймента. По умолчанию эта фича отключена. Но входящий и исходящий трафик можно контролировать через аннотации на поде, примерно так 😃
Кстати: M это Mbps, G это Gbps.
👉 @BackendPortal
Одна простая привычка, которая сильно упрощает поддержку Dockerfile, это сортировка многострочных списков пакетов по алфавиту.
На первый взгляд мелочь, но влияние на читаемость и будущую поддержку заметное.
Когда ставишь пакеты в многострочном apt-get install или apk add блоке, легко случайно добавить дубликат или пропустить что-то, что затерялось в середине списка.
Алфавитная сортировка полностью снимает этот вопрос. Список можно быстро просканировать, сразу увидеть дубли и держать всё в едином стиле на разных окружениях.
Плюс уменьшаются шумные диффы в код-ревью.
Когда пакеты отсортированы, добавление или удаление одного пункта выглядит как аккуратное и предсказуемое изменение.
Без сортировки маленькое обновление часто превращается в огромный diff, и ревью становится сложнее, чем должно быть.
Этот подход особенно полезен, когда команда растёт.
Несколько человек, трогающих один Dockerfile, не начинают перетасовывать строки под свой вкус или форматировать по-разному.
Структура остаётся стабильной, и поддержка со временем становится проще.
Небольшое улучшение, но на сотнях билдов оно экономит заметно нервов и времени.
👉 @BackendPortal
💧 А вы заметили, насколько сейчас сложнее устроиться на работу?
Да даже получать приглашение на техническое собеседование.
К примеру, на хх.ру при нормальном резюме после 100 откликов — ты должен получить минимум 4 приглашения от эйчар.
Если у вас меньше, то тут что-то не чисто.
И это я говорю, если мы будем откликаться на позицию мидл и сеньор, т.к. на джунов вакансий кратно меньше.
Один мой знакомый недавно проводил эксперимент на эту тему:
Он выложил вакансии на 3 разные позиции и посмотрел на всё это дело глазами HR, разобрал резюме кандидатов, а затем выложил ролик на свой ют канал.
Его зовут Вадим Новоселов - один из немногих, кто показывает рынок трудоустройства в IT изнутри.
В тг канале много авторского контента:
(тут) можно оставить своё резюме для прожарки на предстоящем стриме
(тут) гайд по трудоустройству за 3-4 месяца
(тут) подкаст о том, что будет с рынком айти в рф
Этот человек вкладывает душу в свой контент и проекты, советую подписаться и черпать для себя полезные фишки: @gernar288
Совет: всегда добавляй workflow_dispatch в триггеры workflow.
Так у тебя появится кнопка в UI GitHub, чтобы вручную запускать новые прогонки (когда CI, как обычно, развалится).
👉 @BackendPortal
Сообщество разработчиков объявило о выходе экспериментального CRDT-расширения для Postgres. Проект открыт и доступен для изучения и использования.
CRDT это тип данных, который применяется в приложениях с одновременным редактированием. Простой пример — Google Docs, где несколько пользователей могут печатать одновременно, а изменения автоматически объединяются без конфликтов.
Обычно такие структуры сериализуются на стороне сервера и только потом сохраняются в базу. Новое расширение меняет подход: теперь Postgres может работать с CRDT нативно — хранить, индексировать, искать и автоматически объединять изменения прямо в базе данных.
Авторы проекта показывают, как это может выглядеть в будущем:
create table blog_posts (
id uuid primary key,
title text,
body crdt default '{}'
);
Когда между идеей и продом — преград нет!
В VK любят решать сложные и масштабные задачи, а ещё — быстро реализовывать идеи. Компания рассказала, каких принципов придерживается команда в работе и какими результатами гордится. Переходите по ссылке, там много интересного!
Когда приложению нужно узнать о чем-то важном, например что пользователь оплатил подписку, у тебя есть два варианта:
1. приложение дергает API раз в пять минут, проверяя, был ли новый платеж;
2. платежная система сама шлет тебе уведомление в момент события.
Первый вариант — это polling: ты спрашиваешь, даже если ничего не произошло. Работает, но медленно и плохо масштабируется.
Второй вариант — webhook: HTTP-коллбек, который срабатывает, когда произошло событие.
Вместо того чтобы опрашивать систему, она сама присылает нужные данные.
Как выглядит поток, если ты используешь вебхук:
1. настраиваешь публичный эндпоинт;
2. твой сервер принимает POST с данными платежа;
3. проверяешь подпись (секретный ключ);
4. выполняешь свою бизнес-логику (платеж подтвержден, подписка активна и так далее).
Типичные проблемы:
- платеж может прийти дважды, поэтому сохраняют обработанные ID (идемпотентность);
- события могут прийти не по порядку, так что на хронологию лучше не рассчитывать;
- запрос может отправить кто угодно, поэтому обязательна проверка подписи.
Вебхуки важны потому, что избавляют приложение от постоянного опроса сторонней системы.
Сегодня их используют везде: платежи, подписки, деплои, интеграции, автоматизации и вообще любые сценарии, где другой сервис узнает о событии раньше тебя.
👉 @BackendPortal
Большинство людей используют grep чтобы искать по файлам. Я использую его чтобы выживать в продовых пожарах в 3 ночи.
grep "error" logfile.txt
→ Ищет "error" в файле.
grep -i "error" logfile.txt
→ Ищет без учета регистра.
grep -r "TODO" /project/
→ Рекурсивный поиск по директориям.
grep -n "function" script.py
→ Показывает номер строки вместе с результатами.
grep -v "debug" logfile.txt
→ Показывает всё, кроме строк с "debug".
grep -c "warning" logfile.txt
→ Считает количество совпадений.
grep -w "cat" animals.txt
→ Совпадение только по целым словам.
grep -C 3 "exception" logfile.txt
→ Показывает 3 строки до и после совпадения.
grep "import" *.py
→ Ищет сразу по нескольким файлам.
grep -E "error|warning|critical" logfile
→ Ищет по нескольким шаблонам сразу.
Тот самый продовый пожар в 3 ночи
Приложение упало. Пользователи бесятся. Телефон разрывается.
grep -rni "exception" /var/log/ | grep "2025-12-02"
Это находит все исключения в логах за сегодня. С номерами строк. По всем файлам.
Тысячи строк сужаются до причины падения за секунды.
Почему это важно
Твой IDE не работает на удалённых серверах. Не тянет гигабайтные логи. И точно не помогает в 3 ночи, когда прод лег.
А grep помогает.
Разница между джуном и сеньором?
Умение пользоваться терминалом, когда это реально нужно.
👉 @BackendPortal
Большинство инженерных команд косячат с архитектурой сообщений, потому что не понимают простую вещь:
Стримы хранят правду.
Очереди выполняют работу.
Когда это путают, система начинает кровоточить.
Я видел проекты, где слили миллионы просто потому, что всё пихали в очередь типа
"Ну просто запушим заказ в очередь, а там обработаем!"
"Мы будем стримить абсолютно всё!"
Если событие меняет состояние бизнеса → стрим.
Если сообщение это действие к выполнению → очередь.
Оптимизация слоев Docker-образа сократила время деплоя с 12 минут до 90 секунд.
Изначальный Dockerfile:
Любое изменение кода пересобирало весь образ
Зависимости ставились каждый раз заново
Кэш слоев никак не использовался
Размер образа был 1.2GB
Проблемный фрагмент:
COPY . /app
RUN pip install -r requirements.txt
COPY requirements.txt /app/
RUN pip install -r requirements.txt
COPY . /app
Уменьшаем время выборки из БД с 2–3 секунд до ~100 мс:
SELECT * FROM transactions
WHERE user_id = 40
ORDER BY created_at DESC
LIMIT 20 OFFSET 10000;
SELECT * FROM transactions
WHERE user_id = 40
AND created_at < '2024-05-01 10:00:00'
ORDER BY created_at DESC
LIMIT 20;
WHERE (created_at, id) < ('2024-05-01 10:00:00', 98765)
ORDER BY created_at DESC, id DESC
Оптимизация SQL в бэкенде
Оптимизация SQL обеспечивает эффективную работу запросов в бэкенде, снижает задержки и повышает общую производительность системы.
Плохо оптимизированный SQL приводит к медленному отклику, высокой загрузке процессора и узким местам в приложениях с высокой нагрузкой.
✓ 1. Изучение планов выполнения запросов
Используйте команды EXPLAIN или EXPLAIN ANALYZE, чтобы понять, как база данных выполняет запрос.
→ Помогает выявить полное сканирование таблиц, неэффективные соединения, отсутствующие индексы или ненужную сортировку.
✓ 2. Индексирование для ускорения поиска
Создавайте индексы для столбцов, которые часто используются в запросах (например, поля поиска, внешние ключи).
Используйте составные индексы при фильтрации по нескольким столбцам.
Избегайте избыточного индексирования: каждый индекс замедляет операции вставки, обновления и удаления.
✓ 3. Избегайте использования SELECT *
Выбирайте только необходимые столбцы с помощью конструкции SELECT столбец1, столбец2.
→ Это сокращает объём передаваемых данных и повышает скорость выполнения запроса.
✓ 4. Оптимизация соединений (JOIN)
Используйте подходящие типы соединений (INNER, LEFT, RIGHT) в зависимости от задачи.
Убедитесь, что столбцы, используемые в соединениях, проиндексированы.
Избегайте объединения слишком многих таблиц в одном запросе — при необходимости разбивайте сложную логику.
✓ 5. Эффективное использование условий WHERE
Применяйте фильтрацию как можно раньше, используя избирательные условия.
По возможности используйте индексированные столбцы в фильтрах WHERE.
Избегайте использования функций в WHERE (например, LOWER(name)), так как они препятствуют использованию индексов.
✓ 6. Ограничение количества возвращаемых строк
Используйте LIMIT или OFFSET для пагинации вместо возврата огромных наборов данных.
→ Это повышает производительность фронтенда, которому не требуется вся информация сразу.
✓ 7. Избегание проблемы N+1 запросов
Возникает при получении связанных данных в циклах.
Вместо этого используйте соединения (JOIN) или эффективные пакетные запросы.
✓ 8. Использование кэширования
Кэшируйте часто выполняемые запросы на чтение с помощью Redis или Memcached.
→ Это снижает нагрузку на базу данных и значительно повышает скорость работы.
✓ 9. Нормализация там, где нужно, денормализация — когда это оправдано
Нормализация уменьшает избыточность и повышает согласованность данных.
→ Денормализация ускоряет операции чтения при высокой нагрузке, если производительность — приоритет.
✓ 10. Оптимизация операций вставки и обновления
Используйте пакетные вставки вместо поочерёдной вставки строк.
Избегайте ненужных обновлений: проверяйте, изменились ли значения, прежде чем выполнять обновление.
✓ 11. Разделение больших таблиц
Разделяйте большие таблицы по дате или региону для ускорения запросов.
→ Полезно для логов, аналитики или данных временных рядов.
👉 @BackendPortal
Я предпочитаю формат [error, data], а не { error, data } для результатов асинхронных операций. Почему? Потому что кортеж гарантирует порядок. Ошибку ставим первой, чтобы потребитель не забывал о ней. У объекта порядок ключей не важен, и легко пропустить проверку поля error.
Такие мелкие решения в итоге делают API действительно удобным. Если хочешь поощрять обработку ошибок, ставь их вперед. Дай понять потребителю, что они существуют. Сделай так, чтобы проигнорировать ошибку было сложно. 🍦
И именно так и был разработан until-async: https://github.com/kettanaito/until-async
👉 @BackendPortal
Терминальный клиент для HTTP / GraphQL / gRPC с поддержкой SSH-туннелей, WebSocket, SSE, workflows, профилирования, OpenAPI и диффов ответов.
https://github.com/unkn0wn-root/resterm
👉 @BackendPortal
Сегодня решаю классическую задачу из распределенных систем:
как надежно стримить логи с нескольких реплик в хронологическом порядке?
| sort 🙃watermark = min(latest_timestamp for each stream)
sort and print all buffered logs where timestamp < watermark
AWS открыл бесплатный доступ к SimuLearn до 6 января!
✓ Реальные симуляции, чтобы прокачать навыки по облакам
✓ Без кредитки и без риска внезапных списаний
✓ EC2, NoSQL, архитектура, траффик под нагрузкой и другое
Один из топовых ресурсов:
→ ссылка
👉 @BackendPortal
Пиковый опыт разработки на TypeScript в бэкенде.
Определяешь маршрут, возвращаешь данные, всё полностью типобезопасно.
Типобезопасность тянется до фронтенда через RPC-подобный коннектор.
Документация по API генерируется для всех ответов.
OpenTelemetry заводится меньше чем за 10 строк.
Живём в интересное время.
Код тоже очень хороший, чувак написал его примерно за час.
https://github.com/SaltyAom/elysia-prisma-better-auth-example
👉 @BackendPortal
Еще одна книжка на полку. Пятое издание. Подборка статей, собранных Стоунбрейкером, Питером Бейлисом и Джозефом Хеллерстейном. PDF доступен бесплатно.
redbook.io/pdf/redbook-5th-edition.pdf
👉 @BackendPortal
Удаляйте ChatGPT. Вы не умеете им пользоваться.
Большинство пользователей спамит в ИИ всякую чушь — просят рассказать анекдот, изливают душу и используют как Гугл.
Российский тимлид OpenAI Вадим Петрич рассказывает в «Доктор GPT» как извлекать из нейронок максимум пользы. Это очень интересно:
• ТОП №1 нейросеть, генерирующая видео без цензуры вообще
• Готовые промты на все случаи жизни
• Инсайды и разработки от китов индустрии
Подпишитесь, с Доктором GPT нейронки станут инструментом роста, а не безделушкой:
/channel/+K65EHRh_x_c2OTli
Почему JSON жрет твой CPU
Твой API тупит. Ты думаешь что база медленная, сеть лагает. Но реальная пробка может быть в том формате, на котором всё общается.
JSON это не формат данных. Это текст.
Каждый раз, когда ты отправляешь {"id": 12345}, сервер платит скрытый "налог на парсинг". Даже самые быстрые парсеры вроде simdjson упираются в аппаратные ограничения, которых у бинарных форматов просто нет.
Разложим по технике.
1. Цена на CPU (state-machine против арифметики)
JSON (текст):
Чтобы прочитать число 12345, CPU получает сырые байты. Даже оптимизированный парсер должен пройти через state machine:
- искать структурные символы (: , { }).
- проверять escape-последовательности.
- а потом конвертировать строку в число:
цикл: взять char, вычесть '0', умножить накопленное на 10, прибавить.
Это прыжки в ветках, пропуски кеша, ситуации, где CPU просто ждет.
Protobuf (бинарный):
Отправляет Varint (для маленьких чисел) или фиксированный формат.
fixed32 => просто memcpy. Никакого парсинга.
Varint => читаешь байт, смотришь флаг в старшем бите (MSB), решаешь, идет ли число дальше.
Результат: несколько битовых операций. На нагрузках с большим количеством чисел бинарный формат фундаментально быстрее.
2. Стоимость по сети (энтропия против повторов)
JSON:
[
{"status": "active"},
{"status": "active"}
]
gzip всё решит!
gzip решает сеть, но ест CPU.