diff --git a/README.md b/README.md
index 316a8e4..cd9c944 100644
--- a/README.md
+++ b/README.md
@@ -1446,136 +1446,172 @@ futriix:~> cluster health
## Backpressure
-Для равномерной загрузки каждого узла кластера, в субд futriix применяется механизм **"backpressure"**.
-**Backpressure (Обратное давление)** — это механизм управления потоками данных, предотвращающий переполнение узла кластера, когда он не успевает обрабатывать поступающие события.
-В нашем проекте данный механизм реализован для защиты системы от резких пиковых нагрузок: если буфер входящих сообщений достигает заданного порога, источник данных автоматически замедляется или приостанавливается до тех пор, пока потребитель не освободит ресурсы. Это гарантирует стабильность работы, отсутствие потерь данных и отказ от бесконечного накопления задач в очереди.
+Назначение
-**Математическая формула вероятностного отклонения в Backpressure**
+Для защищиты субд futriix от перегрузки при всплесках входящей нагрузки, в ней реализован механизм **Backpressure (клапан обратного давления)**, реализующий алгоритм **"Buffer Ring (кольцевой буфер обратного давления)."**
+Он реализует адаптивное откладывание запросов вместо их немедленного отклонения: когда система близка к насыщению, запросы не отбрасываются, а ненадолго помещаются в кольцевой буфер, чтобы дать ядру время обработать уже принятые операции.
-В системе Backpressure используется адаптивная вероятностная модель для отклонения запросов при перегрузке, которое рассчитывается по следующей формуле:
+Такой подход отличается от классического «reject при перегрузке» тем, что сглаживает пики, а не режет их, и сохраняет больше полезной работы при кратковременных всплесках.
+
+**Идея**
+
+**Кольцевой буфер (Buffer Ring)** — это фиксированное кольцо слотов для ожидающих запросов. В отличие от очереди (FIFO), кольцо:
+
+ * Имеет постоянный размер N (не растёт под нагрузкой);
+ * Переиспользует слоты по кругу через индексы head и tail;
+ * При переполнении не расширяется, а применяет политику вытеснения;
+ * Поддерживает O(1) на вставку и извлечение — никаких аллокаций в горячем пути.
+
+Каждый слот хранит «билет» запроса: метаданные (тип, deadline, приоритет) и функцию продолжения resume(), которая будет вызвана, когда наступит очередь.
```sh
-P_reject = f(level) × g(load) × h(time)
-
-Где:
-
- * P_reject — итоговая вероятность отклонения запроса (0.0 - 1.0)
- * f(level) — коэффициент на основе уровня перегрузки
- * g(load) — коэффициент на основе текущей нагрузки
- * h(time) — коэффициент на основе времени (для защиты от "thundering herd")
+ tail (writer) head (reader)
+ ↓ ↓
+ ┌───┬───┬───┬───┬───┬───┬───┬───┐
+ │ 7 │ 8 │ 9 │ │ │ 4 │ 5 │ 6 │
+ └───┴───┴───┴───┴───┴───┴───┴───┘
+ ↑ занято ↑ свободно ↑ занято
```
-**Компоненты формулы**
+**Алгоритм**
-**Коэффициент уровня перегрузки f(level)**
+1. Классификация нагрузки
+
+На каждом цикле проверки (например, раз в check_interval_ms) менеджер снимает метрики: загрузку CPU, памяти, длину очереди, число соединений. По порогам из конфигурации определяется уровень:
+
+| Уровень | Условие | Действие |
+|---------|---------|----------|
+| `Low` | CPU < `cpu_threshold` и очередь < `queue_size_threshold` | запрос проходит сразу |
+| `Medium` | один из порогов превышен | запрос помещается в кольцо на короткую задержку `low_delay_ms` |
+| `High` | CPU > `cpu_threshold` и очередь > `queue_size_threshold` | запрос помещается в кольцо; при переполнении применяется `high_reject_prob` |
+| `Critical` | система не успевает дренировать кольцо | запросы отклоняются с `503 Service Unavailable` |
+
+
+**2. Постановка в кольцо (enqueue)**
```sh
-f(level) = {
- 0.00, если level = None
- 0.00, если level = Low (только задержка)
- 0.30, если level = Medium
- 0.70, если level = High
- 0.90, если level = Critical
-}
-```
-
+func (r *Ring) Enqueue(req *Request) EnqueueResult:
+ if r.size == r.capacity:
+ // Переполнение — выбираем политику вытеснения
+ if req.Priority > r.slots[r.tail].Priority:
+ evicted = r.slots[r.tail] // вытесняем менее приоритетный
+ r.slots[r.tail] = req
+ r.tail = (r.tail + 1) mod r.capacity
+ return Enqueued(evicted)
+ else:
+ return Rejected(reason="ring_full")
-**Коэффициент нагрузки g(load)**
+ r.slots[r.tail] = req
+ r.tail = (r.tail + 1) mod r.capacity
+ r.size++
+ return Enqueued(nil)
+```
+
+**3. Дренирование (dequeue)**
+
+Отдельная горутина-дренажёр (drainer) периодически забирает запросы из головы кольца и передаёт их на выполнение:
```sh
-g(load) = (cpu_usage + memory_usage + queue_factor + connection_factor) / 4
-
-где:
-cpu_usage = current_cpu / cpu_threshold
-memory_usage = current_memory / memory_threshold
-queue_factor = min(queue_size / queue_threshold, 1.0)
-connection_factor = min(connections / connection_threshold, 1.0)
+func (r *Ring) drainLoop():
+ ticker = NewTicker(r.drain_interval)
+ for range ticker:
+ for r.size > 0 and systemHasCapacity():
+ req = r.slots[r.head]
+ r.slots[r.head] = nil
+ r.head = (r.head + 1) mod r.capacity
+ r.size--
+ go req.resume() // выполняем вне критической секции
```
-
-**Коэффициент времени h(time) (экспоненциальное сглаживание)**
+
+Почему отдельная горутина: если бы запросы «дренировались» из того же потока, что их принимает, кольцо не сглаживало бы нагрузку, а просто перемещало её в вызывающий код. Дренажёр работает асинхронно и может приостанавливаться, если systemHasCapacity() возвращает `false`.
+
+**4. Управление задержкой**
+
+Каждый запрос в кольце имеет deadline — абсолютное время, к которому он должен быть либо выполнен, либо отклонён:
```sh
-h(time) = 1 - e^(-λ × Δt)
-
-где:
-λ = 0.1 (константа скорости затухания)
-Δt = время с последнего отклонения в секундах
+req.deadline = now + config.LowDelayMs
```
-
+Дренажёр перед `resume()` проверяет: если `now > req.deadline` — запрос отклоняется с `504 Gateway Timeout`, а не выполняется «просроченным». Это гарантирует, что клиент получит ответ в предсказуемое время, даже если система перегружена.
-**Итоговая формула вероятности отклонения**
+**5. Адаптивная настройка**
+
+Пороги и задержки пересчитываются по наблюдаемым метрикам:
+
+* queue_size_threshold — растёт, если кольцо регулярно переполняется, и падает, если оно почти всегда пусто.
+* low_delay_ms — увеличивается при росте времени дренирования.
+* high_reject_prob — рассчитывается как доля запросов, которые пришлось вытеснить на прошлом цикле.
+
+Адаптация выполняется плавно(экспоненциальное сглаживание), чтобы избежать осцилляций.
+
+**Псевдокод жизненного цикла запроса**
```sh
-P_reject = f(level) × g(load) × (1 - e^(-0.1 × Δt))
+Client → API Handler
+ │
+ ├─► Backpressure.Check()
+ │ │
+ │ ├─ Low → выполнить немедленно
+ │ ├─ Medium → Enqueue(req) → resume() через low_delay_ms
+ │ ├─ High → Enqueue(req) → resume() при появлении capacity
+ │ └─ Critical → Reject(503)
+ │
+ └─► Ring.Enqueue(req)
+ │
+ ├─ свободный слот → положить, вернуть Enqueued
+ ├─ переполнение → вытеснить менее приоритетный
+ └─ невозможно → Reject(503)
+
+Drainer Loop
+ │
+ ├─ systemHasCapacity() == true → req = Ring.Dequeue(); go req.resume()
+ ├─ systemHasCapacity() == false → sleep(drain_interval)
+ └─ req.deadline < now → Reject(504)
```
-**Формула задержки (для уровня Low)**
+**Параметры конфигурации**
-```sh
-D = D_base × (1 + α × load_factor)
+| Параметр | Значение по умолчанию | Назначение |
+|----------|----------------------|------------|
+| `enabled` | `false` | Включить механизм |
+| `cpu_threshold` | `0.8` | Порог CPU (0–1), выше которого запросы буферизуются |
+| `memory_threshold` | `0.85` | Порог памяти (0–1) |
+| `queue_size_threshold` | `10000` | Порог длины очереди |
+| `connection_threshold` | `5000` | Порог числа соединений |
+| `check_interval_ms` | `1000` | Интервал проверки нагрузки |
+| `low_delay_ms` | `100` | Задержка для уровня `Medium` |
+| `medium_reject_prob` | `0` | Вероятность отказа при `Medium` (%) |
+| `high_reject_prob` | `50` | Вероятность отказа при `High` (%) |
+| `ring_capacity` | `4 × queue_size_threshold` | Размер кольца |
-где:
-D_base = 100ms (базовая задержка)
-α = 2.0 (коэффициент усиления)
-load_factor = (cpu_usage + memory_usage) / 2
-```
-
-**Графическое представление**
+**Гарантии**
-```sh
-Вероятность отклонения P_reject
- |
-1.0 | * * * Critical (90%)
- | *
-0.9 | * High (70%)
- | *
-0.7 | * Medium (30%)
- | *
-0.5 | *
- | *
-0.3 | * Low (0% - только задержка)
- | *
-0.1 |*
- |_____________________________ Нагрузка
- 0 0.2 0.4 0.6 0.8 1.0
-```
-
+ * Ограниченная память. Кольцо никогда не превышает ring_capacity слотов.
+ * O(1) на операцию. Вставка и извлечение не зависят от размера кольца.
+ * Отсутствие блокировок на писателе. Enqueue не ждёт — он либо кладёт, либо вытесняет, либо отказывает.
+ * Predictable latency. Deadline гарантирует, что клиент получит ответ в предсказуемое время.
+ * Прозрачность. Все отклонения логируются в аудит (BACKPRESSURE_REJECT) с указанием причины и текущего уровня нагрузки.
-#### Пример рассчёта
-**Исходные данные:**
+**Ограничения**
-* Уровень: High → f(level) = 0.70
+* Не является очередью. Порядок FIFO не гарантируется при вытеснении по приоритету.
+* Требует настройки под нагрузку. При слишком маленьком кольце и жёстких порогах возможны ложные срабатывания.
+* Не заменяет rate limiting. Buffer Ring сглаживает всплески, но не ограничивает устойчивую скорость запросов — для этого нужен отдельный слой rate limiter перед API.
-* CPU: 85% → cpu_usage = 0.85/0.80 = 1.0625
+**Пример**
-* Memory: 75% → memory_usage = 0.75/0.85 = 0.882
+При 10 000 RPS и пороге `cpu_threshold` = 0.8:
-* Queue: 8000/10000 = 0.8
+1. На пике 15 000 RPS CPU достигает 0.9 → уровень `High`.
+2. 5 000 «лишних» запросов попадают в кольцо (capacity 40 000).
+3. Дренажёр выпускает их по мере освобождения CPU — примерно 200 запросов каждые 10 мс.
+4. Если пик длится дольше `low_delay_ms`, «просроченные» запросы отклоняются с `504` — клиенты получают быструю деградацию вместо таймаутов.
+5. Когда нагрузка падает до 8 000 RPS, кольцо пустеет, и запросы снова идут напрямую.
-* Connections: 4000/5000 = 0.8
-* Время с последнего отклонения: 2 секунды
-
-**Рассчёт**
-```sh
-load_factor = (1.0625 + 0.882 + 0.8 + 0.8) / 4 = 0.886
-
-time_factor = 1 - e^(-0.1 × 2) = 1 - e^(-0.2) = 1 - 0.819 = 0.181
-
-P_reject = 0.70 × 0.886 × 0.181 = 0.112 = 11.2%
-```
-**Результат: ~11% запросов будут отклонены.**
-
-
-**Преимущества формулы**
-
-1. **Адаптивность** — реагирует на изменение нагрузки в реальном времени
-2. **Сглаживание** — предотвращает резкие скачки отклонений
-3. **Самовосстановление** — при снижении нагрузки вероятность автоматически уменьшается
-4. **Предсказуемость** — поведение системы становится детерминированным и предсказуемым
(К началу)