15708
Присоединяйтесь к нашему каналу и погрузитесь в мир Backend-разработки Связь: @devmangx РКН: https://clck.ru/3FobxK
Кто-то сделал веб-симулятор System Design.
Называется Paperdraw. Он позволяет перетаскивать компоненты (drag & drop) и в реальном времени смотреть, как они ведут себя при реальных условиях: нагрузке, сбоях, задержках и масштабировании.
100% бесплатно можно попробовать.
👉 @BackendPortal
System Design Talks 23: паттерн Circuit Breaker
Проблема
Во время распродажи Payment Gateway начинает тормозить и отвечает по 30 секунд. Внезапно начинают падать и Order Service, и User Profile Service, хотя напрямую они не связаны.
У Circuit Breaker есть 3 состояния:
- Closed (нормальный режим): запросы проходят как обычно. Брейкер отслеживает ошибки.
- Open (разомкнут): если число ошибок доходит до порога (например, 50% запросов завершаются ошибкой), он “срабатывает”.
- Half-Open: после таймаута брейкер пропускает несколько запросов. Если они снова падают, он опять переходит в состояние Open.
Ответ:
Order Service забивает все свои worker threads, пока ждёт ответа от Payment Service.
Вызов Payment Service нужно обернуть в Circuit Breaker. Как только фиксируем всплеск ошибок, он срабатывает и переходит в состояние Open.
Вместо ожидания Order Service сразу возвращает пользователю ответ вроде: «Платежи временно недоступны».
👉 @BackendPortal
Распределённые системы (или даже запутанные микросервисные архитектуры) сложно дебажить, и, если честно, почти всегда в процессе узнаёшь что-то новое. Классические примеры:
- zombie worker, который обрабатывает задачу дважды
- split-brain во время выбора лидера
- рассинхронизация часов (clock skew), приводящая к «нарушениям причинности»
- каскадная неправильная настройка таймаутов (cascading timeout misconfiguration) и многое другое
Чтобы эффективно разбирать такие проблемы, на мой взгляд, нужно одновременно держать в голове и использовать две ментальные модели, постоянно переключаясь между двумя разными перспективами — глобальным и локальным представлением.
Глобальное представление показывает общую архитектуру — как сервисы взаимодействуют друг с другом, как выглядит поток данных и какие гарантии должна обеспечивать система. Это карта. Она показывает, как всё должно быть.
Локальное представление — это то, с чем ты реально работаешь во время инцидента. Ты смотришь на состояние конкретной ноды, её очередь сообщений, логику ретраев и её часы. Ты задаёшься вопросом: что этот компонент сейчас считает истиной?
Интересно то, что эти два представления не всегда совпадают.
Сервис может считать себя здоровым, в то время как вся система работает лишь частично. Сетевое разделение может привести к тому, что две ноды одновременно считают себя лидером. Консьюмер очереди может обрабатывать сообщения в корректном локальном порядке, который при этом нарушает важные для тебя глобальные гарантии обработки.
Именно поэтому про распределённые системы сложно рассуждать. Баги почти никогда не находятся внутри одного компонента. Они живут в разрыве между компонентами :)
Поэтому, если ты работаешь с распределёнными системами, вырабатывай привычку осознанно переключаться между этими представлениями. Когда что-то ломается, сначала задай вопрос: «как выглядит глобальное состояние?», а затем сразу — «как каждая нода представляет себе это глобальное состояние?»
Несоответствие между этими двумя ответами почти всегда и есть место, где скрыта проблема.
Надеюсь, это поможет.
👉 @BackendPortal
Высокопроизводительная lock-free реализация биржевого order book на Rust.
github.com/joaquinbejar/OrderBook-rs
👉 @BackendPortal
Парень реализовал LogFlow — пайплайн для агрегации логов и observability на Go.
Kafka → Go → Elasticsearch → React.
Mock-сервисы генерируют структурированные логи, отправляют их в Kafka, а Go-процессор потребляет их и выполняет bulk-индексацию в Elasticsearch.
React-дэшборд поддерживает стриминг логов в реальном времени через WebSocket и исторический поиск с cursor-based бесконечной пагинацией.
README и фронтенд сгенерированы с помощью AI.
👉 @BackendPortal
Вайбкодеры, перестаньте случайно коммитить свои секретные файлы в Git
Существует 2 файла игнорирования в Git, которые можно использовать:
1. Local: игнор для конкретного проекта
2. Global: игнор для всех ваших проектов
Рекомендуется использовать оба. Локальная конфигурация работает по умолчанию и включена в большинство фреймворков.
Для глобального gitignore можно задать путь к этому файлу в глобальной конфигурации Git с помощью CLI-команды:
git config --global core.excludesfile ~/.gitignore_global
~/.gitignore_global
Если ты бэкенд-разработчик и хочешь разобраться в базах данных и распределённых системах, список литературы и лекции курса MIT по распределённым системам — отличная отправная точка.
Все материалы здесь:
https://pdos.csail.mit.edu/6.824/schedule.html
👉 @BackendPortal
Google запускал миллионы контейнеров задолго до появления Docker.
До Docker Linux cgroups были своего рода скрытой суперсилой, о которой почти никто не знал.
Google активно использовал cgroups в течение многих лет для управления своей масштабной инфраструктурой, ещё до того как «контейнеризация» стала модным словом.
Cgroups — это фича ядра Linux, появившаяся в 2007 году, которая позволяет изолировать процессы и управлять ресурсами.
Но о ней почти никто не знал.
Проблема? Cgroups были крайне сложны и требовали глубоких знаний Linux для использования.
Затем в 2013 появился Docker и всё изменил.
Docker не изобрёл контейнеры или cgroups.
Он сделал гораздо более важную вещь — обернул существующие технологии Linux в простой и удобный интерфейс, которым может пользоваться любой разработчик.
Внезапно то, что раньше требовало часов настройки cgroups, стало выполняться одной командой docker run.
Docker демократизировал контейнерные технологии.
Он взял инфраструктурные возможности уровня Google и сделал их доступными каждому разработчику.
Иногда самые значимые инновации — это не создание чего-то нового, а упрощение доступа к уже существующим мощным технологиям.
👉 @BackendPortal
API требуют ограничения скорости (rate limiting), чтобы один всплеск трафика не перегрузил весь сервис.
В этом гайде yongdev показывает, как реализовать rate limiting по алгоритму token bucket в FastAPI, построив его с нуля.
По ходу вы разберётесь с rate limit заголовками, обработкой 429 (Too Many Requests) и тем, как этот паттерн вписывается в реальную архитектуру API.
👉 @BackendPortal
Существует множество способов выполнить один и тот же запрос в Postgres.
- Делать поиск через последовательное сканирование (sequential scan) или по индексу?
- Какие индексы использовать?
- В каком порядке лучше джойнить таблицы?
- Какой алгоритм сортировки выбрать?
Все эти решения принимает query planner. Его задача — принять запрос, определить оптимальный план выполнения, а затем передать его в execution engine.
Postgres собирает статистику по каждой таблице (размер, оценка кардинальности колонок и т.д.), и эти данные используются планировщиком, помогая ему принимать более точные решения.
Однако здесь есть риск: по мере обновления статистики планировщик может изменить план выполнения для уже существующих запросов. Обычно он принимает правильные решения, но иногда может выбрать новый план, который ухудшит производительность.
В таких случаях можно:
- настраивать параметры, например enable_seqscan=off
- вручную обновлять статистику
- или использовать расширения вроде pg_hint_plan, чтобы подсказать планировщику более подходящий вариант выполнения
👉 @BackendPortal
Контейнеры против виртуальных машин
1. Использование ресурсов:
Контейнеры используют ядро хостовой операционной системы, что делает их более легкими и быстрыми по сравнению с виртуальными машинами. Виртуальные машины имеют полноценную операционную систему и гипервизор, что делает их более ресурсоемкими.
2. Портабельность:
Контейнеры разработаны с учетом портируемости и могут работать на любой системе с совместимой хостовой операционной системой. Виртуальные машины менее портируемы, так как для их работы требуется совместимый гипервизор.
3. Безопасность:
Виртуальные машины обеспечивают более высокий уровень безопасности, поскольку каждая виртуальная машина имеет свою собственную операционную систему и может быть изолирована от хоста и других виртуальных машин. Контейнеры обеспечивают меньшее изолирование, так как они используют ядро хостовой операционной системы.
👉 @BackendPortal
Яндекс открыл прием заявок в Школу бэкенд-разработки
Зовем начинающих специалистов, желающих узнать, как писать код для высоконагруженных веб‑сервисов. Программа разделена на 2 трека:
В Java-треке изучим инструменты разработки веб-приложений платформы Spring. Ещё в программе: многопоточность, базы данных и создание распределенных систем.
В С++-треке освоим управление памятью, оптимизацию производительности и современное использование C++ в промышленной разработке.
Для поступления нужно базово понимать один из языков — Python, Java или C++, уметь писать читаемый код и понимать основы алгоритмов и структур данных.
Подать заявку можно здесь.
MVC-архитектура (Model–View–Controller)
По мере роста приложений управлять кодом становится всё сложнее. Новички часто пишут всё в одном месте — бизнес-логику, пользовательский интерфейс и работу с данными. Для небольших проектов это ещё работает, но очень быстро такой код становится трудно поддерживать, отлаживать и масштабировать.
MVC-архитектура решает эту проблему, вводя чёткое разделение ответственности (separation of concerns).
Что такое MVC?
MVC (Model–View–Controller) — это шаблон проектирования, который делит приложение на три основных компонента, каждый из которых отвечает за свою часть логики. Такое разделение делает код более организованным, читаемым и поддерживаемым.
MVC — это способ структурировать код.
Он делит приложение на 3 части:
- Model = данные + логика
- View = то, что видит пользователь
- Controller = обрабатывает ввод и связывает Model и View
Можно представить это так:
Пользователь что-то нажимает → Controller обрабатывает
Controller запрашивает данные у Model
Model обрабатывает и возвращает результат
Controller передаёт результат во View
View отображает его пользователю
Чисто. Структурировано. Предсказуемо.
Что делает каждая часть?
- Model — работает с данными
Взаимодействует с базой данных и содержит бизнес-логику
- View — отвечает за UI
Только отображает данные, без логики
- Controller — промежуточный слой
Связывает Model и View
Почему это важно?
Без MVC → хаотичный код
С MVC → структурированный код
Преимущества:
- Простая отладка
- Лёгкие изменения
- Лучшая масштабируемость
Пример
В системе логина:
- Model проверяет учётные данные пользователя в базе
- View отображает форму входа и сообщения (успех/ошибка)
- Controller принимает ввод пользователя, валидирует его через Model и решает, какой View отобразить
👉 @BackendPortal
TF-IDF — один из самых распространённых способов оценки релевантности документов в поисковых системах. Многие запоминают формулу, но интуиция, почему это работает, на самом деле довольно простая…
Я читал об этом статью ещё в 2020 году, и она до сих пор остаётся актуальной и базовой — если кто-то хочет разобраться глубже :) А вот кратко суть:
IDF — это Inverse Document Frequency (обратная частота документа). Основная идея проста: слово, которое встречается почти в каждом документе, практически ничего не говорит о том, почему конкретный документ релевантен.
Такие слова, как “a”, “and”, “the”, встречаются везде. Они почти не несут сигнала. IDF автоматически «штрафует» их, присваивая им меньший вес.
Интуитивно IDF терма — это логарифм обратной вероятности того, что случайно выбранный документ содержит этот терм. (Если это звучит тяжеловато — лучше посмотреть полное объяснение, там это разобрано подробно)
Например, если терм встречается в 10 из 1000 документов, его IDF:
log(1000 / 10) = log(100)
Чем реже терм, тем выше его IDF — и тем полезнее он для различения документов.
Есть ещё одно интересное следствие, если смотреть на это с вероятностной точки зрения.
Если предположить, что термы встречаются независимо, то IDF для двух термов вместе равен сумме их индивидуальных IDF.
Именно поэтому поисковые системы могут оценивать многословный запрос, просто суммируя веса отдельных термов. Документ, содержащий несколько редких и значимых термов, естественным образом получает более высокий скор релевантности.
Это очень простая идея, но при этом одна из самых фундаментальных в информационном поиске.
👉 @BackendPortal
Кир Шатров, Principal Engineer в Shopify, пишет для The Consensus о технике отслеживания стоимости (MySQL) базы данных для каждого API-вызова.
Пейволл больше не действует, приятного чтения!
https://theconsensus.dev/p/2026/03/20/every-query-gets-a-receipt.html
👉 @BackendPortal
Microsoft выложила репозиторий для изучения Rust
7 курсов разного уровня
✓ Подойдёт, если вы переходите с TypeScript, Python, C++ или Go
✓ Асинхронность, продвинутые паттерны и best practices
✓ Всё объединено в понятный и хорошо структурированный обучающий путь
→ http://github.com/microsoft/RustTraining
👉 @BackendPortal
В распределённых системах нет «общих часов», поэтому двум узлам крайне сложно договориться о том, что такое «сейчас». Если честно, именно это и делает распределённые системы такими интересными.
Здесь как раз помогает отношение «happened-before» — оно вносит порядок в этот хаос. Давайте чуть углубимся...
Если событие A произошло раньше события B, это значит, что A могло причинно повлиять на B. Два события без такой связи считаются конкурентными, и система рассматривает их именно так. Вот конкретный пример — классические Alice и Bob, редактирующие общий документ.
1. Alice читает документ (событие A), вносит изменение (событие B) и сохраняет его.
2. Bob тоже читает документ (событие C) до того, как до него доходит сохранение от Alice.
3. Затем Bob сохраняет свою версию (событие D).
Теперь, без отслеживания отношения happened-before, система не понимает, что чтение Bob (C) не включало запись Alice (B). В итоге изменения Alice будут тихо перезаписаны.
С отслеживанием причинности система знает, что событие B произошло раньше события D, значит запись Bob основана на устаревших данных и должна была учитывать B. Система может обнаружить конфликт и запросить его разрешение вместо того, чтобы молча терять данные.
Кстати, именно так системы вроде DynamoDB и Riak обрабатывают конкурентные записи без потери данных. Есть несколько практических способов это реализовать:
1. Lamport clocks
Каждый узел увеличивает счётчик при каждом событии и обновляет его при получении сообщений. Достаточно простая реализация.
2. Vector clocks
Каждый узел ведёт счётчик для каждого узла. Это позволяет точно фиксировать причинные зависимости и обнаруживать конкурентные записи. В Git похожий принцип используется при определении конфликтов слияния (в некотором смысле).
3. Hybrid Logical Clocks (HLC)
Комбинируют физическое время и логические счётчики. Используются, например, в CockroachDB. Позволяют учитывать причинность, оставаясь близко к реальному времени, что даёт возможность эффективно выполнять time-based запросы и поддерживать консистентный порядок без полной зависимости от физических часов.
Выбор подхода зависит от требований к консистентности и допустимого оверхеда. Vector clocks растут вместе с количеством узлов, а HLC часто являются хорошим компромиссом для продакшн-систем.
Важно понимать: причинность не решает все проблемы консистентности, но она чётко определяет, что нельзя игнорировать — если A произошло раньше B, система обязана соблюдать этот порядок. Всё остальное — предмет комприссов.
Это глубокая тема сама по себе, но надеюсь, этого достаточно, чтобы вы захотели копнуть дальше 🙂
👉 @BackendPortal
Топ 75 вопросов по System Design (с документацией)
Задают ли вопросы по System Design на собеседованиях для джунов?
Хватит тратить время на рандом подготовку — вот всё, что тебе нужно
👉 @BackendPortal
Скажу так, и это серьёзно: построить надёжную систему — не сложно.
Сложно — иметь терпение замедлиться.
Если система большая, не спеши с планированием. Потрать столько времени, сколько нужно — хоть месяцы.
Начни с HLD (high-level design) — общей картины, как всё устроено и как компоненты связаны между собой. Затем декомпозируй это в LLD (low-level design), где ты уже определяешь, как каждая часть реально работает и взаимодействует.
После этого сядь и нормально проработай edge cases. Именно там чаще всего и ломаются системы, а не в очевидных сценариях.
К моменту, когда ты приступаешь к реализации, ты уже закрыл большую часть сложных вопросов. Само внедрение проходит гораздо проще.
Многие испытывают сложности не потому, что не умеют строить системы, а потому что начинают слишком рано, не продумав всё как следует.
На этом всё. Всем добра. Удачного дня.
👉 @BackendPortal
Мы все знаем теорему CAP, но есть ещё одна тройка, которая конкурирует в стриминге и системах реального времени и получает гораздо меньше внимания. Эта триада:
- consistency (все видят одно и то же значение)
- availability (система всегда отвечает на запросы)
- freshness (насколько данные актуальны)
Эти три цели конфликтуют между собой разными способами.
Если вы приоритизируете consistency и freshness, вам нужна жёсткая координация между узлами. Такая координация добавляет задержки и может приводить к остановке системы, если один из узлов медленный или недоступен, что ухудшает availability.
Если вы приоритизируете availability и freshness, вы позволяете данным быстро проходить и разрешаете всем узлам принимать записи. Но без координации узлы могут временно расходиться, нарушая гарантии consistency. Пример — поведение Kafka при высокой нагрузке с acks=1 (с оговорками, есть нюансы).
Если вы приоритизируете consistency и availability, обычно вводится буферизация или батчинг, чтобы обеспечить координацию без блокировок. Эта буферизация снижает freshness и увеличивает end-to-end задержку с секунд до минут.
Популярные real-time системы, такие как Apache Flink, Kafka Streams и Spark Streaming, делают разные компромиссы в этом треугольнике.
Как всегда, бесплатных компромиссов не бывает.
Поэтому крайне важно понимать, какие два свойства вы оптимизируете, и явно учитывать это во всех архитектурных решениях: replication factor, стратегия коммитов, подход к windowing, обработка опаздывающих данных и многое другое.
Выберите свои два. Спроектируйте систему с учётом того, чем вы жертвуете.
👉 @BackendPortal
Когда твое приложение начинает получать тысячи пользователей, одного сервера уже недостаточно.
Можно масштабироваться двумя способами:
1. вертикально: добавить серверу больше CPU или RAM (это дорого и имеет предел).
2. горизонтально: добавить больше серверов.
Второй вариант дает масштабируемость, но приносит новую проблему:
на какой сервер должен идти каждый запрос?
Здесь появляется балансировщик нагрузки (Load Balancer):
компонент, который распределяет трафик между серверами, используя разные алгоритмы.
Если сервер "A" падает, балансировщик это обнаруживает и перестает отправлять на него трафик.
Теперь каждый сервер запускает копию твоего приложения. Поскольку трафик распределен, ты можешь обслуживать больше пользователей, не перегружая один сервер.
Но теперь узкое место смещается:
если все серверы обращаются к одной и той же базе данных, она становится перегруженной.
Решение: добавить реплики для чтения и кэш, чтобы снизить нагрузку.
Но если ты добавляешь реплики, как гарантировать, что данные всегда синхронизированы?
И так эволюционирует архитектура: решая одну проблему за раз.
Проектирование систем — это именно про это:
понимание, где находятся узкие места, и что нужно, чтобы твое приложение продолжало масштабироваться.
👉 @BackendPortal
ihj — это терминально-нативный Jira-клиент, написанный на Rust/Go, с поддержкой TUI с нечетким поиском и headless CLI-команд.
Не нужно открывать браузер — можно прямо из терминала просматривать, управлять и искать Jira issues.
Архитектура provider-agnostic, с возможностью расширения на другие бэкенды в будущем: GitHub Issues, Linear, Trello и т.д.
https://github.com/mikecsmith/ihj
👉 @BackendPortal
System Design
CDN-кэширование: одно изменение в DNS, которое ускорило наш сайт в 7 раз.
С 3 секунд → до 0.4 секунды.
Тот же код. Тот же сервер.
Пользователям в Мумбаи, Дели, Бангалоре стало казаться, что всё работает прямо у них на устройстве.
POV: вы наконец перестали заставлять пользователей из Индии ждать сервер в Вирджинии.
1/ Жёсткая реальность
Ваш origin-сервер спокойно стоит в Вирджинии, США.
Пользователь из UP/Бихара открывает сайт → расстояние 12 000+ км.
Даже скорость света не спасает.
RTT (round trip latency): 200–400 мс ещё до того, как сервер вообще начнёт отвечать.
Результат? Пользователь уже закрыл вкладку и ушёл к конкуренту.
Latency = тихий убийца.
2/ CDN = ваша армия edge-серверов
Вместо того чтобы каждый пользователь ходил на ваш одинокий сервер в США,
CDN размещает копии ваших статических файлов (изображения, CSS, JS) на 200+ edge-серверах по всему миру.
Пользователь из Мумбаи? → попадает на CDN-ноду в Мумбаи (20–50 км).
Из Дели? → нода в Дели.
Из Бангалора? → нода в Бангалоре.
Проблема расстояния решена.
3/ Как это работает (очень просто)
Первый запрос (cache miss):
→ пользователь попадает на ближайший edge CDN
→ кэша нет → CDN подтягивает данные с origin
→ сохраняет в кэш → отдаёт пользователю
Следующие 1000 запросов (cache hit):
→ тот же edge отдаёт данные мгновенно из локального кэша
→ origin-сервер спокойно «отдыхает»
Нагрузка на origin резко падает.
4/ Реальный пример из e-commerce (из практики)
Изображения товаров = 2 МБ каждое.
Без CDN:
пользователь из Токио/Индии ждёт ~1 секунду на каждую картинку.
С CDN:
та же картинка загружается ~0.1 секунды с ближайшего edge.
Страница с 10 изображениями: 10 с → 1 с
Конверсия выросла.
Отказы снизились.
Скорость = деньги.
5/ Настройка за 5 минут (без преувеличений)
1. Зайти в Cloudflare (даже бесплатный тариф подойдёт)
2. Добавить домен
3. Поменять NS / DNS-записи
4. Включить кэширование
5. Готово
Теперь весь ваш статический контент раздаётся с 300+ локаций автоматически.
Без изменений в коде.
Огромный прирост скорости.
👉 @BackendPortal
Как начать зарабатывать в IT в 2026 году даже без опыта и образования
Самое странное сейчас это пытаться вкатиться в IT по классике, когда опытные программисты давно кодят с нейронками даже в больших проектах.
Поэтому в 2026 выигрывает тот, кто быстро делает рабочие решения без долгих лет обучения и максимально сокращает путь с нуля до первого реального проекта в IT.
Андрей Ивашев запускает бесплатный 3-дневный интенсив:
«Вайбкодинг: с нуля до первого IT-продукта»
📅 7-9 апреля в 19:00 МСК
Для тех хочет начать программировать с нейронками, создать свой первый IT-продукт и заработать на этом первые деньги даже без опыта и образования.
Программа 🔥
7 апреля
Почему сегодня вход в IT стал сложнее и как вайбкодинг меняет правила игры
8 апреля
3 способа заработать на вайбкодинге в 2026 и где брать первого клиента, чтобы сделать проект за реальные деньги
9 апреля
Эра агентов или программирование на автопилоте
🎁 Бонус за регистрацию:
«Библиотека промптов для заработка на вайбкодинге», которые помогут упаковать портфолио и общаться с клиентами так, чтобы покупали.
50 бесплатных нейросетей, чтобы вы могли кодить без остановки + секретные бонусы
Бесплатных мест для наших подписчиков всего 100.
Зарегистрироваться бесплатно
Зарегистрироваться бесплатно
Зарегистрироваться бесплатно
Тыкни на 🔥, если идёшь.
System Design
Инвалидация кэша — проблема, которая сломала больше продакшн-систем, чем почти любой другой баг.
В компьютерных науках есть всего две по-настоящему сложные задачи.
Это — первая.
Сегодня я покажу, почему это действительно сложно и какие практические стратегии реально работают.
1/ Основная проблема
Вы кэшируете профиль пользователя.
Пользователь обновляет свой email.
В базе данных уже новый email, но в кэше всё ещё старый.
Пользователь видит устаревшие данные и начинает путаться.
Инвалидация кэша — это по сути поддержание кэша и базы данных в идеально синхронизированном состоянии.
Ошиблись — и вы отдаёте неактуальную информацию.
2/ Почему это на удивление сложно
База обновилась в 10:00:00.000.
Другой сервер проверяет кэш в 10:00:00.001.
Этого микроскопического зазора достаточно, чтобы проскочили устаревшие данные.
В распределённых системах тайминги никогда не идеальны.
Нельзя просто очистить кэш и надеяться на лучшее.
Нужна чёткая стратегия.
3/ Стратегия 1: TTL (Time To Live)
Самый простой подход.
При сохранении данных в кэш задаётся время жизни.
Пример в Redis:
redis.setex("user:123", 300, user_data) # истекает через 5 минутdef update_user(id, data):
db.update(id, data)
redis.set("user:" + id, data)
def update_user(id, data):
db.update(id, data)
redis.delete("user:" + id)
def get_user(id):
cached = redis.get("user:" + id)
if cached:
return json.loads(cached)
user = db.query("SELECT * FROM users WHERE id = %s", id)
redis.setex("user:" + id, 300, json.dumps(user))
return user
Использование rate limiting
~ Ограничение скорости API применяется для того, чтобы предотвратить от одного пользователя слишком много запросов, которые могут замедлить работу системы.
~ Ограничение скорости веб-сервера используется для защиты сайта от слишком большого числа посетителей или атак. (например, сайт разрешает только 10 или 5 запросов в секунду с одного IP. Если кто-то пытается отправить больше запросов, его блокируют). Это помогает защитить систему от атак типа DoS.
~ Ограничение скорости базы данных используется для предотвращения слишком большого числа запросов к базе данных, что может привести к ее замедлению или поломке. (например, сайт электронной коммерции разрешает пользователю делать только 10 запросов к базе данных за 10 минут), чтобы избежать перегрузки системы и сохранить скорость работы приложения.
~ Ограничение скорости входа применяется для предотвращения атак, когда хакеры пытаются угадать пароли, делая много попыток. (разрешено только 2-3 попытки входа в минуту на пользователя).
👉 @BackendPortal
Маршрутизация трафика в Kubernetes:
→ ClusterIP: Тип сервиса по умолчанию, который предоставляет стабильный внутренний IP для взаимодействия внутри кластера.
→ NodePort: Открывает сервис на определённом порту на всех нодах (Nodes), позволяя получать к нему доступ извне через IP ноды.
→ LoadBalancer: Стандартный способ открыть сервис в интернет — создаётся внешний балансировщик нагрузки от облачного провайдера.
→ Ingress: Умный уровень маршрутизации, который управляет внешним HTTP/HTTPS-трафиком и направляет его к нескольким сервисам через одну точку входа.
👉 @BackendPortal
Асинхронные системы масштабируют вашу систему… и ваши проблемы.
Большинство разработчиков осознают это только после того, как нарушается консистентность, и при этом на первый взгляд всё выглядит нормально.
Асинхронность масштабирует вашу систему.
Она также нарушает порядок.
И вот откуда берутся большинство багов.
Вот статья о том:
- почему это происходит
- как группировка решает проблему
- и где она не работает
Прочитайте здесь
👉 @BackendPortal
На Stepik вышел первый курс по: Claude Code — вайбкодинг с нуля
Изучаете всё шаг за шагом: CLAUDE.md → rules → commands → sub-agent → Skills → hooks:
🔴Оформите правила проекта через CLAUDE.md, подключение файлов через @ и разнесение логики в .claude/rules, чтобы не раздуло инструкцию.
🔴Сделаете свои slash-команды с frontmatter (description/allowed-tools/model) и аргументами через $ARGUMENTS и $1/$2/$3 для буста воркфлоу.
🔴Освоите саб-агентов: когда их запускать, как писать определения и как делегировать им расследования и проверки без засора основного контекста.
🔴Поднимете Hooks под реальный воркфлоу: /hooks, sh-скрипты, SessionStart/Stop/PreToolUse/PostToolUse, exit codes, matchers и env-переменные.
🔴Настроите Skills (SKILL.md + references), свяжете их с саб-агентами через skills-поле и подключите MCP, Web и headless (-p) для продвинутых случаев
Скидка 25%, действует 48 часов
⬇️ Пройти курс на Stepik
А что если бы можно было запускать Postgres как один файл и при этом использовать всё лучшее из SQLite?
Разработчик представил pg-micro — экспериментальный проект, который пытается это реализовать.
pg-micro отличается от других подходов тем, что он полностью локальный и ориентирован на производительность: нет ограничений по конкурентности и отсутствует трансляция SQL-запросов.
Как это работает: используется нативный парсер Postgres для разбора запроса, после чего он компилируется в AST от Turso. Затем этот AST компилируется в байткод, и дальше всё исполняется нативно — так же, как в SQLite. Благодаря этому решение можно запускать практически в любом окружении.
Исторически между Postgres и SQLite есть функциональный разрыв. Но Turso активно его сокращает: такие вещи, как MVCC и строгая развитая система типов, уже реализованы. Также есть PR’ы для lateral join’ов и других возможностей, что в теории позволяет свести разрыв почти к нулю.
Что это даёт на практике?
Можно представить, например, примитив наподобие Durable Objects от Cloudflare, но с интерфейсом Postgres.
Или использовать паттерн локальных баз данных для агентов, как в SQLite — полностью эфемерных и бесплатных, но с интерфейсом Postgres.
Или выполнять удалённый Postgres на платформах вроде Vercel, но с плотностью, которую даёт Turso Cloud.
Пока что многое может не работать — проект экспериментальный. Но он развивается как open source, поэтому PR’ы приветствуются.
Старт: npx pg-micro
👉 @BackendPortal