<rss version="2.0"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:media="http://search.yahoo.com/mrss/"
     xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Мишка на сервере</title>
    <link>https://jtprog.ru/</link>
    <description>Recent content in Мишка на сервере on Мишка на сервере</description>
    <generator>Hugo</generator>
    <language>ru</language>
    <copyright>jtprogru</copyright>
    <lastBuildDate>Fri, 05 Jun 2026 20:00:00 +0300</lastBuildDate>
    <atom:link href="https://jtprog.ru/" rel="self" type="application/rss+xml" /><item>
      <title>Как объяснить маме, папе, бабушке и дедушке, что такое сложный пароль</title>
      <link>https://jtprog.ru/posts/passwords-for-parents/</link>
      <pubDate>Fri, 05 Jun 2026 20:00:00 +0300</pubDate>
      <dc:creator>jtprogru</dc:creator>
      <guid isPermaLink="true">https://jtprog.ru/posts/passwords-for-parents/</guid>
      <category>Безопасность</category>
      <category>Пароли</category>
      <category>2FA</category>
      <category>Госуслуги</category>
      <category domain="category">Opinions</category>
      <enclosure url="https://jtprog.ru/cover.svg" type="image/jpeg" length="0" />
      <media:thumbnail url="https://jtprog.ru/cover.svg" /><description><![CDATA[<div><p>Привет, <code>%username%</code>! Наверняка ты ловил себя на мысли «да неее, меня-то уж точно не разведут», а потом «опаньки» — и диктуешь, сам того не понимая, код, рядом с которым написано «НИКОМУ НЕ НАЗЫВАТЬ».</p>
<p>Мамам, папам, бабушкам и дедушкам часто сложно с компьютером. А фраза «придумай сложный пароль» вызывает панику и просьбу «придумай сам». Сверху — «повсеместная цифровизация» (напомню про <a href="https://twtr.jtprog.ru/Fi5v7bAfn1h" rel="noopener noreferrer" target="_blank">&ldquo;Запись только через сайт&rdquo;</a>
) и региональные МФЦ, где работают обычные люди, для которых «сложный пароль» автоматически превращается в <code>1955.12.21Яб</code>. Виновных пусть ищут те, в чьи обязанности это входит.</p>
<h2 id="как-меня-развели">Как меня развели</h2>
<p>Пришла ко мне мама и задала вопрос: «Как придумать сложный пароль?» К её несчастью, я у неё дурной на голову, и долго рассказывал про всякое разное — для понимания контекста, так сказать. Но простые советы таки смог выделить и озвучить голосом.</p>
<p>Через какое-то время я подумал «а дай я продублирую все рекомендации ещё и текстом», а когда счётчик символов перевалил за 1.5k — понял: пусть это будет самая простая статья в моём блоге, но она должна решить одну конкретную задачу — «объяснить любым маме/папе/бабушке/дедушке, зачем сложный пароль и как его придумать».</p>
<p>Осенью 2019 года я попался на тупой развод. Подробности опущу, но тот убийственный диалог не забуду:</p>
<blockquote><p><strong>М:</strong> «Вам СМСка пришла — видите, там написано <em>Никому не называть</em>?»<br>
<strong>Я:</strong> «Да! Вижу!»<br>
<strong>М:</strong> «Называйте!»<br>
<strong>Я:</strong> «2314»<br>
<strong>М:</strong> «Спасибо!»</p>
</blockquote><p>Через считанные секунды до меня дошла абсурдность ситуации, но настолько отвратительно я себя ещё никогда не чувствовал.</p>
<p>В октябре 2022 года в подобную ситуацию попала мама. Разница лишь в том, что я отдал доступ в банк, а мама — в Госуслуги.</p>
<p>Для справки: мошенники при попытке угнать аккаунт на Госуслугах просили именно код из СМС. Это значит, что пароль уже знали — поэтому «надо придумывать сложные пароли». А зная, что «помощь с регистрацией на Госуслугах» оказывают сотрудники МФЦ, через которые проходит большой поток людей — ребята и девчата стараются себе упростить жизнь. <a href="https://www.kaspersky.ru/blog/gosuslugi-telegram-bot-hr-scam/40956/" rel="noopener noreferrer" target="_blank">Свежая схема</a>
 — угон Госуслуг через «отдел кадров» в Telegram-боте, и работает она ровно потому, что пароль слабый или повторяющийся.</p>
<p>Раньше (буквально 5–7 лет назад) хорошим паролем считался пароль с использованием латинских букв в нижнем и верхнем регистре и цифр <code>0-9</code>, а достаточной длиной — 6–8 символов. Сейчас правила другие. NIST в актуальной редакции <a href="https://pages.nist.gov/800-63-3/sp800-63b.html" rel="noopener noreferrer" target="_blank">SP 800-63B</a>
 (<a href="https://www.enzoic.com/blog/nist-sp-800-63b-rev4/" rel="noopener noreferrer" target="_blank">Rev.4, август 2025</a>
) формулирует прямо: длина важнее «сложности». Минимум — 15 символов, если пароль один и без второго фактора. Состав символов больше не обязателен — главное, чтобы пароль был длинным, уникальным и не светился в утечках.</p>
<h2 id="что-делать">Что делать</h2>
<p>То, что я предложу дальше, кому-то покажется слишком сложным, кому-то слишком простым. Но сделать это надо.</p>
<p>Для начала возьми отдельный блокнот и ручку и выпиши все сайты, на которые ходишь с логином и паролем — в простейшем формате:</p>
<ul>
<li>Сайт: <code>ya.ru</code></li>
<li>Логин/имя пользователя: <code>vasilisapetrovna@ya.ru</code></li>
<li>Пароль: <code>МойТекущийПароль</code></li>
</ul>
<p>Дальше — пройдись по списку и отметь, что не так. Имя, дата рождения, простое слово, которое легко соотнести с тобой (<code>vasya</code>, <code>10012990</code>, <code>prepod</code>) — под замену. Всё, что короче 15 символов, — под замену. Повторяющиеся пароли — самое опасное: узнают пароль от Одноквашников и в остальные сервисы попадут без проблем.</p>
<p>Теперь главный вопрос: «как придумать сложный пароль?» Это проще, чем кажется.</p>
<p>Бери четыре слова, которые с тобой никак не связаны, и склеивай в одну фразу. Например: <code>корзина-трактор-ягода-фонарь</code>. Запомнить — секунда, а для бытовых угроз (фишинг, утечки, перебор) — больше чем достаточно. По-научному это «парольная фраза», и она бьёт «сложный» восьмисимвольный шифр с <code>@</code>, <code>#</code> и <code>$</code> в одну калитку. Подробнее про парольные фразы и как их не забывать — у <a href="https://te-st.org/2025/09/26/top3-sposoba-pridumyvat-nadyozhnye-paroli-i-bolshe-ih-ne-zabyvat/" rel="noopener noreferrer" target="_blank">Теплицы социальных технологий</a>
 и у <a href="https://www.kaspersky.ru/blog/international-password-day-2025/39449/" rel="noopener noreferrer" target="_blank">Касперского</a>
.</p>
<p>Только не используй мою комбинацию буквально — как только пост уйдёт в публикацию, она через пару дней приедет в словари для перебора. Возьми свои четыре слова, желательно — из разных смысловых полей (не «кот-собака-хомяк-попугай», а что-то вроде «фиалка-домкрат-печенье-маяк»).</p>
<p>Если придумывать совсем лень — поставь менеджер паролей. Из живых и проверенных — четыре на выбор:</p>
<ul>
<li><a href="https://bitwarden.com/" rel="noopener noreferrer" target="_blank">Bitwarden</a>
 — бесплатный, open-source, под все платформы и браузеры. По умолчанию пароли лежат в облаке самого Bitwarden, но можно поднять <a href="https://bitwarden.com/help/install-on-premise-linux/" rel="noopener noreferrer" target="_blank">свой сервер</a>
 — большинству не надо, берём облако и не паримся.</li>
<li><a href="https://keepass.info/" rel="noopener noreferrer" target="_blank">KeePass</a>
 и его форки — <a href="https://keepassxc.org/" rel="noopener noreferrer" target="_blank">KeePassXC</a>
 на десктопе, <a href="https://www.keepassdx.com/" rel="noopener noreferrer" target="_blank">KeePassDX</a>
 на Android, <a href="https://strongboxsafe.com/" rel="noopener noreferrer" target="_blank">Strongbox</a>
 на iOS. Тоже бесплатно и open-source, но всё хранится в одном зашифрованном файле — и ты сам решаешь, где этот файл лежит: на диске, в iCloud, в Яндекс.Диске, на флешке. Гибче, но и думать придётся больше.</li>
<li><a href="https://proton.me/pass" rel="noopener noreferrer" target="_blank">Proton Pass</a>
 — бесплатный (с лимитами) или ~$4 в месяц за полную версию, open-source, от команды ProtonMail. Швейцарская юрисдикция, end-to-end шифрование, есть встроенный 2FA-аутентификатор и алиасы почты. По духу ближе к Bitwarden, но интерфейс заметно более «человеческий».</li>
<li><a href="https://1password.com/" rel="noopener noreferrer" target="_blank">1Password</a>
 — платный (~$48 в год для одного, ~$72 в год за семейный план на пятерых, <a href="https://www.ubergizmo.com/2026/02/1password-price-increase/" rel="noopener noreferrer" target="_blank">с марта 2026 цена выросла</a>
), зато с самым человеческим интерфейсом. Если настраиваешь маме и не хочешь объяснять, что такое «синхронизация vault&rsquo;а» — это, пожалуй, самый короткий путь.</li>
</ul>
<p>Один длинный пароль помнишь сам (тот самый, из четырёх слов) — это мастер-пароль от менеджера. Остальные пусть генерит и хранит он.</p>
<p>Тут есть ловушка, в которую попадают все, кто впервые ставит менеджер паролей: если потерял мастер-пароль — потерял всё. Никакой «восстановим по СМС» там не предусмотрено: это и есть фича, а не баг — иначе мошенник делал бы то же самое. Поэтому мастер-пароль выписываешь на бумажку (тот самый блокнот пригодится) и кладёшь в надёжное место дома. У 1Password есть ещё <code>Secret Key</code> — это второй ключ, который тоже нужен для входа на новом устройстве; его аналогично распечатываешь и хранишь.</p>
<p>А если ставить отдельное приложение всё равно лень — посмотри, что уже встроено. На iPhone и Mac это <a href="https://support.apple.com/ru-ru/HT204085" rel="noopener noreferrer" target="_blank">«Связка ключей iCloud»</a>
 (в iOS 18 и macOS Sequoia — уже отдельным приложением <a href="https://support.apple.com/ru-ru/120758" rel="noopener noreferrer" target="_blank">«Пароли»</a>
). На Android и в Chrome — <a href="https://passwords.google.com/" rel="noopener noreferrer" target="_blank">Google Password Manager</a>
. У тех, кто живёт в Яндекс.Браузере, — <a href="https://browser.yandex.ru/help/personal-data-protection/passwords.html" rel="noopener noreferrer" target="_blank">встроенный менеджер Яндекса</a>
. Базовая механика везде одна: сгенерировать длинный пароль, запомнить, подставить в нужное поле и раскатать на остальные устройства. Для задачи «перестать использовать один и тот же пароль везде» этого хватает.</p>
<p>Цена простоты — привязка к экосистеме. Связка ключей не поедет на Android, Google Password Manager на iPhone — поедет, но криво. Яндекс — только в Яндекс.Браузере. Пин-код от карты или код от домофона туда тоже не положишь: это не сейф произвольных секретов, а хранилище логинов-паролей к сайтам. Поэтому встроенный менеджер — нормальный первый шаг, но как только сменишь телефон с iPhone на Android или наоборот — переезжать будет больно. Bitwarden, KeePass и 1Password в этом смысле нейтральны: работают одинаково везде.</p>
<p>А если и менеджер паролей — это уже слишком сложно (бабушке, дедушке, кому-то ещё, кто с компьютером на «вы»), есть рабочий вариант, над которым любят посмеяться безопасники: маленький блокнот и ручка. Да-да, тот самый, с которого мы начали — где выписаны сайт, логин и пароль. Пусть он и останется хранилищем для важного: Госуслуги, банк, почта, пин-коды от карт. Пароли в нём могут быть какими угодно длинными и страшными — записал и не запоминаешь.</p>
<p>Тут важно понимать, от чего этот способ защищает, а от чего — нет. От фишинга, утечек паролей с сайтов и звонков «из службы безопасности» — защищает: пароль уникальный, длинный, нигде не светится. От того, кто физически возьмёт блокнот в руки, — нет. Отсюда пара правил: блокнот живёт дома, в одном понятном месте, не в сумке и не в кошельке; никаких подписей «ПАРОЛИ» на обложке; и желательно — не на виду у курьера, мастера и случайных гостей. Для мамы с папой риск «пришли в квартиру и нашли блокнот» сильно меньше риска «надиктовал код по телефону мошеннику» — этим и берём.</p>
<p>Включи второй фактор (2FA) хотя бы на банке, почте и Госуслугах. Лучше через приложение-аутентификатор, а не через SMS — SMS уязвимы к SIM-swap (мошенник идёт в салон с поддельной доверенностью и перевыпускает симку на свой паспорт; все коды теперь идут ему) и к классическому выманиванию по телефону.</p>
<p>Из аутентификаторов на Android — <a href="https://getaegis.app/" rel="noopener noreferrer" target="_blank">Aegis</a>
 (open-source, можно делать зашифрованный бэкап) или <a href="https://2fas.com/" rel="noopener noreferrer" target="_blank">2FAS</a>
. На iPhone — <a href="https://2fas.com/" rel="noopener noreferrer" target="_blank">2FAS</a>
 или встроенный кодогенератор прямо в приложении «Пароли». Кроссплатформенно — <a href="https://support.google.com/accounts/answer/1066447" rel="noopener noreferrer" target="_blank">Google Authenticator</a>
 (с облачной синхронизацией) или <a href="https://yandex.ru/support/id/authenticator/about.html" rel="noopener noreferrer" target="_blank">Яндекс Ключ</a>
.</p>
<p>При подключении 2FA сервис показывает <strong>резервные коды</strong> — обычно 8–10 одноразовых кодов на случай, если телефон с аутентификатором утонет, разобьётся или потеряется. Их обязательно сохрани: в менеджер паролей, в тот же блокнот, в Telegram-избранное — куда угодно, но не игнорируй экран «вот ваши backup-коды, сохраните их». Без них при потере телефона восстановление доступа превращается в эпопею с фотографиями паспорта в техподдержку, а где-то — в полное «начать с нуля».</p>
<p>Где можно — переходи на passkeys. Google, Apple, Microsoft, GitHub уже поддерживают. Это вход без пароля, по биометрии. Продиктовать по телефону его в принципе нельзя — нечего диктовать.</p>
<h2 id="если-коротко">Если коротко</h2>
<p>Три правила, которые закроют львиную долю бытовых угроз:</p>
<ol>
<li>Пароль от 15 символов, не повторяется между сервисами, не светится в утечках.</li>
<li>На критичных аккаунтах (банк, почта, Госуслуги) — второй фактор через приложение.</li>
<li>Никаких кодов из SMS вслух по телефону. С 1 июня 2025 в России <a href="https://rg.ru/2025/05/30/vyzov-sbroshen.html" rel="noopener noreferrer" target="_blank">действует правило</a>
: пока идёт голосовой вызов, SMS с кодами подтверждения (от Госуслуг, банков, маркетплейсов) задерживаются оператором связи и доставляются только после разговора. Но этот закон не помогает, если мошенник звонит через WhatsApp, Telegram или Zoom — для оператора это просто интернет-трафик, SMS пройдёт как обычно. Поэтому правило «положил трубку, перезвонил по номеру с карты» по-прежнему рабочее.</li>
</ol>
<p>Если ты помог маме/папе/бабушке/дедушке настроить менеджер паролей и 2FA — ты сделал больше, чем три статьи на эту тему. Передай дальше.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></description>
      <content:encoded><![CDATA[<style>/* Inline-CSS, который тема вкладывает в <description> каждого item'а
   RSS-фида (layouts/index.rss.xml). RSS-ридеры (Feedly, Inoreader,
   NetNewsWire) уважают <style> внутри description с переменной
   степенью энтузиазма — это базовый fallback, достаточный для читаемой
   типографики, не более.

   Цвета продублированы из 00-vars.css (light-палитра) — поправь
   синхронно при изменении --bg / --text / --accent / --border. */

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  line-height: 1.6;
  color: #1c1c1f;
  max-width: 720px;
  margin: 0 auto;
  padding: 1em;
}
h1, h2, h3 { line-height: 1.25; margin-top: 1.4em; }
a { color: #c2410c; }
pre {
  background: #1e1e24;
  color: #e8e6df;
  padding: 1em;
  border-radius: 6px;
  overflow-x: auto;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.9em;
}
code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  background: #f3f1ed;
  padding: 0.1em 0.4em;
  border-radius: 4px;
}
pre code { background: transparent; padding: 0; }
blockquote {
  border-left: 3px solid #c2410c;
  padding-left: 1em;
  color: #5b5b62;
  font-style: italic;
  margin-left: 0;
}
img { max-width: 100%; height: auto; border-radius: 6px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #e5e3dc; padding: 6px 10px; text-align: left; }
</style><div><p>Привет, <code>%username%</code>! Наверняка ты ловил себя на мысли «да неее, меня-то уж точно не разведут», а потом «опаньки» — и диктуешь, сам того не понимая, код, рядом с которым написано «НИКОМУ НЕ НАЗЫВАТЬ».</p>
<p>Мамам, папам, бабушкам и дедушкам часто сложно с компьютером. А фраза «придумай сложный пароль» вызывает панику и просьбу «придумай сам». Сверху — «повсеместная цифровизация» (напомню про <a href="https://twtr.jtprog.ru/Fi5v7bAfn1h" rel="noopener noreferrer" target="_blank">&ldquo;Запись только через сайт&rdquo;</a>
) и региональные МФЦ, где работают обычные люди, для которых «сложный пароль» автоматически превращается в <code>1955.12.21Яб</code>. Виновных пусть ищут те, в чьи обязанности это входит.</p>
<h2 id="как-меня-развели">Как меня развели</h2>
<p>Пришла ко мне мама и задала вопрос: «Как придумать сложный пароль?» К её несчастью, я у неё дурной на голову, и долго рассказывал про всякое разное — для понимания контекста, так сказать. Но простые советы таки смог выделить и озвучить голосом.</p>
<p>Через какое-то время я подумал «а дай я продублирую все рекомендации ещё и текстом», а когда счётчик символов перевалил за 1.5k — понял: пусть это будет самая простая статья в моём блоге, но она должна решить одну конкретную задачу — «объяснить любым маме/папе/бабушке/дедушке, зачем сложный пароль и как его придумать».</p>
<p>Осенью 2019 года я попался на тупой развод. Подробности опущу, но тот убийственный диалог не забуду:</p>
<blockquote><p><strong>М:</strong> «Вам СМСка пришла — видите, там написано <em>Никому не называть</em>?»<br>
<strong>Я:</strong> «Да! Вижу!»<br>
<strong>М:</strong> «Называйте!»<br>
<strong>Я:</strong> «2314»<br>
<strong>М:</strong> «Спасибо!»</p>
</blockquote><p>Через считанные секунды до меня дошла абсурдность ситуации, но настолько отвратительно я себя ещё никогда не чувствовал.</p>
<p>В октябре 2022 года в подобную ситуацию попала мама. Разница лишь в том, что я отдал доступ в банк, а мама — в Госуслуги.</p>
<p>Для справки: мошенники при попытке угнать аккаунт на Госуслугах просили именно код из СМС. Это значит, что пароль уже знали — поэтому «надо придумывать сложные пароли». А зная, что «помощь с регистрацией на Госуслугах» оказывают сотрудники МФЦ, через которые проходит большой поток людей — ребята и девчата стараются себе упростить жизнь. <a href="https://www.kaspersky.ru/blog/gosuslugi-telegram-bot-hr-scam/40956/" rel="noopener noreferrer" target="_blank">Свежая схема</a>
 — угон Госуслуг через «отдел кадров» в Telegram-боте, и работает она ровно потому, что пароль слабый или повторяющийся.</p>
<p>Раньше (буквально 5–7 лет назад) хорошим паролем считался пароль с использованием латинских букв в нижнем и верхнем регистре и цифр <code>0-9</code>, а достаточной длиной — 6–8 символов. Сейчас правила другие. NIST в актуальной редакции <a href="https://pages.nist.gov/800-63-3/sp800-63b.html" rel="noopener noreferrer" target="_blank">SP 800-63B</a>
 (<a href="https://www.enzoic.com/blog/nist-sp-800-63b-rev4/" rel="noopener noreferrer" target="_blank">Rev.4, август 2025</a>
) формулирует прямо: длина важнее «сложности». Минимум — 15 символов, если пароль один и без второго фактора. Состав символов больше не обязателен — главное, чтобы пароль был длинным, уникальным и не светился в утечках.</p>
<h2 id="что-делать">Что делать</h2>
<p>То, что я предложу дальше, кому-то покажется слишком сложным, кому-то слишком простым. Но сделать это надо.</p>
<p>Для начала возьми отдельный блокнот и ручку и выпиши все сайты, на которые ходишь с логином и паролем — в простейшем формате:</p>
<ul>
<li>Сайт: <code>ya.ru</code></li>
<li>Логин/имя пользователя: <code>vasilisapetrovna@ya.ru</code></li>
<li>Пароль: <code>МойТекущийПароль</code></li>
</ul>
<p>Дальше — пройдись по списку и отметь, что не так. Имя, дата рождения, простое слово, которое легко соотнести с тобой (<code>vasya</code>, <code>10012990</code>, <code>prepod</code>) — под замену. Всё, что короче 15 символов, — под замену. Повторяющиеся пароли — самое опасное: узнают пароль от Одноквашников и в остальные сервисы попадут без проблем.</p>
<p>Теперь главный вопрос: «как придумать сложный пароль?» Это проще, чем кажется.</p>
<p>Бери четыре слова, которые с тобой никак не связаны, и склеивай в одну фразу. Например: <code>корзина-трактор-ягода-фонарь</code>. Запомнить — секунда, а для бытовых угроз (фишинг, утечки, перебор) — больше чем достаточно. По-научному это «парольная фраза», и она бьёт «сложный» восьмисимвольный шифр с <code>@</code>, <code>#</code> и <code>$</code> в одну калитку. Подробнее про парольные фразы и как их не забывать — у <a href="https://te-st.org/2025/09/26/top3-sposoba-pridumyvat-nadyozhnye-paroli-i-bolshe-ih-ne-zabyvat/" rel="noopener noreferrer" target="_blank">Теплицы социальных технологий</a>
 и у <a href="https://www.kaspersky.ru/blog/international-password-day-2025/39449/" rel="noopener noreferrer" target="_blank">Касперского</a>
.</p>
<p>Только не используй мою комбинацию буквально — как только пост уйдёт в публикацию, она через пару дней приедет в словари для перебора. Возьми свои четыре слова, желательно — из разных смысловых полей (не «кот-собака-хомяк-попугай», а что-то вроде «фиалка-домкрат-печенье-маяк»).</p>
<p>Если придумывать совсем лень — поставь менеджер паролей. Из живых и проверенных — четыре на выбор:</p>
<ul>
<li><a href="https://bitwarden.com/" rel="noopener noreferrer" target="_blank">Bitwarden</a>
 — бесплатный, open-source, под все платформы и браузеры. По умолчанию пароли лежат в облаке самого Bitwarden, но можно поднять <a href="https://bitwarden.com/help/install-on-premise-linux/" rel="noopener noreferrer" target="_blank">свой сервер</a>
 — большинству не надо, берём облако и не паримся.</li>
<li><a href="https://keepass.info/" rel="noopener noreferrer" target="_blank">KeePass</a>
 и его форки — <a href="https://keepassxc.org/" rel="noopener noreferrer" target="_blank">KeePassXC</a>
 на десктопе, <a href="https://www.keepassdx.com/" rel="noopener noreferrer" target="_blank">KeePassDX</a>
 на Android, <a href="https://strongboxsafe.com/" rel="noopener noreferrer" target="_blank">Strongbox</a>
 на iOS. Тоже бесплатно и open-source, но всё хранится в одном зашифрованном файле — и ты сам решаешь, где этот файл лежит: на диске, в iCloud, в Яндекс.Диске, на флешке. Гибче, но и думать придётся больше.</li>
<li><a href="https://proton.me/pass" rel="noopener noreferrer" target="_blank">Proton Pass</a>
 — бесплатный (с лимитами) или ~$4 в месяц за полную версию, open-source, от команды ProtonMail. Швейцарская юрисдикция, end-to-end шифрование, есть встроенный 2FA-аутентификатор и алиасы почты. По духу ближе к Bitwarden, но интерфейс заметно более «человеческий».</li>
<li><a href="https://1password.com/" rel="noopener noreferrer" target="_blank">1Password</a>
 — платный (~$48 в год для одного, ~$72 в год за семейный план на пятерых, <a href="https://www.ubergizmo.com/2026/02/1password-price-increase/" rel="noopener noreferrer" target="_blank">с марта 2026 цена выросла</a>
), зато с самым человеческим интерфейсом. Если настраиваешь маме и не хочешь объяснять, что такое «синхронизация vault&rsquo;а» — это, пожалуй, самый короткий путь.</li>
</ul>
<p>Один длинный пароль помнишь сам (тот самый, из четырёх слов) — это мастер-пароль от менеджера. Остальные пусть генерит и хранит он.</p>
<p>Тут есть ловушка, в которую попадают все, кто впервые ставит менеджер паролей: если потерял мастер-пароль — потерял всё. Никакой «восстановим по СМС» там не предусмотрено: это и есть фича, а не баг — иначе мошенник делал бы то же самое. Поэтому мастер-пароль выписываешь на бумажку (тот самый блокнот пригодится) и кладёшь в надёжное место дома. У 1Password есть ещё <code>Secret Key</code> — это второй ключ, который тоже нужен для входа на новом устройстве; его аналогично распечатываешь и хранишь.</p>
<p>А если ставить отдельное приложение всё равно лень — посмотри, что уже встроено. На iPhone и Mac это <a href="https://support.apple.com/ru-ru/HT204085" rel="noopener noreferrer" target="_blank">«Связка ключей iCloud»</a>
 (в iOS 18 и macOS Sequoia — уже отдельным приложением <a href="https://support.apple.com/ru-ru/120758" rel="noopener noreferrer" target="_blank">«Пароли»</a>
). На Android и в Chrome — <a href="https://passwords.google.com/" rel="noopener noreferrer" target="_blank">Google Password Manager</a>
. У тех, кто живёт в Яндекс.Браузере, — <a href="https://browser.yandex.ru/help/personal-data-protection/passwords.html" rel="noopener noreferrer" target="_blank">встроенный менеджер Яндекса</a>
. Базовая механика везде одна: сгенерировать длинный пароль, запомнить, подставить в нужное поле и раскатать на остальные устройства. Для задачи «перестать использовать один и тот же пароль везде» этого хватает.</p>
<p>Цена простоты — привязка к экосистеме. Связка ключей не поедет на Android, Google Password Manager на iPhone — поедет, но криво. Яндекс — только в Яндекс.Браузере. Пин-код от карты или код от домофона туда тоже не положишь: это не сейф произвольных секретов, а хранилище логинов-паролей к сайтам. Поэтому встроенный менеджер — нормальный первый шаг, но как только сменишь телефон с iPhone на Android или наоборот — переезжать будет больно. Bitwarden, KeePass и 1Password в этом смысле нейтральны: работают одинаково везде.</p>
<p>А если и менеджер паролей — это уже слишком сложно (бабушке, дедушке, кому-то ещё, кто с компьютером на «вы»), есть рабочий вариант, над которым любят посмеяться безопасники: маленький блокнот и ручка. Да-да, тот самый, с которого мы начали — где выписаны сайт, логин и пароль. Пусть он и останется хранилищем для важного: Госуслуги, банк, почта, пин-коды от карт. Пароли в нём могут быть какими угодно длинными и страшными — записал и не запоминаешь.</p>
<p>Тут важно понимать, от чего этот способ защищает, а от чего — нет. От фишинга, утечек паролей с сайтов и звонков «из службы безопасности» — защищает: пароль уникальный, длинный, нигде не светится. От того, кто физически возьмёт блокнот в руки, — нет. Отсюда пара правил: блокнот живёт дома, в одном понятном месте, не в сумке и не в кошельке; никаких подписей «ПАРОЛИ» на обложке; и желательно — не на виду у курьера, мастера и случайных гостей. Для мамы с папой риск «пришли в квартиру и нашли блокнот» сильно меньше риска «надиктовал код по телефону мошеннику» — этим и берём.</p>
<p>Включи второй фактор (2FA) хотя бы на банке, почте и Госуслугах. Лучше через приложение-аутентификатор, а не через SMS — SMS уязвимы к SIM-swap (мошенник идёт в салон с поддельной доверенностью и перевыпускает симку на свой паспорт; все коды теперь идут ему) и к классическому выманиванию по телефону.</p>
<p>Из аутентификаторов на Android — <a href="https://getaegis.app/" rel="noopener noreferrer" target="_blank">Aegis</a>
 (open-source, можно делать зашифрованный бэкап) или <a href="https://2fas.com/" rel="noopener noreferrer" target="_blank">2FAS</a>
. На iPhone — <a href="https://2fas.com/" rel="noopener noreferrer" target="_blank">2FAS</a>
 или встроенный кодогенератор прямо в приложении «Пароли». Кроссплатформенно — <a href="https://support.google.com/accounts/answer/1066447" rel="noopener noreferrer" target="_blank">Google Authenticator</a>
 (с облачной синхронизацией) или <a href="https://yandex.ru/support/id/authenticator/about.html" rel="noopener noreferrer" target="_blank">Яндекс Ключ</a>
.</p>
<p>При подключении 2FA сервис показывает <strong>резервные коды</strong> — обычно 8–10 одноразовых кодов на случай, если телефон с аутентификатором утонет, разобьётся или потеряется. Их обязательно сохрани: в менеджер паролей, в тот же блокнот, в Telegram-избранное — куда угодно, но не игнорируй экран «вот ваши backup-коды, сохраните их». Без них при потере телефона восстановление доступа превращается в эпопею с фотографиями паспорта в техподдержку, а где-то — в полное «начать с нуля».</p>
<p>Где можно — переходи на passkeys. Google, Apple, Microsoft, GitHub уже поддерживают. Это вход без пароля, по биометрии. Продиктовать по телефону его в принципе нельзя — нечего диктовать.</p>
<h2 id="если-коротко">Если коротко</h2>
<p>Три правила, которые закроют львиную долю бытовых угроз:</p>
<ol>
<li>Пароль от 15 символов, не повторяется между сервисами, не светится в утечках.</li>
<li>На критичных аккаунтах (банк, почта, Госуслуги) — второй фактор через приложение.</li>
<li>Никаких кодов из SMS вслух по телефону. С 1 июня 2025 в России <a href="https://rg.ru/2025/05/30/vyzov-sbroshen.html" rel="noopener noreferrer" target="_blank">действует правило</a>
: пока идёт голосовой вызов, SMS с кодами подтверждения (от Госуслуг, банков, маркетплейсов) задерживаются оператором связи и доставляются только после разговора. Но этот закон не помогает, если мошенник звонит через WhatsApp, Telegram или Zoom — для оператора это просто интернет-трафик, SMS пройдёт как обычно. Поэтому правило «положил трубку, перезвонил по номеру с карты» по-прежнему рабочее.</li>
</ol>
<p>Если ты помог маме/папе/бабушке/дедушке настроить менеджер паролей и 2FA — ты сделал больше, чем три статьи на эту тему. Передай дальше.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></content:encoded>
    </item><item>
      <title>IndexNow для статического блога: что это, зачем и как я его прикручивал</title>
      <link>https://jtprog.ru/posts/indexnow/</link>
      <pubDate>Tue, 02 Jun 2026 14:58:25 +0300</pubDate>
      <dc:creator>jtprogru</dc:creator>
      <guid isPermaLink="true">https://jtprog.ru/posts/indexnow/</guid>
      <category>Hugo</category>
      <category>GitHub Actions</category>
      <category>Seo</category>
      <category>Ci</category>
      <category domain="category">Howto</category>
      <enclosure url="https://jtprog.ru/howto.png" type="image/jpeg" length="0" />
      <media:thumbnail url="https://jtprog.ru/howto.png" /><description><![CDATA[<div><p>Привет, <code>%username%</code>! Выкатил новый пост, поправил страницу, обновил title — и сидишь, ждёшь, пока поисковики соизволят переобойти сайт. День, два, неделя. А хочется, чтобы апдейт подхватился сразу после <code>git push</code>, без танцев с Search Console и ручных submission-форм.</p>
<p>Дальше — как закрыть эту боль одним шагом в GitHub Actions через мой CLI <a href="https://github.com/jtprogru/indexnow" rel="noopener noreferrer" target="_blank">indexnow</a>
 и почему оно вообще работает.</p>
<h2 id="что-такое-indexnow-и-зачем-он-нужен">Что такое IndexNow и зачем он нужен</h2>
<p>Протокол <a href="https://www.indexnow.org/documentation" rel="noopener noreferrer" target="_blank">IndexNow</a>
 — это простой способ сказать поисковику: «эти URL изменились, переобойди их побыстрее, пожалуйста». Ты делаешь один HTTP-запрос с ключом и списком URL, поисковик в ответ подтверждает приём (или отбивает с осмысленной ошибкой) — и дальше уже его проблема, когда именно он переобойдёт страницы.</p>
<p>Главное: <strong>submission автоматически шарится между всеми участниками протокола</strong>. По спеке достаточно дёрнуть <strong>один</strong> эндпоинт (например, <code>api.indexnow.org</code> или <code>bing.com/indexnow</code>), и тот же запрос провалидируется и расшарится со всеми: Bing, Yandex, Naver, Seznam, Yep и другие участники. Google к протоколу формально не присоединился — для него по-прежнему остаётся sitemap + Search Console.</p>
<p>Аутентификация — самая «забавная» часть протокола. Ты придумываешь ключ (произвольная hex-строка длиной 8–128 символов), хостишь его в виде текстового файла на собственном домене, например <code>https://example.com/&lt;key&gt;.txt</code>, и присылаешь этот ключ в каждом запросе. Поисковик идёт по URL, читает файл, сверяет содержимое с тем ключом, что ты прислал. Совпало — submission принят. Нет — 403. Просто и без OAuth.</p>
<p>И тут же — мой любимый перл из <a href="https://yandex.ru/support/webmaster/ru/indexnow/key" rel="noopener noreferrer" target="_blank">документации Яндекс.Вебмастера</a>
: «Ключ менять необязательно. Вы можете изменить ключ, если он стал известен третьим лицам.» То есть ключ, который ты по спеке обязан выложить публичным <code>.txt</code> на свой домен и который любой может вытащить одним <code>curl</code>, Яндекс предлагает ротировать, если он «стал известен третьим лицам». А он по дизайну протокола известен им всегда. Ну камон.</p>
<h2 id="зачем-я-написал-свой-cli">Зачем я написал свой CLI</h2>
<p>Дёргать API руками лениво, особенно когда у тебя на пуш приходится 10–50 изменившихся URL и хочется делать это из CI. Можно, конечно, нагуглить готовый пример с <code>curl</code> и <code>jq</code>, но:</p>
<ul>
<li>ошибки разбирать в bash больно;</li>
<li>ретраи на 429/5xx писать руками лень;</li>
<li>sitemap парсить из XML в bash — отдельный жанр перформанса;</li>
<li>лимит протокола в 10 000 URL на запрос тоже надо учитывать.</li>
</ul>
<p>Поэтому я написал на <a href="/want-coding-golang/">Go</a>
 маленький <code>indexnow</code> — сначала как CLI для разовых submission&rsquo;ов, а с релиза <code>v0.5.0</code> это уже и <strong>готовый GitHub Action</strong>. По дороге всё то, что обычно копится в самописных скриптах, я аккуратно унёс внутрь бинаря.</p>
<p>Заодно это стало хорошим pet-project&rsquo;ом: тесты с <code>-race</code>, <code>golangci-lint</code>, <code>mkdocs</code> для документации, релизы через <code>goreleaser</code>, а теперь и composite Action с верификацией бинарей. Маленький инструмент, который и время экономит, и руки в форме держит.</p>
<h2 id="минимальный-шаг-в-github-actions">Минимальный шаг в GitHub Actions</h2>
<p>Самый короткий путь — взять готовый Action и засунуть один шаг в workflow:</p>
<div class="codeblock codeblock--yaml" data-lang="yaml"><span class="codeblock__lang" aria-hidden="true">yaml</span><button class="codeblock__copy" type="button" data-copy aria-label="Скопировать" title="Скопировать"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">jtprogru/indexnow@v0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">with</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.INDEXNOW_KEY }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">sitemap</span><span class="p">:</span><span class="w"> </span><span class="l">https://example.com/sitemap.xml</span></span></span></code></pre></div>
</div>
<p>Всё. Этот шаг сам:</p>
<ul>
<li>определит ОС и архитектуру раннера (<code>linux/amd64</code>, <code>linux/arm64</code>, <code>darwin/arm64</code>, …);</li>
<li>скачает релизный бинарь нужной сборки со страницы релизов;</li>
<li>сверит его <code>sha256</code> с <code>checksums.txt</code>, который лежит рядом с бинарями в релизе — это защищает от «а что если кто-то подменил артефакт»;</li>
<li>закэширует бинарь в <code>runner.tool_cache</code>, чтобы следующие раны не качали его повторно;</li>
<li>запустит <code>indexnow submit</code> с переданными параметрами.</li>
</ul>
<p>Ключ передаётся через <code>env</code>, а не флагом, — даже если в твоём шаге случайно отрабатывает <code>set -x</code>, ключ в логах не светится. В <code>$GITHUB_STEP_SUMMARY</code> после прогона падает короткий отчёт: сколько URL улетело, сколько батчей упало, куда отправлял. Не нужно лезть в полный лог раннера, чтобы понять, прошёл submit или нет.</p>
<h2 id="submit-только-тех-url-что-изменились">Submit только тех URL, что изменились</h2>
<p>Слать весь sitemap при каждом пуше расточительно: поисковики переобойдут страницы и без тебя, IndexNow используешь именно для тех апдейтов, что важны прямо сейчас. Поэтому мой любимый рецепт — submit ровно того, что изменилось между предыдущим и текущим коммитом:</p>
<div class="codeblock codeblock--yaml" data-lang="yaml"><span class="codeblock__lang" aria-hidden="true">yaml</span><button class="codeblock__copy" type="button" data-copy aria-label="Скопировать" title="Скопировать"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">jtprogru/indexnow@v0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">with</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.INDEXNOW_KEY }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">sitemap</span><span class="p">:</span><span class="w"> </span><span class="l">https://example.com/sitemap.xml</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">sitemap-since</span><span class="p">:</span><span class="w"> </span><span class="l">${{ github.event.before }}</span></span></span></code></pre></div>
</div>
<p><code>sitemap-since</code> фильтрует записи sitemap по <code>&lt;lastmod&gt;</code>: всё, что старее переданного времени, отбрасывается.</p>
<p>Один граничный случай, который я заложил по умолчанию: <strong>записи без <code>&lt;lastmod&gt;</code> всегда проходят</strong>. «Нет сигнала о времени» трактуется как «могло измениться», и для IndexNow это безопасный дефолт — повторный submit идемпотентен, лишний раз дёрнуть не страшно. Куда хуже промолчать про реально изменившуюся страницу.</p>
<h2 id="а-если-sitemapу-не-доверяешь--urls-from">А если sitemap&rsquo;у не доверяешь — <code>urls-from</code></h2>
<p><code>sitemap-since</code> хорош, когда <code>&lt;lastmod&gt;</code> у тебя действительно проставляется. Если нет (или ты не хочешь полагаться на свежесть sitemap&rsquo;а вообще) — есть второй рецепт: собрать список URL из <code>git diff</code> между двумя коммитами и скормить его в Action через <code>urls-from</code>.</p>
<div class="codeblock codeblock--yaml" data-lang="yaml"><span class="codeblock__lang" aria-hidden="true">yaml</span><button class="codeblock__copy" type="button" data-copy aria-label="Скопировать" title="Скопировать"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/checkout@v6</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">with</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">fetch-depth</span><span class="p">:</span><span class="w"> </span><span class="m">0</span><span class="w">
</span></span></span><span class="line"><span class="cl">- <span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">jtprogru/indexnow@v0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">with</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.INDEXNOW_KEY }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">urls-from</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">      git diff --name-only &#34;${{ github.event.before }}..HEAD&#34; -- &#39;content/**/*.md&#39; |
</span></span></span><span class="line"><span class="cl"><span class="sd">        sed &#39;s#^content/\(.*\)/index\.md$#https://jtprog.ru/\1/#&#39;</span></span></span></code></pre></div>
</div>
<p><code>urls-from</code> — это просто bash-сниппет, чей stdout (по одной строке на URL) превращается в источник URL. Сниппет крутится в <code>$GITHUB_WORKSPACE</code>, так что <code>git</code> видит весь checked-out репозиторий и <code>git diff</code> работает как обычно. Пустой вывод — это не ошибка, шаг тихо выйдет с <code>submitted-count=0</code>.</p>
<p>Вот тот самый маппинг: <code>content/&lt;slug&gt;/index.md</code> → <code>https://jtprog.ru/&lt;slug&gt;/</code>. Никакого парсинга sitemap, никаких лишних submission&rsquo;ов на страницы, которые не трогал. <code>fetch-depth: 0</code> обязательно — без полной истории <code>git diff</code> против <code>github.event.before</code> молча отдаст пустоту.</p>
<h2 id="тег-v0-и-плавающие-версии">Тег <code>@v0</code> и плавающие версии</h2>
<p>Одна из мелких, но важных деталей — модель версионирования.</p>
<ul>
<li><code>@v0.7.0</code> — конкретный релиз. Поведение зафиксировано, обновления только если ты сам поправишь workflow.</li>
<li><code>@v0.7</code> — все патчи внутри <code>0.7.x</code>, обновляется автоматически.</li>
<li><code>@v0</code> — все релизы внутри <code>0.x</code>, едет с каждым новым минором.</li>
</ul>
<p>Плавающие теги (<code>v0</code>, <code>v0.5</code>) переставляются отдельным workflow на каждый релиз <code>v0.Y.Z</code>. То есть подписался один раз на <code>@v0</code> — и едешь на последнем <code>0.x</code> без правок workflow. Когда выкачу <code>v1.0.0</code>, тег <code>@v0</code> останется на последнем релизе ветки <code>0.x</code>: ты сам решаешь, переезжать ли на мажор. Никаких сюрпризов в духе «обновился — поведение сломалось».</p>
<h2 id="inputs-outputs-и-downstream-шаги">Inputs, outputs и downstream-шаги</h2>
<p>Inputs Action&rsquo;а зеркалят флаги CLI: источники URL (<code>urls</code> / <code>file</code> / <code>sitemap</code> / <code>urls-from</code>), <code>sitemap-since</code>, <code>endpoint</code>, <code>host</code>, <code>key-location</code>, <code>fail-on</code>, retry-knobs (<code>max-retries</code>, <code>base-backoff</code>, <code>max-backoff</code>), <code>dry-run</code>, <code>verbose</code>, <code>quiet</code>, <code>user-agent</code>. Между «попробовал локально, всё работает» и «засунул в CI» нет шага «а как там оно в Action называется» — один и тот же набор имён.</p>
<p>Outputs тоже из коробки:</p>
<ul>
<li><code>exit-code</code> — финальный код выхода CLI (<code>0</code> / <code>1</code> / <code>2</code>);</li>
<li><code>submitted-count</code> — сколько URL ушло (суммарно по батчам);</li>
<li><code>failed-count</code> — сколько батчей завершились не-2xx или ошибкой;</li>
<li><code>report</code> — одностраничная сводка; параллельно она же пишется в <code>$GITHUB_STEP_SUMMARY</code>.</li>
</ul>
<p>Этими outputs удобно дёргать downstream-шаги: уронить алерт в Telegram, если <code>failed-count &gt; 0</code>; или, наоборот, проигнорировать падение submit, если ты ему не доверяешь и не хочешь, чтобы из-за этого падал весь pipeline. Полный референс и готовые рецепты — в <a href="https://jtprogru.github.io/indexnow/guides/github-action/" rel="noopener noreferrer" target="_blank">docs → GitHub Action</a>
.</p>
<h2 id="если-actions-не-вариант">Если Actions не вариант</h2>
<p>GitLab CI, Drone, Woodpecker, cron на VPS, локальный запуск перед публикацией поста — для всех этих кейсов есть тот же бинарь, ставится двумя способами:</p>
<div class="codeblock codeblock--bash" data-lang="bash"><span class="codeblock__lang" aria-hidden="true">bash</span><button class="codeblock__copy" type="button" data-copy aria-label="Скопировать" title="Скопировать"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">brew tap jtprogru/tap <span class="o">&amp;&amp;</span> brew install indexnow
</span></span><span class="line"><span class="cl"><span class="c1"># или</span>
</span></span><span class="line"><span class="cl">go install github.com/jtprogru/indexnow/cmd/indexnow@latest</span></span></code></pre></div>
</div>
<p>Готовые бинарники под Linux / macOS / FreeBSD в связках <code>amd64</code>/<code>arm64</code> лежат <a href="https://github.com/jtprogru/indexnow/releases" rel="noopener noreferrer" target="_blank">на странице релизов</a>
. И дальше тот же <code>submit</code>, только из шелла:</p>
<div class="codeblock codeblock--bash" data-lang="bash"><span class="codeblock__lang" aria-hidden="true">bash</span><button class="codeblock__copy" type="button" data-copy aria-label="Скопировать" title="Скопировать"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">INDEXNOW_KEY</span><span class="o">=</span>8f7e6d5c4b3a29180706050403020100
</span></span><span class="line"><span class="cl">indexnow submit <span class="se">\
</span></span></span><span class="line"><span class="cl">    --sitemap https://example.com/sitemap.xml <span class="se">\
</span></span></span><span class="line"><span class="cl">    --sitemap-since 2026-06-01T00:00:00Z</span></span></code></pre></div>
</div>
<p>Источник URL — на выбор:</p>
<ul>
<li>позиционные аргументы: <code>indexnow submit https://a https://b</code>;</li>
<li><code>--file urls.txt</code> (по одному URL на строку, <code>#</code> — комментарий);</li>
<li><code>--stdin</code> — типичный pipe из другого CLI (<code>sitemap-to-urls | indexnow submit --stdin</code>);</li>
<li><code>--sitemap</code> — URL или локальный путь к XML.</li>
</ul>
<p>С sitemap&rsquo;ом отдельная история: <code>&lt;sitemapindex&gt;</code> раскрывается рекурсивно (ходишь по всем дочерним), а <code>.gz</code>-варианты гунзипятся прозрачно — отдельный шаг с <code>gunzip</code> не нужен. На больших проектах с десятками сегментированных sitemap&rsquo;ов это здорово упрощает жизнь.</p>
<h2 id="что-cli-делает-за-тебя">Что CLI делает за тебя</h2>
<p>Если коротко — всё то, что обычно копится в скриптах вокруг такой задачи:</p>
<ul>
<li><strong>Ретраи 429/5xx и transport-ошибок</strong> с экспоненциальным backoff&rsquo;ом, jitter&rsquo;ом и уважением к заголовку <code>Retry-After</code> (понимает и секунды, и HTTP-date). Ретраи без backoff превращают деградацию в катастрофу — особенно если поисковик уже под нагрузкой.</li>
<li><strong>Резка батчей</strong> по лимиту протокола (10 000 URL на запрос). Не нужно думать, что делать, когда у тебя 25 000 урлов: CLI сам режет на три батча, по каждому идёт отдельный submit и отдельный результат в отчёте.</li>
<li><strong>Несколько эндпоинтов сразу</strong>: <code>--endpoint bing,yandex,naver</code>. Если ты по какой-то причине не доверяешь «один эндпоинт расшарит всем», передай список — CLI отправит в каждый и склеит результат.</li>
<li><strong>Внятные exit code</strong> (<code>0</code> — всё ок, <code>1</code> — submission failed по сети/HTTP/<code>fail-on</code>, <code>2</code> — usage error: кривые флаги, нет источника URL, нет ключа) и флаг <code>--fail-on any|4xx|5xx|never</code>. Например, на 429 ты можешь не хотеть падать (это не твоя проблема), а на 4xx по ключу — обязательно.</li>
<li><strong>Управление ключом</strong> через <code>indexnow key</code>: <code>key gen --write public/</code> генерит ключ и кладёт hosted-файл в нужную директорию, <code>key verify --host example.com --key $KEY</code> дёргает GET по hosted-файлу и сверяет содержимое.</li>
</ul>
<p><code>key verify</code> стоит гонять до первого submit — чтобы убедиться, что key-файл реально отдаётся не только тебе из браузера, но и поисковикам. Иначе все submit&rsquo;ы будут возвращать 403, а ты будешь чесать репу и читать changelog в поисках сломанного релиза.</p>
<h2 id="тонкие-места-на-которых-легко-споткнуться">Тонкие места, на которых легко споткнуться</h2>
<ul>
<li><strong><code>fetch-depth: 0</code> в <code>actions/checkout</code></strong>. Без полной истории <code>git diff</code> против <code>github.event.before</code> молча отдаст пустоту: shallow-клон не видит предыдущий коммит. Симптом — <code>submitted-count=0</code> на каждом пуше, и ты долго гадаешь, почему.</li>
<li><strong>Первый пуш в ветке.</strong> <code>github.event.before</code> там — нули (<code>0000000...</code>), <code>git diff 0000000..HEAD</code> сваливается с <code>fatal: bad revision</code>. Прикрой fallback&rsquo;ом на <code>HEAD~1</code>.</li>
<li><strong>CDN кеширует hosted key-файл.</strong> Cloudflare, Fastly и прочие радостно складывают <code>.txt</code> в кеш на пять-десять минут. Поменял ключ — поисковик в это окно ловит старую версию и отбивает 403 на твой свежий submit. После ротации — явный purge, без вариантов.</li>
<li><strong><code>&lt;lastmod&gt;</code> без timezone.</strong> <code>sitemap-since</code> ждёт RFC3339. Если Hugo (или чем ты там собираешь sitemap) пишет <code>2026-06-02T14:00:00</code> без <code>Z</code> и без смещения, фильтр поедет на таймзоне раннера: на GitHub-hosted это UTC, у себя на сервере — что настроил. Один и тот же sitemap начнёт давать разные срезы в зависимости от того, где крутится workflow.</li>
<li><strong>Параллельные эндпоинты ≠ страховка от лимитов.</strong> Отправил в <code>bing,yandex,naver</code> — формально получишь три ответа, но Bing всё равно поделится submission&rsquo;ом с остальными. Если поисковик отбил 429, лучше уменьшить частоту запусков, чем долбить параллельно во все доступные API.</li>
</ul>
<h2 id="где-взять-и-куда-нести-issue">Где взять и куда нести issue</h2>
<ul>
<li>Код, issues и звёздочки: <a href="https://github.com/jtprogru/indexnow" rel="noopener noreferrer" target="_blank">github.com/jtprogru/indexnow</a>
</li>
<li>Документация (EN + RU): <a href="https://jtprogru.github.io/indexnow/" rel="noopener noreferrer" target="_blank">jtprogru.github.io/indexnow</a>
</li>
<li>Гайд по GitHub Action: <a href="https://jtprogru.github.io/indexnow/guides/github-action/" rel="noopener noreferrer" target="_blank">jtprogru.github.io/indexnow/guides/github-action/</a>
</li>
</ul>
<p>Если интегрируешь — поделись опытом в issues или прямо в комментариях. Особенно интересны истории про GitLab/Drone: под GitHub Action у меня самые подробные тесты, а на других CI оно проверяется реже.</p>
<p>PS: расскажи, как у тебя сейчас устроена индексация — Search Console + ручной запрос, sitemap-only, или что-то более хитрое? И насколько вообще IndexNow дал прирост по скорости индексации? Хочется собрать чуть более широкие данные, чем у меня одного.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></description>
      <content:encoded><![CDATA[<style>/* Inline-CSS, который тема вкладывает в <description> каждого item'а
   RSS-фида (layouts/index.rss.xml). RSS-ридеры (Feedly, Inoreader,
   NetNewsWire) уважают <style> внутри description с переменной
   степенью энтузиазма — это базовый fallback, достаточный для читаемой
   типографики, не более.

   Цвета продублированы из 00-vars.css (light-палитра) — поправь
   синхронно при изменении --bg / --text / --accent / --border. */

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  line-height: 1.6;
  color: #1c1c1f;
  max-width: 720px;
  margin: 0 auto;
  padding: 1em;
}
h1, h2, h3 { line-height: 1.25; margin-top: 1.4em; }
a { color: #c2410c; }
pre {
  background: #1e1e24;
  color: #e8e6df;
  padding: 1em;
  border-radius: 6px;
  overflow-x: auto;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.9em;
}
code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  background: #f3f1ed;
  padding: 0.1em 0.4em;
  border-radius: 4px;
}
pre code { background: transparent; padding: 0; }
blockquote {
  border-left: 3px solid #c2410c;
  padding-left: 1em;
  color: #5b5b62;
  font-style: italic;
  margin-left: 0;
}
img { max-width: 100%; height: auto; border-radius: 6px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #e5e3dc; padding: 6px 10px; text-align: left; }
</style><div><p>Привет, <code>%username%</code>! Выкатил новый пост, поправил страницу, обновил title — и сидишь, ждёшь, пока поисковики соизволят переобойти сайт. День, два, неделя. А хочется, чтобы апдейт подхватился сразу после <code>git push</code>, без танцев с Search Console и ручных submission-форм.</p>
<p>Дальше — как закрыть эту боль одним шагом в GitHub Actions через мой CLI <a href="https://github.com/jtprogru/indexnow" rel="noopener noreferrer" target="_blank">indexnow</a>
 и почему оно вообще работает.</p>
<h2 id="что-такое-indexnow-и-зачем-он-нужен">Что такое IndexNow и зачем он нужен</h2>
<p>Протокол <a href="https://www.indexnow.org/documentation" rel="noopener noreferrer" target="_blank">IndexNow</a>
 — это простой способ сказать поисковику: «эти URL изменились, переобойди их побыстрее, пожалуйста». Ты делаешь один HTTP-запрос с ключом и списком URL, поисковик в ответ подтверждает приём (или отбивает с осмысленной ошибкой) — и дальше уже его проблема, когда именно он переобойдёт страницы.</p>
<p>Главное: <strong>submission автоматически шарится между всеми участниками протокола</strong>. По спеке достаточно дёрнуть <strong>один</strong> эндпоинт (например, <code>api.indexnow.org</code> или <code>bing.com/indexnow</code>), и тот же запрос провалидируется и расшарится со всеми: Bing, Yandex, Naver, Seznam, Yep и другие участники. Google к протоколу формально не присоединился — для него по-прежнему остаётся sitemap + Search Console.</p>
<p>Аутентификация — самая «забавная» часть протокола. Ты придумываешь ключ (произвольная hex-строка длиной 8–128 символов), хостишь его в виде текстового файла на собственном домене, например <code>https://example.com/&lt;key&gt;.txt</code>, и присылаешь этот ключ в каждом запросе. Поисковик идёт по URL, читает файл, сверяет содержимое с тем ключом, что ты прислал. Совпало — submission принят. Нет — 403. Просто и без OAuth.</p>
<p>И тут же — мой любимый перл из <a href="https://yandex.ru/support/webmaster/ru/indexnow/key" rel="noopener noreferrer" target="_blank">документации Яндекс.Вебмастера</a>
: «Ключ менять необязательно. Вы можете изменить ключ, если он стал известен третьим лицам.» То есть ключ, который ты по спеке обязан выложить публичным <code>.txt</code> на свой домен и который любой может вытащить одним <code>curl</code>, Яндекс предлагает ротировать, если он «стал известен третьим лицам». А он по дизайну протокола известен им всегда. Ну камон.</p>
<h2 id="зачем-я-написал-свой-cli">Зачем я написал свой CLI</h2>
<p>Дёргать API руками лениво, особенно когда у тебя на пуш приходится 10–50 изменившихся URL и хочется делать это из CI. Можно, конечно, нагуглить готовый пример с <code>curl</code> и <code>jq</code>, но:</p>
<ul>
<li>ошибки разбирать в bash больно;</li>
<li>ретраи на 429/5xx писать руками лень;</li>
<li>sitemap парсить из XML в bash — отдельный жанр перформанса;</li>
<li>лимит протокола в 10 000 URL на запрос тоже надо учитывать.</li>
</ul>
<p>Поэтому я написал на <a href="/want-coding-golang/">Go</a>
 маленький <code>indexnow</code> — сначала как CLI для разовых submission&rsquo;ов, а с релиза <code>v0.5.0</code> это уже и <strong>готовый GitHub Action</strong>. По дороге всё то, что обычно копится в самописных скриптах, я аккуратно унёс внутрь бинаря.</p>
<p>Заодно это стало хорошим pet-project&rsquo;ом: тесты с <code>-race</code>, <code>golangci-lint</code>, <code>mkdocs</code> для документации, релизы через <code>goreleaser</code>, а теперь и composite Action с верификацией бинарей. Маленький инструмент, который и время экономит, и руки в форме держит.</p>
<h2 id="минимальный-шаг-в-github-actions">Минимальный шаг в GitHub Actions</h2>
<p>Самый короткий путь — взять готовый Action и засунуть один шаг в workflow:</p>
<div class="codeblock codeblock--yaml" data-lang="yaml"><span class="codeblock__lang" aria-hidden="true">yaml</span><button class="codeblock__copy" type="button" data-copy aria-label="Скопировать" title="Скопировать"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">jtprogru/indexnow@v0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">with</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.INDEXNOW_KEY }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">sitemap</span><span class="p">:</span><span class="w"> </span><span class="l">https://example.com/sitemap.xml</span></span></span></code></pre></div>
</div>
<p>Всё. Этот шаг сам:</p>
<ul>
<li>определит ОС и архитектуру раннера (<code>linux/amd64</code>, <code>linux/arm64</code>, <code>darwin/arm64</code>, …);</li>
<li>скачает релизный бинарь нужной сборки со страницы релизов;</li>
<li>сверит его <code>sha256</code> с <code>checksums.txt</code>, который лежит рядом с бинарями в релизе — это защищает от «а что если кто-то подменил артефакт»;</li>
<li>закэширует бинарь в <code>runner.tool_cache</code>, чтобы следующие раны не качали его повторно;</li>
<li>запустит <code>indexnow submit</code> с переданными параметрами.</li>
</ul>
<p>Ключ передаётся через <code>env</code>, а не флагом, — даже если в твоём шаге случайно отрабатывает <code>set -x</code>, ключ в логах не светится. В <code>$GITHUB_STEP_SUMMARY</code> после прогона падает короткий отчёт: сколько URL улетело, сколько батчей упало, куда отправлял. Не нужно лезть в полный лог раннера, чтобы понять, прошёл submit или нет.</p>
<h2 id="submit-только-тех-url-что-изменились">Submit только тех URL, что изменились</h2>
<p>Слать весь sitemap при каждом пуше расточительно: поисковики переобойдут страницы и без тебя, IndexNow используешь именно для тех апдейтов, что важны прямо сейчас. Поэтому мой любимый рецепт — submit ровно того, что изменилось между предыдущим и текущим коммитом:</p>
<div class="codeblock codeblock--yaml" data-lang="yaml"><span class="codeblock__lang" aria-hidden="true">yaml</span><button class="codeblock__copy" type="button" data-copy aria-label="Скопировать" title="Скопировать"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">jtprogru/indexnow@v0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">with</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.INDEXNOW_KEY }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">sitemap</span><span class="p">:</span><span class="w"> </span><span class="l">https://example.com/sitemap.xml</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">sitemap-since</span><span class="p">:</span><span class="w"> </span><span class="l">${{ github.event.before }}</span></span></span></code></pre></div>
</div>
<p><code>sitemap-since</code> фильтрует записи sitemap по <code>&lt;lastmod&gt;</code>: всё, что старее переданного времени, отбрасывается.</p>
<p>Один граничный случай, который я заложил по умолчанию: <strong>записи без <code>&lt;lastmod&gt;</code> всегда проходят</strong>. «Нет сигнала о времени» трактуется как «могло измениться», и для IndexNow это безопасный дефолт — повторный submit идемпотентен, лишний раз дёрнуть не страшно. Куда хуже промолчать про реально изменившуюся страницу.</p>
<h2 id="а-если-sitemapу-не-доверяешь--urls-from">А если sitemap&rsquo;у не доверяешь — <code>urls-from</code></h2>
<p><code>sitemap-since</code> хорош, когда <code>&lt;lastmod&gt;</code> у тебя действительно проставляется. Если нет (или ты не хочешь полагаться на свежесть sitemap&rsquo;а вообще) — есть второй рецепт: собрать список URL из <code>git diff</code> между двумя коммитами и скормить его в Action через <code>urls-from</code>.</p>
<div class="codeblock codeblock--yaml" data-lang="yaml"><span class="codeblock__lang" aria-hidden="true">yaml</span><button class="codeblock__copy" type="button" data-copy aria-label="Скопировать" title="Скопировать"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/checkout@v6</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">with</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">fetch-depth</span><span class="p">:</span><span class="w"> </span><span class="m">0</span><span class="w">
</span></span></span><span class="line"><span class="cl">- <span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">jtprogru/indexnow@v0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">with</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.INDEXNOW_KEY }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">urls-from</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">      git diff --name-only &#34;${{ github.event.before }}..HEAD&#34; -- &#39;content/**/*.md&#39; |
</span></span></span><span class="line"><span class="cl"><span class="sd">        sed &#39;s#^content/\(.*\)/index\.md$#https://jtprog.ru/\1/#&#39;</span></span></span></code></pre></div>
</div>
<p><code>urls-from</code> — это просто bash-сниппет, чей stdout (по одной строке на URL) превращается в источник URL. Сниппет крутится в <code>$GITHUB_WORKSPACE</code>, так что <code>git</code> видит весь checked-out репозиторий и <code>git diff</code> работает как обычно. Пустой вывод — это не ошибка, шаг тихо выйдет с <code>submitted-count=0</code>.</p>
<p>Вот тот самый маппинг: <code>content/&lt;slug&gt;/index.md</code> → <code>https://jtprog.ru/&lt;slug&gt;/</code>. Никакого парсинга sitemap, никаких лишних submission&rsquo;ов на страницы, которые не трогал. <code>fetch-depth: 0</code> обязательно — без полной истории <code>git diff</code> против <code>github.event.before</code> молча отдаст пустоту.</p>
<h2 id="тег-v0-и-плавающие-версии">Тег <code>@v0</code> и плавающие версии</h2>
<p>Одна из мелких, но важных деталей — модель версионирования.</p>
<ul>
<li><code>@v0.7.0</code> — конкретный релиз. Поведение зафиксировано, обновления только если ты сам поправишь workflow.</li>
<li><code>@v0.7</code> — все патчи внутри <code>0.7.x</code>, обновляется автоматически.</li>
<li><code>@v0</code> — все релизы внутри <code>0.x</code>, едет с каждым новым минором.</li>
</ul>
<p>Плавающие теги (<code>v0</code>, <code>v0.5</code>) переставляются отдельным workflow на каждый релиз <code>v0.Y.Z</code>. То есть подписался один раз на <code>@v0</code> — и едешь на последнем <code>0.x</code> без правок workflow. Когда выкачу <code>v1.0.0</code>, тег <code>@v0</code> останется на последнем релизе ветки <code>0.x</code>: ты сам решаешь, переезжать ли на мажор. Никаких сюрпризов в духе «обновился — поведение сломалось».</p>
<h2 id="inputs-outputs-и-downstream-шаги">Inputs, outputs и downstream-шаги</h2>
<p>Inputs Action&rsquo;а зеркалят флаги CLI: источники URL (<code>urls</code> / <code>file</code> / <code>sitemap</code> / <code>urls-from</code>), <code>sitemap-since</code>, <code>endpoint</code>, <code>host</code>, <code>key-location</code>, <code>fail-on</code>, retry-knobs (<code>max-retries</code>, <code>base-backoff</code>, <code>max-backoff</code>), <code>dry-run</code>, <code>verbose</code>, <code>quiet</code>, <code>user-agent</code>. Между «попробовал локально, всё работает» и «засунул в CI» нет шага «а как там оно в Action называется» — один и тот же набор имён.</p>
<p>Outputs тоже из коробки:</p>
<ul>
<li><code>exit-code</code> — финальный код выхода CLI (<code>0</code> / <code>1</code> / <code>2</code>);</li>
<li><code>submitted-count</code> — сколько URL ушло (суммарно по батчам);</li>
<li><code>failed-count</code> — сколько батчей завершились не-2xx или ошибкой;</li>
<li><code>report</code> — одностраничная сводка; параллельно она же пишется в <code>$GITHUB_STEP_SUMMARY</code>.</li>
</ul>
<p>Этими outputs удобно дёргать downstream-шаги: уронить алерт в Telegram, если <code>failed-count &gt; 0</code>; или, наоборот, проигнорировать падение submit, если ты ему не доверяешь и не хочешь, чтобы из-за этого падал весь pipeline. Полный референс и готовые рецепты — в <a href="https://jtprogru.github.io/indexnow/guides/github-action/" rel="noopener noreferrer" target="_blank">docs → GitHub Action</a>
.</p>
<h2 id="если-actions-не-вариант">Если Actions не вариант</h2>
<p>GitLab CI, Drone, Woodpecker, cron на VPS, локальный запуск перед публикацией поста — для всех этих кейсов есть тот же бинарь, ставится двумя способами:</p>
<div class="codeblock codeblock--bash" data-lang="bash"><span class="codeblock__lang" aria-hidden="true">bash</span><button class="codeblock__copy" type="button" data-copy aria-label="Скопировать" title="Скопировать"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">brew tap jtprogru/tap <span class="o">&amp;&amp;</span> brew install indexnow
</span></span><span class="line"><span class="cl"><span class="c1"># или</span>
</span></span><span class="line"><span class="cl">go install github.com/jtprogru/indexnow/cmd/indexnow@latest</span></span></code></pre></div>
</div>
<p>Готовые бинарники под Linux / macOS / FreeBSD в связках <code>amd64</code>/<code>arm64</code> лежат <a href="https://github.com/jtprogru/indexnow/releases" rel="noopener noreferrer" target="_blank">на странице релизов</a>
. И дальше тот же <code>submit</code>, только из шелла:</p>
<div class="codeblock codeblock--bash" data-lang="bash"><span class="codeblock__lang" aria-hidden="true">bash</span><button class="codeblock__copy" type="button" data-copy aria-label="Скопировать" title="Скопировать"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">INDEXNOW_KEY</span><span class="o">=</span>8f7e6d5c4b3a29180706050403020100
</span></span><span class="line"><span class="cl">indexnow submit <span class="se">\
</span></span></span><span class="line"><span class="cl">    --sitemap https://example.com/sitemap.xml <span class="se">\
</span></span></span><span class="line"><span class="cl">    --sitemap-since 2026-06-01T00:00:00Z</span></span></code></pre></div>
</div>
<p>Источник URL — на выбор:</p>
<ul>
<li>позиционные аргументы: <code>indexnow submit https://a https://b</code>;</li>
<li><code>--file urls.txt</code> (по одному URL на строку, <code>#</code> — комментарий);</li>
<li><code>--stdin</code> — типичный pipe из другого CLI (<code>sitemap-to-urls | indexnow submit --stdin</code>);</li>
<li><code>--sitemap</code> — URL или локальный путь к XML.</li>
</ul>
<p>С sitemap&rsquo;ом отдельная история: <code>&lt;sitemapindex&gt;</code> раскрывается рекурсивно (ходишь по всем дочерним), а <code>.gz</code>-варианты гунзипятся прозрачно — отдельный шаг с <code>gunzip</code> не нужен. На больших проектах с десятками сегментированных sitemap&rsquo;ов это здорово упрощает жизнь.</p>
<h2 id="что-cli-делает-за-тебя">Что CLI делает за тебя</h2>
<p>Если коротко — всё то, что обычно копится в скриптах вокруг такой задачи:</p>
<ul>
<li><strong>Ретраи 429/5xx и transport-ошибок</strong> с экспоненциальным backoff&rsquo;ом, jitter&rsquo;ом и уважением к заголовку <code>Retry-After</code> (понимает и секунды, и HTTP-date). Ретраи без backoff превращают деградацию в катастрофу — особенно если поисковик уже под нагрузкой.</li>
<li><strong>Резка батчей</strong> по лимиту протокола (10 000 URL на запрос). Не нужно думать, что делать, когда у тебя 25 000 урлов: CLI сам режет на три батча, по каждому идёт отдельный submit и отдельный результат в отчёте.</li>
<li><strong>Несколько эндпоинтов сразу</strong>: <code>--endpoint bing,yandex,naver</code>. Если ты по какой-то причине не доверяешь «один эндпоинт расшарит всем», передай список — CLI отправит в каждый и склеит результат.</li>
<li><strong>Внятные exit code</strong> (<code>0</code> — всё ок, <code>1</code> — submission failed по сети/HTTP/<code>fail-on</code>, <code>2</code> — usage error: кривые флаги, нет источника URL, нет ключа) и флаг <code>--fail-on any|4xx|5xx|never</code>. Например, на 429 ты можешь не хотеть падать (это не твоя проблема), а на 4xx по ключу — обязательно.</li>
<li><strong>Управление ключом</strong> через <code>indexnow key</code>: <code>key gen --write public/</code> генерит ключ и кладёт hosted-файл в нужную директорию, <code>key verify --host example.com --key $KEY</code> дёргает GET по hosted-файлу и сверяет содержимое.</li>
</ul>
<p><code>key verify</code> стоит гонять до первого submit — чтобы убедиться, что key-файл реально отдаётся не только тебе из браузера, но и поисковикам. Иначе все submit&rsquo;ы будут возвращать 403, а ты будешь чесать репу и читать changelog в поисках сломанного релиза.</p>
<h2 id="тонкие-места-на-которых-легко-споткнуться">Тонкие места, на которых легко споткнуться</h2>
<ul>
<li><strong><code>fetch-depth: 0</code> в <code>actions/checkout</code></strong>. Без полной истории <code>git diff</code> против <code>github.event.before</code> молча отдаст пустоту: shallow-клон не видит предыдущий коммит. Симптом — <code>submitted-count=0</code> на каждом пуше, и ты долго гадаешь, почему.</li>
<li><strong>Первый пуш в ветке.</strong> <code>github.event.before</code> там — нули (<code>0000000...</code>), <code>git diff 0000000..HEAD</code> сваливается с <code>fatal: bad revision</code>. Прикрой fallback&rsquo;ом на <code>HEAD~1</code>.</li>
<li><strong>CDN кеширует hosted key-файл.</strong> Cloudflare, Fastly и прочие радостно складывают <code>.txt</code> в кеш на пять-десять минут. Поменял ключ — поисковик в это окно ловит старую версию и отбивает 403 на твой свежий submit. После ротации — явный purge, без вариантов.</li>
<li><strong><code>&lt;lastmod&gt;</code> без timezone.</strong> <code>sitemap-since</code> ждёт RFC3339. Если Hugo (или чем ты там собираешь sitemap) пишет <code>2026-06-02T14:00:00</code> без <code>Z</code> и без смещения, фильтр поедет на таймзоне раннера: на GitHub-hosted это UTC, у себя на сервере — что настроил. Один и тот же sitemap начнёт давать разные срезы в зависимости от того, где крутится workflow.</li>
<li><strong>Параллельные эндпоинты ≠ страховка от лимитов.</strong> Отправил в <code>bing,yandex,naver</code> — формально получишь три ответа, но Bing всё равно поделится submission&rsquo;ом с остальными. Если поисковик отбил 429, лучше уменьшить частоту запусков, чем долбить параллельно во все доступные API.</li>
</ul>
<h2 id="где-взять-и-куда-нести-issue">Где взять и куда нести issue</h2>
<ul>
<li>Код, issues и звёздочки: <a href="https://github.com/jtprogru/indexnow" rel="noopener noreferrer" target="_blank">github.com/jtprogru/indexnow</a>
</li>
<li>Документация (EN + RU): <a href="https://jtprogru.github.io/indexnow/" rel="noopener noreferrer" target="_blank">jtprogru.github.io/indexnow</a>
</li>
<li>Гайд по GitHub Action: <a href="https://jtprogru.github.io/indexnow/guides/github-action/" rel="noopener noreferrer" target="_blank">jtprogru.github.io/indexnow/guides/github-action/</a>
</li>
</ul>
<p>Если интегрируешь — поделись опытом в issues или прямо в комментариях. Особенно интересны истории про GitLab/Drone: под GitHub Action у меня самые подробные тесты, а на других CI оно проверяется реже.</p>
<p>PS: расскажи, как у тебя сейчас устроена индексация — Search Console + ручной запрос, sitemap-only, или что-то более хитрое? И насколько вообще IndexNow дал прирост по скорости индексации? Хочется собрать чуть более широкие данные, чем у меня одного.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></content:encoded>
    </item><item>
      <title>Надёжность строится в диалоге с бизнесом</title>
      <link>https://jtprog.ru/posts/reliability-is-a-conversation/</link>
      <pubDate>Thu, 28 May 2026 20:08:56 +0300</pubDate>
      <dc:creator>jtprogru</dc:creator>
      <guid isPermaLink="true">https://jtprog.ru/posts/reliability-is-a-conversation/</guid>
      <category>SRE</category>
      <category>SLO</category>
      <category>Error Budget</category>
      <category>System Design</category>
      <category>Надёжность</category>
      <category domain="category">SRE</category>
      <enclosure url="https://jtprog.ru/cover.svg" type="image/jpeg" length="0" />
      <media:thumbnail url="https://jtprog.ru/cover.svg" /><description><![CDATA[<div><p>Привет, <code>%username%</code>! В прошлой статье — <a href="/posts/slo-as-architecture-blueprint/">«SLO как чертёж архитектуры»</a>
 — я закончил тезисом, который тут же хочется развить: SLO выбирается не инженерами в одиночку, а вместе с бизнесом, потому что число в нём привязано к деньгам. А «вместе с бизнесом» в реальности чаще всего выглядит так: SRE придумал SLO, нарисовал дашборд, показал на демо, продакт покивал — и все разошлись. Чертёж готов. Надёжность&hellip; не выросла.</p>
<p>Так бывает, потому что чертёж сам по себе не работает. SLO/SLI/error budget — это <strong>не отчётный артефакт, а язык переговоров</strong>. Технический инструмент превращается в управленческий ровно в тот момент, когда у инженеров и у бизнеса одна и та же картинка целевой надёжности и одна и та же валюта компромиссов. Пока этого нет — у тебя есть красивый график, который никто не использует для принятия решений.</p>
<p>В этой статье я разворачиваю три практических следствия из этого тезиса, и все три — продолжение того же кейса с маркетплейсом (поиск каталога, 50M товаров, 30k RPS на пике), который я гонял в «чертеже»:</p>
<ol>
<li><strong>Диалог с бизнесом — это не презентация SLO, а формат принятия решений.</strong> SRE не «продаёт» таргет продакту, а вместе с ним выбирает уровень надёжности, политику бюджета ошибок и порядок разрешения спора «фичи против надёжности».</li>
<li><strong>System Design-собес проверяет именно этот навык.</strong> Большинство «вопросов по SLO» — не про арифметику девяток, а про умение собрать разговор с бизнесом, удержать рамку трейд-оффов и перевести «бизнес хочет 100%» в инженерную работу.</li>
<li><strong>Метрики SRE-команды меняются, когда продуктов больше одного.</strong> Ни «MTTR по компании», ни «SLO по сервису» как метрика команды не работают, когда команда обслуживает 5–10 продуктов. Нужен сводный язык.</li>
</ol>
<p>Если первая статья была про то, <strong>какой</strong> чертёж рисовать, то эта — про то, <strong>как сделать так, чтобы по чертежу действительно построили</strong>, а не повесили его в рамке на стену.</p>
<h2 id="что-ты-унесёшь-из-статьи">Что ты унесёшь из статьи</h2>
<p>Статья длинная (~40 000 знаков). Сразу — что заберёт каждая роль:</p>
<ul>
<li><strong>SRE / SRE-lead.</strong> Как перестать «отдавать SLO» и начать вести по нему диалог: три признака, что разговор не состоялся; error budget policy как продуктовый, а не инженерный артефакт; и — отдельным блоком — какие метрики брать на команду, когда продуктов много, чтобы они не врали.</li>
<li><strong>Продакт / аналитик.</strong> Что именно бизнес должен уметь произнести сам (а не получать от SRE как откровение): где у нас критичные пользовательские пути, сколько стоит девятка в деньгах, кто и когда жмёт на стоп.</li>
<li><strong>Кандидат / интервьюер на System Design.</strong> Пять типовых собес-кейсов «про SLO», которые на самом деле проверяют переговорный навык, и разбор, что в них считается сильным ответом, а что — провалом.</li>
</ul>
<p>Общий блок для всех: почему <strong>надёжность нельзя «сделать», её можно только постоянно переторговывать</strong> — и как выглядит этот процесс в зрелой команде.</p>
<h2 id="tldr-если-читать-дальше-уже-некогда">TL;DR (если читать дальше уже некогда)</h2>
<p>Четыре тезиса, к которым приходит статья:</p>
<ol>
<li><strong>SLO без error budget policy — это украшение дашборда.</strong> Контракт из SLO делает записанное правило: что происходит, когда бюджет сгорел, и кто принимает по этому поводу решение. Само число ничего не гарантирует. Без правила — это график, мимо которого все ходят.</li>
<li><strong>Надёжность — это не состояние, а переговорный процесс.</strong> Её не «достигают» один раз. Каждый квартал бизнес и SRE заново выбирают уровень, потому что меняются нагрузка, деньги и приоритеты. SLO, который не пересматривают, врёт уже через полгода.</li>
<li><strong>На собесе по SLO проверяют не формулы, а умение поменять поведение бизнеса.</strong> Сильный ответ всегда начинается со сценария и денег, а не с топологии и девяток. «100% доступности» — не повод сказать «нельзя», а повод показать цену.</li>
<li><strong>Метрики SRE-команды при мультипродукте раскладываются на три слоя</strong> (надёжность продуктов / инженерное усилие / качество диалога) — один агрегат тут не справляется. Среднее по больнице — MTTR, composite SLO, число инцидентов — прячет ровно то, ради чего метрику заводили.</li>
</ol>
<p>Дальше — как до этого дойти. Если интересует только управленческая кульминация — переходи сразу к разделу <a href="#%d0%bc%d0%b5%d1%82%d1%80%d0%b8%d0%ba%d0%b8-sre-%d0%ba%d0%be%d0%bc%d0%b0%d0%bd%d0%b4%d1%8b-%d0%b4%d0%bb%d1%8f-%d0%bc%d1%83%d0%bb%d1%8c%d1%82%d0%b8%d0%bf%d1%80%d0%be%d0%b4%d1%83%d0%ba%d1%82%d0%b0">Метрики SRE-команды для мультипродукта</a>
.</p>
<h2 id="чертёж-без-переговоров--это-просто-дашборд">Чертёж без переговоров — это просто дашборд</h2>
<p>Начнём с диагноза. В прошлой статье SLO получился как инженерный объект: числитель, знаменатель, окно, бюджет ошибок. Всё аккуратно. Но у этого объекта есть два режима существования, и разница между ними — это и есть вся статья.</p>
<h3 id="slo-как-артефакт-против-slo-как-контракта">SLO как артефакт против SLO как контракта</h3>
<p><strong>SLO-артефакт</strong> — это число на дашборде. Его придумали, согласовали галочкой, поставили мониторинг, иногда даже сделали красивый burn-rate-график. Он существует. Он измеряется. И он ни на что не влияет, потому что ни одно решение в компании не принимается, глядя на него.</p>
<p><strong>SLO-контракт</strong> — это то же число, но вокруг него выстроен процесс. Когда бюджет ошибок тает быстрее плана — кто-то останавливает рискованные деплои. Когда бюджет сгорел — спринт переключается на надёжность, и это не подвиг отдельного SRE, а записанное правило. Когда продакт хочет выкатить фичу к Чёрной пятнице — он сам спрашивает «сколько у нас осталось бюджета», потому что знает, что это его валюта тоже.</p>
<p>Разница видна по тому, как объект ведёт себя в жизни команды:</p>
<table>
  <thead>
      <tr>
          <th></th>
          <th>SLO-артефакт</th>
          <th>SLO-контракт</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Где живёт</td>
          <td>На дашборде</td>
          <td>В процессе принятия решений</td>
      </tr>
      <tr>
          <td>Кто смотрит</td>
          <td>Дежурный SRE</td>
          <td>Продакт и SRE вместе</td>
      </tr>
      <tr>
          <td>Что происходит при сгорании</td>
          <td>Ничего («ну красный»)</td>
          <td>Срабатывает записанное правило</td>
      </tr>
      <tr>
          <td>Кто «владелец» числа</td>
          <td>Инженеры</td>
          <td>Продуктовый владелец + SRE</td>
      </tr>
      <tr>
          <td>Роль в споре «фича vs надёжность»</td>
          <td>Никакой</td>
          <td>Валюта, в которой спор решается</td>
      </tr>
      <tr>
          <td>Пересмотр</td>
          <td>Когда вспомнят</td>
          <td>Раз в квартал, ритуалом</td>
      </tr>
  </tbody>
</table>
<p>Разница между ними — не в качестве дашборда. Она в том, <strong>встроен ли SLO в принятие решений</strong>. И встроить его туда нельзя в одностороннем порядке: SRE не может «назначить» бизнесу, что теперь решения принимаются по бюджету ошибок. Это можно только договорить.</p>
<aside class="callout callout--note" role="note">
  <div class="callout__icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg></div>
  <div class="callout__body"><p class="callout__title">Главная подмена</p>
    <div class="callout__content"><p>«Мы внедрили SLO» почти всегда означает «мы настроили SLI и нарисовали дашборд». Это внедрение <strong>артефакта</strong>. Внедрение <strong>контракта</strong> — это когда на вопрос «что у нас происходит при сгорании бюджета» отвечает не SRE, а продакт, и отвечает одинаково с SRE. Пока ответы расходятся — контракта нет, есть график.</p></div>
  </div>
</aside><h3 id="три-признака-что-разговор-не-состоялся">Три признака, что разговор не состоялся</h3>
<p>Проверить, в каком режиме у тебя SLO, можно по трём симптомам. Если узнаёшь хотя бы один — диалога не было, был монолог SRE.</p>
<ol>
<li><strong>SLO «спущен сверху».</strong> Инженеры посчитали девятки, выбрали таргет «по аналогии с большими» и поставили продакта перед фактом. Продакт не участвовал в выборе числа — значит, он не считает его своим и не будет на него опираться в спорах. Для него это «инженерная штука», а не общий контракт.</li>
<li><strong>Нет error budget policy.</strong> SLO есть, бюджет считается, дашборд горит то зелёным, то красным. Но что конкретно делать, когда бюджет на исходе — нигде не записано. В итоге красный дашборд не меняет ничего: «ну красный, ну ладно, катим дальше».</li>
<li><strong>На пересечении бюджета никто не останавливает фичи.</strong> Самый жёсткий признак. Бюджет сгорел в ноль, а релизы продолжают выкатываться, потому что «дедлайн важнее». Это значит, что SLO проигрывает любому продуктовому приоритету — то есть фактически его нет.</li>
</ol>
<p>Все три признака — про одно: <strong>SLO не имеет оперативных последствий</strong>. А инструмент без последствий — это декорация.</p>
<h3 id="кейс-mercari-переименовать-мало-нужен-ритуал">Кейс Mercari: переименовать мало, нужен ритуал</h3>
<p>Хороший пример того, как легко перепутать артефакт с контрактом, — переход к User Journey SLO. Команды (в том числе Mercari, описавшие это в посте <a href="https://engineering.mercari.com/en/blog/entry/20241204-keeping-user-journey-slos-up-to-date-with-e2e-testing-in-a-microservices-architecture/" rel="noopener noreferrer" target="_blank">«Keeping User Journey SLOs Up-to-Date with E2E Testing»</a>
 в декабре 2024 года) приходят к тому, что SLO «на сервис» прячет пользовательскую боль, и переезжают на SLO, привязанные к пользовательскому пути. Идея правильная — она ровно из «чертежа»: SLI вешаются на шаги критичного пути, а не на сервис целиком.</p>
<p>Но вот ловушка: само по себе переименование «SLO сервиса X» → «SLO пользовательского пути Y» ничего не меняет, если за ним не стоит <strong>сопровождающий ритуал с продактом</strong>. Если User Journey SLO живёт там же, где жил старый — на дашборде, который смотрит только дежурный SRE, — это просто более точный артефакт. Та же декорация, только лучше нарисованная.</p>
<p>Работает переход тогда, когда вместе с новым SLO появляется регулярная встреча, на которой продакт смотрит на бюджет своего пути и принимает по нему решения. Не SRE показывает — продакт смотрит и решает. Переименование — это 10% работы. Остальные 90% — встроить новый объект в процесс продукта.</p>
<h3 id="почему-без-продуктового-владельца-это-не-лечится">Почему без продуктового владельца это не лечится</h3>
<p>Здесь стоит развести два понятия — <strong>продуктовую надёжность</strong> (видит ли пользователь, что сценарий работает) и <strong>техническую доступность</strong> (отвечает ли ручка <code>/search</code> двухсоткой). Важное следствие из этого разведения: продуктовая надёжность по определению не может принадлежать только SRE.</p>
<p>SRE владеет технической доступностью — это его зона: инфраструктура, репликация, failover, capacity. Но «работает ли поиск для пользователя так, что он покупает» — это вопрос, на который SRE физически не может ответить в одиночку, потому что «так, что он покупает» — это продуктовое определение, а не техническое. Кто решает, что пустая выдача по валидному запросу — это провал, а не «технически 200 OK»? Продакт. Кто решает, что цена на карточке старше минуты — это инцидент? Продакт.</p>
<p>Поэтому <strong>у продуктовой надёжности должен быть продуктовый владелец</strong>. Не «SRE отвечает за надёжность» — это и есть корень всех проблем из предыдущего раздела. А «SRE отвечает за инструментарий и техническую доступность, продакт — за то, что считается надёжностью с точки зрения пользователя, и они держат общий SLO». Диалог не состоится, пока с продуктовой стороны нет того, кто за этот SLO отвечает головой.</p>
<h2 id="что-мы-на-самом-деле-обсуждаем-с-бизнесом">Что мы на самом деле обсуждаем с бизнесом</h2>
<p>Допустим, продуктовый владелец есть и готов разговаривать. О чём конкретно идёт разговор? Не «покажи мне дашборд» — это не разговор. Настоящий диалог о надёжности крутится вокруг четырёх вещей.</p>
<h3 id="1-таргет-как-бюджет-на-компромисс">1. Таргет как бюджет на компромисс</h3>
<p>Главное, что должен понять бизнес: <strong>высокая надёжность — это не бесплатно и не всегда хорошо</strong>. Это позиция на шкале трейд-оффов.</p>
<ul>
<li>Высокий SLO = низкая скорость фич (бюджет ошибок мал, каждый релиз — ставка), дорогая инфраструктура (резервирование, регионы), медленные релизы (канарейка, постепенный rollout).</li>
<li>Низкий SLO = быстрые фичи, дешёвая инфраструктура, но больше видимых пользователю сбоев.</li>
</ul>
<p>Из «чертежа» помним конкретные множители для нашего маркетплейса: переход с 99.9% на 99.99% — это <code>4–6×</code> → <code>15–25×</code> baseline по инфраструктуре и <code>2–3×</code> → <code>8–10×</code> по людям. Это не «инженеры хотят красивую цифру». Это бизнес-решение, потому что платит за него бизнес, и отказывается от скорости фич — тоже бизнес.</p>
<p>Ключевая фраза, которую SRE должен уметь произнести в этом разговоре, звучит примерно так:</p>
<blockquote><p>«Если снизим SLO поиска с 99.99% до 99.9% — освободим вот этот регион и вот эту часть дежурной нагрузки, сможем катить фичи в полтора раза быстрее. Заплатим за это вот таким ростом видимых сбоев на пике. Берём?»</p>
</blockquote><p>Это и есть перевод надёжности в валюту, понятную обеим сторонам. Не «давайте сделаем понадёжнее», а «вот цена, вот что освобождается, решаем вместе».</p>
<h3 id="2-error-budget-policy-правила-пишутся-до-пожара-а-не-во-время">2. Error budget policy: правила пишутся до пожара, а не во время</h3>
<p>Error budget policy — это <strong>заранее зафиксированные правила игры</strong>. Не «что мы будем делать, когда бюджет сгорит» (это решается в панике и проигрывается дедлайну), а «что происходит автоматически, когда бюджет сгорел» — написанное и согласованное обеими сторонами заранее.</p>
<p>Минимальная политика отвечает на четыре вопроса:</p>
<ul>
<li><strong>Кто и при каком условии останавливает релизы?</strong> Например: при burn-rate выше <code>14.4×</code> за час — автоматический freeze рискованных деплоев до конца окна.</li>
<li><strong>Кто разрешает продолжить?</strong> Не «инженер решил» и не «продакт продавил», а названная роль с названным условием.</li>
<li><strong>Что переходит в roadmap при сгоревшем бюджете?</strong> Reliability-задачи получают приоритет над фичами — и это записано, а не выпрашивается каждый раз заново.</li>
<li><strong>Когда и как пересматривается сам SLO?</strong> Раз в квартал — короткий ритуал «изменилось ли что-то в бизнесе или системе, что меняет нужное число».</li>
</ul>
<p>На практике это умещается на одну страницу — по образцу error budget policy из главы <a href="https://sre.google/workbook/implementing-slos/" rel="noopener noreferrer" target="_blank">«Implementing SLOs»</a>
 в Google SRE Workbook. Для поиска нашего маркетплейса политика могла бы выглядеть так:</p>
<blockquote><p><strong>Error budget policy — поиск каталога (SLO 99.9%, окно 30 дней)</strong></p>
<ul>
<li><strong>Жёлтая зона</strong> (потрачено 50% бюджета): уведомление в канал продукта, ретроспектива на ближайшем синке, новых рискованных экспериментов не начинаем.</li>
<li><strong>Красная зона</strong> (потрачено 90%): freeze рискованных деплоев — катим только хотфиксы и security-патчи. Reliability-задачи поднимаются над фичами в текущем спринте.</li>
<li><strong>Бюджет исчерпан</strong> (100%): полный freeze фич до конца окна. Эскалация продуктовому владельцу, обязательный разбор причин.</li>
<li><strong>Кто снимает freeze:</strong> продуктовый владелец по согласованию с SRE-lead, не раньше чем burn-rate вернулся к норме.</li>
<li><strong>Пересмотр SLO:</strong> первый понедельник квартала, участвуют продакт и SRE-lead.</li>
<li><strong>Подписали:</strong> <em>имя продуктового владельца</em>, <em>имя SRE-lead</em>, дата.</li>
</ul>
</blockquote><p>Эта страница важнее любого дашборда. Дашборд показывает, что бюджет горит. Страница говорит, что с этим делать и кто за это отвечает.</p>
<aside class="callout callout--warn" role="note">
  <div class="callout__icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg></div>
  <div class="callout__body"><p class="callout__title">Без политики SLO проигрывает всегда</p>
    <div class="callout__content"><p>Если решение «морозим или катим» принимается в момент пожара, оно принимается властью: кто выше по иерархии или ближе к CEO, тот и победил. Записанная заранее политика — это способ вынуть это решение из-под давления момента. Её главная ценность не в тексте, а в том, что её согласовали, когда никто не был в панике.</p></div>
  </div>
</aside><p>Важнейшее уточнение, которое часто упускают: <strong>error budget policy — это продуктовый артефакт, а не инженерный</strong>. Его подписывает не тимлид SRE «для себя», а продуктовый владелец — потому что это он соглашается, что при сгоревшем бюджете его фичи подождут. Подпись здесь не метафора: должно быть понятно, кто конкретно сказал «да» этим правилам. Если не можешь назвать имя — политики нет.</p>
<h3 id="3-перевод-девяток-в-деньги">3. Перевод девяток в деньги</h3>
<p>Бизнесу нужны не проценты, а валюта. «99.9% против 99.95%» для продакта — пустой звук, пока ты не показал, что стоит за этой разницей в деньгах. Поэтому в зрелом диалоге всегда есть связка <code>SLI → ₽</code>.</p>
<p>Берём наш маркетплейс. Из «чертежа»: GMV порядка 1 млрд ₽ в день, поиск кормит 40–70% покупок, каждые <code>+100 ms</code> латентности на ключевом read path стоят примерно <code>−0.5…1.5%</code> конверсии. Отсюда — простой мост:</p>
$$ \text{Стоимость простоя} = \text{GMV в час} \times \text{доля задетого трафика} \times \text{длительность} $$<p>Дальше бюджет ошибок перестаёт быть процентом и становится деньгами. Сгоревший за инцидент бюджет — это не «−2% за час на графике», а «вот столько недополученной выручки, если такой инцидент повторится на пике». Burn-rate из множителя (<code>14.4×</code>, <code>36×</code> — подробно про него в статье <a href="/posts/burn-rate-is-not-speed/">«Скорость сгорания бюджета ошибок»</a>
) превращается в скорость утечки денег: при таком-то burn-rate на пике Чёрной пятницы мы теряем столько-то рублей в минуту.</p>
<p>Посчитаем на пальцах для одного и того же 15-минутного инцидента в поиске — полная недоступность пути. GMV 1 млрд ₽ в день размазан неравномерно: обычным днём через поиск проходит порядка 400 млн ₽ выручки (предположим, 40% покупок стартуют с поиска), на пике распродажи дневной GMV умножается в <code>×3–5</code>, и доля стартующих с поиска покупок растёт.</p>
<table>
  <thead>
      <tr>
          <th></th>
          <th>Обычный вторник</th>
          <th>Пик распродажи</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Выручка через поиск за день</td>
          <td>~400 млн ₽</td>
          <td>~1,5 млрд ₽</td>
      </tr>
      <tr>
          <td>Выручка через поиск в час (грубо)</td>
          <td>~17 млн ₽</td>
          <td>~120 млн ₽</td>
      </tr>
      <tr>
          <td>Полный простой поиска 15 минут</td>
          <td>~4,2 млн ₽</td>
          <td>~30 млн ₽</td>
      </tr>
      <tr>
          <td>Тот же burn-rate в долях бюджета</td>
          <td>один и тот же <code>~50×</code></td>
          <td>один и тот же <code>~50×</code></td>
      </tr>
  </tbody>
</table>
<p>Цифры грубые и зависят от профиля трафика — но порядок и так говорит главное: <strong>один и тот же инцидент с одним и тем же burn-rate стоит на пике в разы дороже</strong>. Поэтому «потеряли 15 минут» — бессмысленная фраза без контекста «когда». А burn-rate как безразмерный множитель тут особенно удобен: <code>50×</code> одинаково тревожен и во вторник, и в Чёрную пятницу, просто в деньгах разворачивается по-разному.</p>
<p>Это разговор, который продакт понимает мгновенно. Не «у нас burn-rate 14.4», а «при текущем burn-rate мы за час пикового трафика теряем выручку, равную недельной зарплате команды — продолжаем катить?». Конвертация в деньги и переводит SLO из инженерной плоскости в управленческую.</p>
<aside class="callout callout--note" role="note">
  <div class="callout__icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg></div>
  <div class="callout__body"><p class="callout__title">Сезонность — это не деталь, это половина разговора</p>
    <div class="callout__content"><p>Пять минут даунтайма обычным вторником и пять минут в Чёрную пятницу — это разные деньги в десятки раз. Бюджет ошибок «горит» неравномерно: на пике RPS ты расходуешь его в разы быстрее. Поэтому проектировать SLO и считать стоимость инцидента надо на пик, а не на среднюю нагрузку. Бизнес это, кстати, обычно понимает лучше инженеров — он живёт сезонностью.</p></div>
  </div>
</aside><h3 id="4-где-у-нас-критичные-пользовательские-пути">4. «Где у нас критичные пользовательские пути»</h3>
<p>И последнее, самое неочевидное. Список критичных пользовательских путей (CUJ — critical user journey) бизнес должен уметь произнести <strong>сам</strong>. Это не то, что SRE приносит продакту как откровение — «смотри, я тут проанализировал, у вас критичен поиск». Если CUJ известны только инженерам, значит, бизнес не владеет собственной надёжностью.</p>
<p>Хорошая проверка зрелости диалога: спроси продакта «назови три сценария, простой которых на 30 минут стоит нам больше всего». Если он отвечает не задумываясь — диалог здоровый. Если лезет к SRE «а какие у нас там пути» — надёжность пока живёт в инженерной резервации.</p>
<p>Для нашего маркетплейса CUJ — это путь «пришёл с намерением купить → нашёл → выбрал → положил в корзину → оплатил». И продакт должен понимать, что поиск (вход в этот путь) и оплата (выход) — разного класса критичности, и что на них вешаются разные SLO. Это понимание — не бонус, это условие, без которого все предыдущие три пункта повисают в воздухе.</p>
<h3 id="диалог--это-цикл-а-не-презентация">Диалог — это цикл, а не презентация</h3>
<p>Сложим четыре пункта вместе. Диалог о надёжности — это не разовое «защитили SLO на демо», а повторяющийся цикл:</p>
<figure class="mermaid mermaid--prerendered" aria-label="Mermaid diagram">
<div class="mermaid-svg mermaid-svg--light">
<svg id="m-6645021c4c1a-light" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 1710.91px; background-color: transparent;" viewBox="0 0 1710.90625 148.5" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#m-6645021c4c1a-light{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;fill:#1c1c1f;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#m-6645021c4c1a-light .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#m-6645021c4c1a-light .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#m-6645021c4c1a-light .error-icon{fill:#fee2e2;}#m-6645021c4c1a-light .error-text{fill:#7f1d1d;stroke:#7f1d1d;}#m-6645021c4c1a-light .edge-thickness-normal{stroke-width:1px;}#m-6645021c4c1a-light .edge-thickness-thick{stroke-width:3.5px;}#m-6645021c4c1a-light .edge-pattern-solid{stroke-dasharray:0;}#m-6645021c4c1a-light .edge-thickness-invisible{stroke-width:0;fill:none;}#m-6645021c4c1a-light .edge-pattern-dashed{stroke-dasharray:3;}#m-6645021c4c1a-light .edge-pattern-dotted{stroke-dasharray:2;}#m-6645021c4c1a-light .marker{fill:#5b5b62;stroke:#5b5b62;}#m-6645021c4c1a-light .marker.cross{stroke:#5b5b62;}#m-6645021c4c1a-light svg{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;}#m-6645021c4c1a-light p{margin:0;}#m-6645021c4c1a-light .label{font-family:Inter,system-ui,-apple-system,sans-serif;color:#1c1c1f;}#m-6645021c4c1a-light .cluster-label text{fill:#1c1c1f;}#m-6645021c4c1a-light .cluster-label span{color:#1c1c1f;}#m-6645021c4c1a-light .cluster-label span p{background-color:transparent;}#m-6645021c4c1a-light .label text,#m-6645021c4c1a-light span{fill:#1c1c1f;color:#1c1c1f;}#m-6645021c4c1a-light .node rect,#m-6645021c4c1a-light .node circle,#m-6645021c4c1a-light .node ellipse,#m-6645021c4c1a-light .node polygon,#m-6645021c4c1a-light .node path{fill:#ffffff;stroke:#c8c5bb;stroke-width:1px;}#m-6645021c4c1a-light .rough-node .label text,#m-6645021c4c1a-light .node .label text,#m-6645021c4c1a-light .image-shape .label,#m-6645021c4c1a-light .icon-shape .label{text-anchor:middle;}#m-6645021c4c1a-light .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#m-6645021c4c1a-light .rough-node .label,#m-6645021c4c1a-light .node .label,#m-6645021c4c1a-light .image-shape .label,#m-6645021c4c1a-light .icon-shape .label{text-align:center;}#m-6645021c4c1a-light .node.clickable{cursor:pointer;}#m-6645021c4c1a-light .root .anchor path{fill:#5b5b62!important;stroke-width:0;stroke:#5b5b62;}#m-6645021c4c1a-light .arrowheadPath{fill:rgba(255, 255, 255, 0);}#m-6645021c4c1a-light .edgePath .path{stroke:#5b5b62;stroke-width:1px;}#m-6645021c4c1a-light .flowchart-link{stroke:#5b5b62;fill:none;}#m-6645021c4c1a-light .edgeLabel{background-color:#fafaf7;text-align:center;}#m-6645021c4c1a-light .edgeLabel p{background-color:#fafaf7;}#m-6645021c4c1a-light .edgeLabel rect{opacity:0.5;background-color:#fafaf7;fill:#fafaf7;}#m-6645021c4c1a-light .labelBkg{background-color:rgba(250, 250, 247, 0.5);}#m-6645021c4c1a-light .cluster rect{fill:#f3f1ed;stroke:#c8c5bb;stroke-width:1px;}#m-6645021c4c1a-light .cluster text{fill:#1c1c1f;}#m-6645021c4c1a-light .cluster span{color:#1c1c1f;}#m-6645021c4c1a-light div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:12px;background:#fed7aa;border:1px solid #c2410c;border-radius:2px;pointer-events:none;z-index:100;}#m-6645021c4c1a-light .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#1c1c1f;}#m-6645021c4c1a-light rect.text{fill:none;stroke-width:0;}#m-6645021c4c1a-light .icon-shape,#m-6645021c4c1a-light .image-shape{background-color:#fafaf7;text-align:center;}#m-6645021c4c1a-light .icon-shape p,#m-6645021c4c1a-light .image-shape p{background-color:#fafaf7;padding:2px;}#m-6645021c4c1a-light .icon-shape .label rect,#m-6645021c4c1a-light .image-shape .label rect{opacity:0.5;background-color:#fafaf7;fill:#fafaf7;}#m-6645021c4c1a-light .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#m-6645021c4c1a-light .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#m-6645021c4c1a-light .node .neo-node{stroke:#c8c5bb;}#m-6645021c4c1a-light [data-look="neo"].node rect,#m-6645021c4c1a-light [data-look="neo"].cluster rect,#m-6645021c4c1a-light [data-look="neo"].node polygon{stroke:url(#m-6645021c4c1a-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-6645021c4c1a-light [data-look="neo"].node path{stroke:url(#m-6645021c4c1a-light-gradient);stroke-width:1px;}#m-6645021c4c1a-light [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-6645021c4c1a-light [data-look="neo"].node .neo-line path{stroke:#c8c5bb;filter:none;}#m-6645021c4c1a-light [data-look="neo"].node circle{stroke:url(#m-6645021c4c1a-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-6645021c4c1a-light [data-look="neo"].node circle .state-start{fill:#000000;}#m-6645021c4c1a-light [data-look="neo"].icon-shape .icon{fill:url(#m-6645021c4c1a-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-6645021c4c1a-light [data-look="neo"].icon-shape .icon-neo path{stroke:url(#m-6645021c4c1a-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-6645021c4c1a-light :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="m-6645021c4c1a-light_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-light_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-light_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-light_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-light_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-light_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-light_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-light_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-light_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-light_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-light_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="m-6645021c4c1a-light_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M254.531,63.811L258.698,62.634C262.865,61.457,271.198,59.104,278.865,57.927C286.531,56.75,293.531,56.75,297.031,56.75L300.531,56.75" id="m-6645021c4c1a-light-L_CUJ_Target_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_CUJ_Target_0" data-points="W3sieCI6MjU0LjUzMTI1LCJ5Ijo2My44MTA4MDcyNTA1MDA1OH0seyJ4IjoyNzkuNTMxMjUsInkiOjU2Ljc1fSx7IngiOjMwNC41MzEyNSwieSI6NTYuNzV9XQ==" data-look="classic" marker-end="url(#m-6645021c4c1a-light_flowchart-v2-pointEnd)"/><path d="M563.578,56.75L567.745,56.75C571.911,56.75,580.245,56.75,587.911,56.75C595.578,56.75,602.578,56.75,606.078,56.75L609.578,56.75" id="m-6645021c4c1a-light-L_Target_Policy_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Target_Policy_0" data-points="W3sieCI6NTYzLjU3ODEyNSwieSI6NTYuNzV9LHsieCI6NTg4LjU3ODEyNSwieSI6NTYuNzV9LHsieCI6NjEzLjU3ODEyNSwieSI6NTYuNzV9XQ==" data-look="classic" marker-end="url(#m-6645021c4c1a-light_flowchart-v2-pointEnd)"/><path d="M873.578,56.75L877.745,56.75C881.911,56.75,890.245,56.75,897.911,56.75C905.578,56.75,912.578,56.75,916.078,56.75L919.578,56.75" id="m-6645021c4c1a-light-L_Policy_Run_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Policy_Run_0" data-points="W3sieCI6ODczLjU3ODEyNSwieSI6NTYuNzV9LHsieCI6ODk4LjU3ODEyNSwieSI6NTYuNzV9LHsieCI6OTIzLjU3ODEyNSwieSI6NTYuNzV9XQ==" data-look="classic" marker-end="url(#m-6645021c4c1a-light_flowchart-v2-pointEnd)"/><path d="M1168.672,56.75L1172.839,56.75C1177.005,56.75,1185.339,56.75,1193.005,56.75C1200.672,56.75,1207.672,56.75,1211.172,56.75L1214.672,56.75" id="m-6645021c4c1a-light-L_Run_Money_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Run_Money_0" data-points="W3sieCI6MTE2OC42NzE4NzUsInkiOjU2Ljc1fSx7IngiOjExOTMuNjcxODc1LCJ5Ijo1Ni43NX0seyJ4IjoxMjE4LjY3MTg3NSwieSI6NTYuNzV9XQ==" data-look="classic" marker-end="url(#m-6645021c4c1a-light_flowchart-v2-pointEnd)"/><path d="M1412.141,56.75L1416.307,56.75C1420.474,56.75,1428.807,56.75,1436.5,57.766C1444.193,58.781,1451.245,60.812,1454.771,61.828L1458.297,62.844" id="m-6645021c4c1a-light-L_Money_Review_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Money_Review_0" data-points="W3sieCI6MTQxMi4xNDA2MjUsInkiOjU2Ljc1fSx7IngiOjE0MzcuMTQwNjI1LCJ5Ijo1Ni43NX0seyJ4IjoxNDYyLjE0MDYyNSwieSI6NjMuOTUwODE2ODA5MDcwODh9XQ==" data-look="classic" marker-end="url(#m-6645021c4c1a-light_flowchart-v2-pointEnd)"/><path d="M1462.141,133.299L1457.974,134.499C1453.807,135.699,1445.474,138.1,1421.018,139.3C1396.563,140.5,1355.984,140.5,1315.406,140.5C1274.828,140.5,1234.25,140.5,1189.37,140.5C1144.49,140.5,1095.307,140.5,1046.125,140.5C996.943,140.5,947.76,140.5,897.336,140.5C846.911,140.5,795.245,140.5,743.578,140.5C691.911,140.5,640.245,140.5,588.658,140.5C537.07,140.5,485.563,140.5,434.055,140.5C382.547,140.5,331.039,140.5,301.76,139.504C272.481,138.509,265.431,136.518,261.906,135.522L258.381,134.526" id="m-6645021c4c1a-light-L_Review_CUJ_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Review_CUJ_0" data-points="W3sieCI6MTQ2Mi4xNDA2MjUsInkiOjEzMy4yOTkxODMxOTA5MjkxfSx7IngiOjE0MzcuMTQwNjI1LCJ5IjoxNDAuNX0seyJ4IjoxMzE1LjQwNjI1LCJ5IjoxNDAuNX0seyJ4IjoxMTkzLjY3MTg3NSwieSI6MTQwLjV9LHsieCI6MTA0Ni4xMjUsInkiOjE0MC41fSx7IngiOjg5OC41NzgxMjUsInkiOjE0MC41fSx7IngiOjc0My41NzgxMjUsInkiOjE0MC41fSx7IngiOjU4OC41NzgxMjUsInkiOjE0MC41fSx7IngiOjQzNC4wNTQ2ODc1LCJ5IjoxNDAuNX0seyJ4IjoyNzkuNTMxMjUsInkiOjE0MC41fSx7IngiOjI1NC41MzEyNSwieSI6MTMzLjQzOTE5Mjc0OTQ5OTQzfV0=" data-look="classic" marker-end="url(#m-6645021c4c1a-light_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_CUJ_Target_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Target_Policy_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Policy_Run_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Run_Money_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Money_Review_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Review_CUJ_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="m-6645021c4c1a-light-flowchart-CUJ-0" data-look="classic" transform="translate(131.265625, 98.625)"><rect class="basic label-container" style="" x="-123.265625" y="-37.5" width="246.53125" height="75"/><g class="label" style="" transform="translate(-93.265625, -22.5)"><rect/><foreignObject width="186.53125" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Бизнес называет<br />критичные пути и их цену</p></span></div></foreignObject></g></g><g class="node default" id="m-6645021c4c1a-light-flowchart-Target-1" data-look="classic" transform="translate(434.0546875, 56.75)"><rect class="basic label-container" style="" x="-129.5234375" y="-37.5" width="259.046875" height="75"/><g class="label" style="" transform="translate(-99.5234375, -22.5)"><rect/><foreignObject width="199.046875" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Вместе выбираем SLO<br />как бюджет на компромисс</p></span></div></foreignObject></g></g><g class="node default" id="m-6645021c4c1a-light-flowchart-Policy-3" data-look="classic" transform="translate(743.578125, 56.75)"><rect class="basic label-container" style="" x="-130" y="-48.75" width="260" height="97.5"/><g class="label" style="" transform="translate(-100, -33.75)"><rect/><foreignObject width="200" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>Записываем error budget policy<br />продакт подписывает</p></span></div></foreignObject></g></g><g class="node default" id="m-6645021c4c1a-light-flowchart-Run-5" data-look="classic" transform="translate(1046.125, 56.75)"><rect class="basic label-container" style="" x="-122.546875" y="-37.5" width="245.09375" height="75"/><g class="label" style="" transform="translate(-92.546875, -22.5)"><rect/><foreignObject width="185.09375" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Живём по бюджету:<br />деплои, инциденты, фичи</p></span></div></foreignObject></g></g><g class="node default" id="m-6645021c4c1a-light-flowchart-Money-7" data-look="classic" transform="translate(1315.40625, 56.75)"><rect class="basic label-container" style="" x="-96.734375" y="-37.5" width="193.46875" height="75"/><g class="label" style="" transform="translate(-66.734375, -22.5)"><rect/><foreignObject width="133.46875" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Считаем сгорание<br />в деньгах</p></span></div></foreignObject></g></g><g class="node default" id="m-6645021c4c1a-light-flowchart-Review-9" data-look="classic" transform="translate(1582.5234375, 98.625)"><rect class="basic label-container" style="" x="-120.3828125" y="-37.5" width="240.765625" height="75"/><g class="label" style="" transform="translate(-90.3828125, -22.5)"><rect/><foreignObject width="180.765625" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Квартальный пересмотр:<br />изменилось ли число</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="m-6645021c4c1a-light-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="m-6645021c4c1a-light-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><linearGradient id="m-6645021c4c1a-light-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#c8c5bb" stop-opacity="1"/><stop offset="100%" stop-color="#c8c5bb" stop-opacity="1"/></linearGradient></svg>
</div>
<div class="mermaid-svg mermaid-svg--dark">
<svg id="m-6645021c4c1a-dark" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 1710.91px; background-color: transparent;" viewBox="0 0 1710.90625 148.5" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#m-6645021c4c1a-dark{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;fill:#e8e6df;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#m-6645021c4c1a-dark .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#m-6645021c4c1a-dark .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#m-6645021c4c1a-dark .error-icon{fill:#7f1d1d;}#m-6645021c4c1a-dark .error-text{fill:#fecaca;stroke:#fecaca;}#m-6645021c4c1a-dark .edge-thickness-normal{stroke-width:1px;}#m-6645021c4c1a-dark .edge-thickness-thick{stroke-width:3.5px;}#m-6645021c4c1a-dark .edge-pattern-solid{stroke-dasharray:0;}#m-6645021c4c1a-dark .edge-thickness-invisible{stroke-width:0;fill:none;}#m-6645021c4c1a-dark .edge-pattern-dashed{stroke-dasharray:3;}#m-6645021c4c1a-dark .edge-pattern-dotted{stroke-dasharray:2;}#m-6645021c4c1a-dark .marker{fill:#a8a89e;stroke:#a8a89e;}#m-6645021c4c1a-dark .marker.cross{stroke:#a8a89e;}#m-6645021c4c1a-dark svg{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;}#m-6645021c4c1a-dark p{margin:0;}#m-6645021c4c1a-dark .label{font-family:Inter,system-ui,-apple-system,sans-serif;color:#e8e6df;}#m-6645021c4c1a-dark .cluster-label text{fill:#e8e6df;}#m-6645021c4c1a-dark .cluster-label span{color:#e8e6df;}#m-6645021c4c1a-dark .cluster-label span p{background-color:transparent;}#m-6645021c4c1a-dark .label text,#m-6645021c4c1a-dark span{fill:#e8e6df;color:#e8e6df;}#m-6645021c4c1a-dark .node rect,#m-6645021c4c1a-dark .node circle,#m-6645021c4c1a-dark .node ellipse,#m-6645021c4c1a-dark .node polygon,#m-6645021c4c1a-dark .node path{fill:#23252a;stroke:#3f3f46;stroke-width:1px;}#m-6645021c4c1a-dark .rough-node .label text,#m-6645021c4c1a-dark .node .label text,#m-6645021c4c1a-dark .image-shape .label,#m-6645021c4c1a-dark .icon-shape .label{text-anchor:middle;}#m-6645021c4c1a-dark .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#m-6645021c4c1a-dark .rough-node .label,#m-6645021c4c1a-dark .node .label,#m-6645021c4c1a-dark .image-shape .label,#m-6645021c4c1a-dark .icon-shape .label{text-align:center;}#m-6645021c4c1a-dark .node.clickable{cursor:pointer;}#m-6645021c4c1a-dark .root .anchor path{fill:#a8a89e!important;stroke-width:0;stroke:#a8a89e;}#m-6645021c4c1a-dark .arrowheadPath{fill:rgba(255, 255, 255, 0);}#m-6645021c4c1a-dark .edgePath .path{stroke:#a8a89e;stroke-width:1px;}#m-6645021c4c1a-dark .flowchart-link{stroke:#a8a89e;fill:none;}#m-6645021c4c1a-dark .edgeLabel{background-color:#1a1b1e;text-align:center;}#m-6645021c4c1a-dark .edgeLabel p{background-color:#1a1b1e;}#m-6645021c4c1a-dark .edgeLabel rect{opacity:0.5;background-color:#1a1b1e;fill:#1a1b1e;}#m-6645021c4c1a-dark .labelBkg{background-color:rgba(26, 27, 30, 0.5);}#m-6645021c4c1a-dark .cluster rect{fill:#2a2b2f;stroke:#3f3f46;stroke-width:1px;}#m-6645021c4c1a-dark .cluster text{fill:#e8e6df;}#m-6645021c4c1a-dark .cluster span{color:#e8e6df;}#m-6645021c4c1a-dark div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:12px;background:#7c2d12;border:1px solid #fb923c;border-radius:2px;pointer-events:none;z-index:100;}#m-6645021c4c1a-dark .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#e8e6df;}#m-6645021c4c1a-dark rect.text{fill:none;stroke-width:0;}#m-6645021c4c1a-dark .icon-shape,#m-6645021c4c1a-dark .image-shape{background-color:#1a1b1e;text-align:center;}#m-6645021c4c1a-dark .icon-shape p,#m-6645021c4c1a-dark .image-shape p{background-color:#1a1b1e;padding:2px;}#m-6645021c4c1a-dark .icon-shape .label rect,#m-6645021c4c1a-dark .image-shape .label rect{opacity:0.5;background-color:#1a1b1e;fill:#1a1b1e;}#m-6645021c4c1a-dark .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#m-6645021c4c1a-dark .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#m-6645021c4c1a-dark .node .neo-node{stroke:#3f3f46;}#m-6645021c4c1a-dark [data-look="neo"].node rect,#m-6645021c4c1a-dark [data-look="neo"].cluster rect,#m-6645021c4c1a-dark [data-look="neo"].node polygon{stroke:url(#m-6645021c4c1a-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-6645021c4c1a-dark [data-look="neo"].node path{stroke:url(#m-6645021c4c1a-dark-gradient);stroke-width:1px;}#m-6645021c4c1a-dark [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-6645021c4c1a-dark [data-look="neo"].node .neo-line path{stroke:#3f3f46;filter:none;}#m-6645021c4c1a-dark [data-look="neo"].node circle{stroke:url(#m-6645021c4c1a-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-6645021c4c1a-dark [data-look="neo"].node circle .state-start{fill:#000000;}#m-6645021c4c1a-dark [data-look="neo"].icon-shape .icon{fill:url(#m-6645021c4c1a-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-6645021c4c1a-dark [data-look="neo"].icon-shape .icon-neo path{stroke:url(#m-6645021c4c1a-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-6645021c4c1a-dark :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="m-6645021c4c1a-dark_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-dark_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-dark_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-dark_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-dark_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-dark_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-dark_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-dark_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-dark_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-dark_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-dark_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="m-6645021c4c1a-dark_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M254.531,63.811L258.698,62.634C262.865,61.457,271.198,59.104,278.865,57.927C286.531,56.75,293.531,56.75,297.031,56.75L300.531,56.75" id="m-6645021c4c1a-dark-L_CUJ_Target_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_CUJ_Target_0" data-points="W3sieCI6MjU0LjUzMTI1LCJ5Ijo2My44MTA4MDcyNTA1MDA1OH0seyJ4IjoyNzkuNTMxMjUsInkiOjU2Ljc1fSx7IngiOjMwNC41MzEyNSwieSI6NTYuNzV9XQ==" data-look="classic" marker-end="url(#m-6645021c4c1a-dark_flowchart-v2-pointEnd)"/><path d="M563.578,56.75L567.745,56.75C571.911,56.75,580.245,56.75,587.911,56.75C595.578,56.75,602.578,56.75,606.078,56.75L609.578,56.75" id="m-6645021c4c1a-dark-L_Target_Policy_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Target_Policy_0" data-points="W3sieCI6NTYzLjU3ODEyNSwieSI6NTYuNzV9LHsieCI6NTg4LjU3ODEyNSwieSI6NTYuNzV9LHsieCI6NjEzLjU3ODEyNSwieSI6NTYuNzV9XQ==" data-look="classic" marker-end="url(#m-6645021c4c1a-dark_flowchart-v2-pointEnd)"/><path d="M873.578,56.75L877.745,56.75C881.911,56.75,890.245,56.75,897.911,56.75C905.578,56.75,912.578,56.75,916.078,56.75L919.578,56.75" id="m-6645021c4c1a-dark-L_Policy_Run_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Policy_Run_0" data-points="W3sieCI6ODczLjU3ODEyNSwieSI6NTYuNzV9LHsieCI6ODk4LjU3ODEyNSwieSI6NTYuNzV9LHsieCI6OTIzLjU3ODEyNSwieSI6NTYuNzV9XQ==" data-look="classic" marker-end="url(#m-6645021c4c1a-dark_flowchart-v2-pointEnd)"/><path d="M1168.672,56.75L1172.839,56.75C1177.005,56.75,1185.339,56.75,1193.005,56.75C1200.672,56.75,1207.672,56.75,1211.172,56.75L1214.672,56.75" id="m-6645021c4c1a-dark-L_Run_Money_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Run_Money_0" data-points="W3sieCI6MTE2OC42NzE4NzUsInkiOjU2Ljc1fSx7IngiOjExOTMuNjcxODc1LCJ5Ijo1Ni43NX0seyJ4IjoxMjE4LjY3MTg3NSwieSI6NTYuNzV9XQ==" data-look="classic" marker-end="url(#m-6645021c4c1a-dark_flowchart-v2-pointEnd)"/><path d="M1412.141,56.75L1416.307,56.75C1420.474,56.75,1428.807,56.75,1436.5,57.766C1444.193,58.781,1451.245,60.812,1454.771,61.828L1458.297,62.844" id="m-6645021c4c1a-dark-L_Money_Review_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Money_Review_0" data-points="W3sieCI6MTQxMi4xNDA2MjUsInkiOjU2Ljc1fSx7IngiOjE0MzcuMTQwNjI1LCJ5Ijo1Ni43NX0seyJ4IjoxNDYyLjE0MDYyNSwieSI6NjMuOTUwODE2ODA5MDcwODh9XQ==" data-look="classic" marker-end="url(#m-6645021c4c1a-dark_flowchart-v2-pointEnd)"/><path d="M1462.141,133.299L1457.974,134.499C1453.807,135.699,1445.474,138.1,1421.018,139.3C1396.563,140.5,1355.984,140.5,1315.406,140.5C1274.828,140.5,1234.25,140.5,1189.37,140.5C1144.49,140.5,1095.307,140.5,1046.125,140.5C996.943,140.5,947.76,140.5,897.336,140.5C846.911,140.5,795.245,140.5,743.578,140.5C691.911,140.5,640.245,140.5,588.658,140.5C537.07,140.5,485.563,140.5,434.055,140.5C382.547,140.5,331.039,140.5,301.76,139.504C272.481,138.509,265.431,136.518,261.906,135.522L258.381,134.526" id="m-6645021c4c1a-dark-L_Review_CUJ_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Review_CUJ_0" data-points="W3sieCI6MTQ2Mi4xNDA2MjUsInkiOjEzMy4yOTkxODMxOTA5MjkxfSx7IngiOjE0MzcuMTQwNjI1LCJ5IjoxNDAuNX0seyJ4IjoxMzE1LjQwNjI1LCJ5IjoxNDAuNX0seyJ4IjoxMTkzLjY3MTg3NSwieSI6MTQwLjV9LHsieCI6MTA0Ni4xMjUsInkiOjE0MC41fSx7IngiOjg5OC41NzgxMjUsInkiOjE0MC41fSx7IngiOjc0My41NzgxMjUsInkiOjE0MC41fSx7IngiOjU4OC41NzgxMjUsInkiOjE0MC41fSx7IngiOjQzNC4wNTQ2ODc1LCJ5IjoxNDAuNX0seyJ4IjoyNzkuNTMxMjUsInkiOjE0MC41fSx7IngiOjI1NC41MzEyNSwieSI6MTMzLjQzOTE5Mjc0OTQ5OTQzfV0=" data-look="classic" marker-end="url(#m-6645021c4c1a-dark_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_CUJ_Target_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Target_Policy_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Policy_Run_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Run_Money_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Money_Review_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Review_CUJ_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="m-6645021c4c1a-dark-flowchart-CUJ-0" data-look="classic" transform="translate(131.265625, 98.625)"><rect class="basic label-container" style="" x="-123.265625" y="-37.5" width="246.53125" height="75"/><g class="label" style="" transform="translate(-93.265625, -22.5)"><rect/><foreignObject width="186.53125" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Бизнес называет<br />критичные пути и их цену</p></span></div></foreignObject></g></g><g class="node default" id="m-6645021c4c1a-dark-flowchart-Target-1" data-look="classic" transform="translate(434.0546875, 56.75)"><rect class="basic label-container" style="" x="-129.5234375" y="-37.5" width="259.046875" height="75"/><g class="label" style="" transform="translate(-99.5234375, -22.5)"><rect/><foreignObject width="199.046875" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Вместе выбираем SLO<br />как бюджет на компромисс</p></span></div></foreignObject></g></g><g class="node default" id="m-6645021c4c1a-dark-flowchart-Policy-3" data-look="classic" transform="translate(743.578125, 56.75)"><rect class="basic label-container" style="" x="-130" y="-48.75" width="260" height="97.5"/><g class="label" style="" transform="translate(-100, -33.75)"><rect/><foreignObject width="200" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>Записываем error budget policy<br />продакт подписывает</p></span></div></foreignObject></g></g><g class="node default" id="m-6645021c4c1a-dark-flowchart-Run-5" data-look="classic" transform="translate(1046.125, 56.75)"><rect class="basic label-container" style="" x="-122.546875" y="-37.5" width="245.09375" height="75"/><g class="label" style="" transform="translate(-92.546875, -22.5)"><rect/><foreignObject width="185.09375" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Живём по бюджету:<br />деплои, инциденты, фичи</p></span></div></foreignObject></g></g><g class="node default" id="m-6645021c4c1a-dark-flowchart-Money-7" data-look="classic" transform="translate(1315.40625, 56.75)"><rect class="basic label-container" style="" x="-96.734375" y="-37.5" width="193.46875" height="75"/><g class="label" style="" transform="translate(-66.734375, -22.5)"><rect/><foreignObject width="133.46875" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Считаем сгорание<br />в деньгах</p></span></div></foreignObject></g></g><g class="node default" id="m-6645021c4c1a-dark-flowchart-Review-9" data-look="classic" transform="translate(1582.5234375, 98.625)"><rect class="basic label-container" style="" x="-120.3828125" y="-37.5" width="240.765625" height="75"/><g class="label" style="" transform="translate(-90.3828125, -22.5)"><rect/><foreignObject width="180.765625" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Квартальный пересмотр:<br />изменилось ли число</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="m-6645021c4c1a-dark-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="m-6645021c4c1a-dark-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><linearGradient id="m-6645021c4c1a-dark-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#3f3f46" stop-opacity="1"/><stop offset="100%" stop-color="#3f3f46" stop-opacity="1"/></linearGradient></svg>
</div>
</figure><p>Каждый виток — это квартал. На входе бизнес приносит «что и сколько стоит», на выходе получает «вот сколько надёжности мы дали и какой ценой». Если хоть одно звено разорвано — цикл рассыпается, и SLO откатывается в режим артефакта. Именно эту целостность и проверяют на собесе — к нему и переходим.</p>
<h2 id="кейсы-с-system-design-собеса">Кейсы с System Design-собеса</h2>
<p>Те же тезисы, но в позе «кандидат под прессом». Когда меня самого недавно гоняли по этой теме на интервью, стало особенно ясно: вопросы «про SLO» почти никогда не про SLO. Они про то, умеешь ли ты вести разговор о надёжности так, чтобы бизнес поменял поведение. Разберу пять типовых сценариев — на том же маркетплейсе.</p>
<h3 id="кейс-1-зачем-тебе-slo-999-а-не-9999">Кейс 1. «Зачем тебе SLO 99.9, а не 99.99?»</h3>
<p><strong>Что проверяют:</strong> умеет ли кандидат держать рамку «бюджет → архитектура → деньги».</p>
<p><strong>Провальный ответ:</strong> начать с топологии. «Ну, 99.99 — это active-active в трёх регионах, а 99.9 — один регион с failover между AZ». Технически верно, но это ответ на вопрос «чем отличаются архитектуры», а не «зачем тебе эта надёжность».</p>
<p><strong>Сильный ответ всегда начинается со сценария бизнеса:</strong></p>
<blockquote><p>«Зависит от того, какой это путь. Если это поиск каталога — главный драйвер конверсии — то считаем: на 99.9% бюджет даунтайма на пике ~14 минут в месяц, на 99.99% — полторы минуты. Разница в архитектуре — лишних <code>15–25×</code> против <code>4–6×</code> baseline. Вопрос к бизнесу: эти 12 минут в месяц на пике стоят нам больше или меньше, чем утроение инфраструктуры? Если GMV такой, что минута пикового даунтайма — сотни тысяч, берём 99.99. Если нет — 99.9 с запасом».</p>
</blockquote><p>Ключевое: кандидат не выбирает девятку сам. Он показывает, что выбор девятки — это разговор с бизнесом, и приносит в этот разговор обе цифры — цену надёжности и цену её отсутствия.</p>
<h3 id="кейс-2-у-вас-9995-по-чекауту-но-30-оплат-не-проходит--что-не-так">Кейс 2. «У вас 99.95 по чекауту, но 30% оплат не проходит — что не так?»</h3>
<p><strong>Что проверяют:</strong> понимает ли кандидат разрыв между технической доступностью и продуктовой надёжностью.</p>
<p>Это мой любимый кейс, потому что он ловит самую частую ошибку. Дашборд зелёный — <code>99.95%</code> по эндпоинту оплаты. А бизнес кричит, что треть оплат не доходит. Противоречие? Нет. SLI повешен не туда.</p>
<p><strong>Что произошло:</strong> SLI считает «доля ответов <code>2xx</code> от ручки <code>/pay</code>». Ручка честно отвечает <code>200 OK</code> — она приняла запрос. А дальше платёж уходит в провайдера, провайдер таймаутит, ретрай не настроен, и для пользователя оплата «не прошла» — но для SLI всё прекрасно, ручка-то ответила.</p>
<p><strong>Сильный ответ:</strong></p>
<blockquote><p>«SLI измеряет здоровье ручки, а не сценарий. Его надо переповесить на пользовательский результат: „доля начатых оплат, завершившихся подтверждённым списанием за <code>&lt; N</code> секунд“. Тогда таймауты провайдера, потерянные колбэки и зависшие платежи попадут в знаменатель, и 99.95% превратятся в честные 70%. Дашборд начнёт показывать ту же боль, что чувствует бизнес».</p>
</blockquote><p>Это ровно разведение «продуктовая надёжность против технической доступности». Кандидат, который видит этот разрыв, понимает, что SLI вешается на сценарий, а не на success rate ручки. Кандидат, который не видит, будет до утра чинить инфраструктуру, которая и так зелёная.</p>
<h3 id="кейс-3-бизнес-требует-100-доступности-что-отвечаешь">Кейс 3. «Бизнес требует 100% доступности. Что отвечаешь?»</h3>
<p><strong>Что проверяют:</strong> переговорный навык в чистом виде.</p>
<p><strong>Провальный ответ:</strong> «100% невозможно». Технически правда, но это ответ инженера, который закрывает разговор, а не ведёт его. Бизнес услышит «не хочу» и пойдёт давить.</p>
<p><strong>Сильный ответ — не «нельзя», а цена:</strong></p>
<blockquote><p>«Окей, давай посчитаем, что такое 100%. Каждая девятка после 99.9 удорожает систему примерно в разы. 99.99 — это уже <code>15–25×</code> baseline и заморозка скорости релизов. 99.999 — это multi-cloud, независимые DNS, частично независимые кодовые базы, подходы из telecom. А 100% — это бесконечность: ноль допустимых сбоев означает ноль деплоев, ноль экспериментов, ноль изменений. Мы перестанем выпускать фичи вообще. Точно нужны эти девятки — или нам нужно, чтобы конкретный сценарий, скажем оплата, не падал заметно для пользователя? Это разные задачи, и вторая решается сильно дешевле».</p>
</blockquote><p>Кандидат переводит абсолютное требование в трейд-офф и возвращает бизнесу выбор. Часто за «хотим 100%» стоит «не хотим терять оплаты в пик» — а это не про 100%, это про правильный SLO на правильный путь плюс graceful degradation.</p>
<h3 id="кейс-4-кто-принимает-решение-о-фризе-релизов-при-сгорании-бюджета">Кейс 4. «Кто принимает решение о фризе релизов при сгорании бюджета?»</h3>
<p><strong>Что проверяют:</strong> есть ли у кандидата error budget policy в голове и понимает ли он, что это продуктовый артефакт.</p>
<p><strong>Провальный ответ:</strong> «SRE решает» или «тимлид решает». Это инженерный ответ, и он выдаёт, что у кандидата SLO живёт в инженерной резервации.</p>
<p><strong>Сильный ответ:</strong></p>
<blockquote><p>«Решает не человек в моменте, а записанная заранее error budget policy. В ней зафиксировано: при таком-то burn-rate за такое-то окно — автоматический freeze рискованных деплоев. И подписана эта политика продуктовым владельцем, потому что это он соглашается, что его фичи подождут. Если решение каждый раз принимается заново и под давлением — значит, политики нет, и побеждает тот, кто громче».</p>
</blockquote><p>Здесь проверяют понимание, что фриз — это не власть SRE над продуктом, а заранее согласованное обеими сторонами правило. Кандидат, который это понимает, не будет воевать с продактом — он сошлётся на то, что они вместе подписали.</p>
<h3 id="кейс-5-покажи-как-сожжённый-бюджет-влияет-на-дорожную-карту">Кейс 5. «Покажи, как сожжённый бюджет влияет на дорожную карту»</h3>
<p><strong>Что проверяют:</strong> встроен ли SRE в плановый цикл или живёт в параллельной вселенной с продуктом.</p>
<p><strong>Провальный ответ:</strong> «при сгорании бюджета мы делаем post-mortem». Post-mortem — это хорошо, но это про прошлое. Вопрос — про будущее, про roadmap.</p>
<p><strong>Сильный ответ:</strong></p>
<blockquote><p>«Сгоревший бюджет — это вход в планирование, а не только разбор инцидента. Механически: при систематическом сгорании reliability-задачи поднимаются в приоритете над фичами на следующий цикл — это записано в policy. На квартальном reliability review мы смотрим burn-rate за квартал по каждому пути и решаем, куда идёт инженерное усилие. Если поиск стабильно жжёт бюджет — значит, в следующем квартале часть roadmap уходит на его укрепление, и продакт это принимает, потому что видит связь „сгорание → потерянная выручка“».</p>
</blockquote><p>Это проверка на то, что SRE и продукт планируют из одного документа, а не из двух. Если бюджет ошибок никак не дотягивается до roadmap — SRE и продукт живут в разных вселенных, и SLO снова декорация.</p>
<h3 id="главный-паттерн-всех-пяти-кейсов">Главный паттерн всех пяти кейсов</h3>
<p>Сведём пять кейсов в одну таблицу — что на самом деле проверяет каждый:</p>
<table>
  <thead>
      <tr>
          <th>Вопрос на собесе</th>
          <th>Что реально проверяют</th>
          <th>Маркер слабого ответа</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Зачем 99.9, а не 99.99?</td>
          <td>Рамка «бюджет → архитектура → деньги»</td>
          <td>Начал с топологии, а не со сценария</td>
      </tr>
      <tr>
          <td>99.95, но 30% оплат не проходит?</td>
          <td>Разрыв «доступность vs надёжность»</td>
          <td>Полез чинить зелёную инфраструктуру</td>
      </tr>
      <tr>
          <td>Бизнес хочет 100%?</td>
          <td>Переговорный навык</td>
          <td>Сказал «невозможно» и закрыл тему</td>
      </tr>
      <tr>
          <td>Кто решает фриз?</td>
          <td>Error budget policy как продуктовый артефакт</td>
          <td>«SRE решает» / «тимлид решает»</td>
      </tr>
      <tr>
          <td>Бюджет → roadmap?</td>
          <td>Встроен ли SRE в плановый цикл</td>
          <td>«Делаем post-mortem» (про прошлое)</td>
      </tr>
  </tbody>
</table>
<p>На собесе не проверяют знание формул сгорания бюджета — это гуглится за минуту. Проверяют, <strong>можешь ли ты вести разговор о надёжности так, чтобы бизнес поменял своё поведение</strong>. Все пять сильных ответов имеют одну форму: начать со сценария и денег, перевести требование в трейд-офф, вернуть выбор бизнесу, сослаться на заранее согласованное правило. Это и есть навык, который «чертёж» описывал как «SLO — интерфейс между System Design и бизнесом», только теперь — со стороны человека, который этим интерфейсом пользуется вживую.</p>
<h2 id="метрики-sre-команды-для-мультипродукта">Метрики SRE-команды для мультипродукта</h2>
<p>Третий тезис — и самый практически болезненный. Пока продукт один, метрики команды SRE совпадают с метриками продукта: SLO продукта, его бюджет, его инциденты. Команда отчитывается надёжностью своего единственного сервиса, и всё сходится.</p>
<p>Когда продуктов становится 5–10, эта простая картина ломается. Команда обслуживает зоопарк сервисов с разными CUJ, разной критичностью, разной зрелостью. И тут возникает вопрос, на который у большинства команд нет хорошего ответа: <strong>как одной цифрой отчитаться перед менеджментом за надёжность, которую ты дал восьми разным продуктам?</strong> Соблазн — взять среднее. На нём всё и ломается.</p>
<h3 id="что-не-работает-как-метрика-команды">Что не работает как метрика команды</h3>
<p>Три популярных агрегата, каждый из которых врёт по-своему:</p>
<ul>
<li><strong>MTTR в среднем по всем инцидентам.</strong> Растворяет редкие тяжёлые случаи в массе мелких. Команда, которая быстро закрывает сто пустяковых алертов и месяц не может починить один критичный, покажет прекрасный средний MTTR. Хуже того, метрика поощряет «закрыть быстро, не разбираясь» — лишь бы цифра была хорошей.</li>
<li><strong>Composite SLO по всем продуктам.</strong> «Средняя надёжность по компании 99.94%» — это средняя температура по больнице. Она теряет CUJ: упавший в ноль критичный путь одного продукта тонет в здоровье семи остальных. Наивная агрегация SLO в мультипродукте математически врёт — этот эффект хорошо разобран в посте Алекса Идальго <a href="https://blog.relyabilit.ie/implicit-slos-and-their-dangers/" rel="noopener noreferrer" target="_blank">«Implicit SLOs and their dangers»</a>
: композит почти всегда оптимистичнее, чем худший из путей, а пользователю больно именно от худшего.</li>
<li><strong>Количество инцидентов в абсолюте.</strong> Стимулирует молчать о мелких. Если команду меряют числом инцидентов, она перестаёт их заводить — и ты теряешь сигнал. Это классический закон Гудхарта: метрика, ставшая целью, перестаёт быть метрикой.</li>
</ul>
<p>Общая болезнь всех трёх — они сжимают разнородное в одно число, и в этом сжатии теряется ровно то, ради чего метрику заводили.</p>
<h3 id="что-осмысленно-мерить-три-слоя">Что осмысленно мерить: три слоя</h3>
<p>Вместо одного агрегата — раскладка по трём слоям, параллельная трём ролям из «чертежа»: бизнес / инженерия / управление. Каждый слой отвечает на свой вопрос и не пытается заменить остальные.</p>
<figure class="mermaid mermaid--prerendered" aria-label="Mermaid diagram">
<div class="mermaid-svg mermaid-svg--light">
<svg id="m-c763b06a1ef1-light" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 896px; background-color: transparent;" viewBox="0 0 896 136" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#m-c763b06a1ef1-light{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;fill:#1c1c1f;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#m-c763b06a1ef1-light .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#m-c763b06a1ef1-light .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#m-c763b06a1ef1-light .error-icon{fill:#fee2e2;}#m-c763b06a1ef1-light .error-text{fill:#7f1d1d;stroke:#7f1d1d;}#m-c763b06a1ef1-light .edge-thickness-normal{stroke-width:1px;}#m-c763b06a1ef1-light .edge-thickness-thick{stroke-width:3.5px;}#m-c763b06a1ef1-light .edge-pattern-solid{stroke-dasharray:0;}#m-c763b06a1ef1-light .edge-thickness-invisible{stroke-width:0;fill:none;}#m-c763b06a1ef1-light .edge-pattern-dashed{stroke-dasharray:3;}#m-c763b06a1ef1-light .edge-pattern-dotted{stroke-dasharray:2;}#m-c763b06a1ef1-light .marker{fill:#5b5b62;stroke:#5b5b62;}#m-c763b06a1ef1-light .marker.cross{stroke:#5b5b62;}#m-c763b06a1ef1-light svg{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;}#m-c763b06a1ef1-light p{margin:0;}#m-c763b06a1ef1-light .label{font-family:Inter,system-ui,-apple-system,sans-serif;color:#1c1c1f;}#m-c763b06a1ef1-light .cluster-label text{fill:#1c1c1f;}#m-c763b06a1ef1-light .cluster-label span{color:#1c1c1f;}#m-c763b06a1ef1-light .cluster-label span p{background-color:transparent;}#m-c763b06a1ef1-light .label text,#m-c763b06a1ef1-light span{fill:#1c1c1f;color:#1c1c1f;}#m-c763b06a1ef1-light .node rect,#m-c763b06a1ef1-light .node circle,#m-c763b06a1ef1-light .node ellipse,#m-c763b06a1ef1-light .node polygon,#m-c763b06a1ef1-light .node path{fill:#ffffff;stroke:#c8c5bb;stroke-width:1px;}#m-c763b06a1ef1-light .rough-node .label text,#m-c763b06a1ef1-light .node .label text,#m-c763b06a1ef1-light .image-shape .label,#m-c763b06a1ef1-light .icon-shape .label{text-anchor:middle;}#m-c763b06a1ef1-light .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#m-c763b06a1ef1-light .rough-node .label,#m-c763b06a1ef1-light .node .label,#m-c763b06a1ef1-light .image-shape .label,#m-c763b06a1ef1-light .icon-shape .label{text-align:center;}#m-c763b06a1ef1-light .node.clickable{cursor:pointer;}#m-c763b06a1ef1-light .root .anchor path{fill:#5b5b62!important;stroke-width:0;stroke:#5b5b62;}#m-c763b06a1ef1-light .arrowheadPath{fill:rgba(255, 255, 255, 0);}#m-c763b06a1ef1-light .edgePath .path{stroke:#5b5b62;stroke-width:1px;}#m-c763b06a1ef1-light .flowchart-link{stroke:#5b5b62;fill:none;}#m-c763b06a1ef1-light .edgeLabel{background-color:#fafaf7;text-align:center;}#m-c763b06a1ef1-light .edgeLabel p{background-color:#fafaf7;}#m-c763b06a1ef1-light .edgeLabel rect{opacity:0.5;background-color:#fafaf7;fill:#fafaf7;}#m-c763b06a1ef1-light .labelBkg{background-color:rgba(250, 250, 247, 0.5);}#m-c763b06a1ef1-light .cluster rect{fill:#f3f1ed;stroke:#c8c5bb;stroke-width:1px;}#m-c763b06a1ef1-light .cluster text{fill:#1c1c1f;}#m-c763b06a1ef1-light .cluster span{color:#1c1c1f;}#m-c763b06a1ef1-light div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:12px;background:#fed7aa;border:1px solid #c2410c;border-radius:2px;pointer-events:none;z-index:100;}#m-c763b06a1ef1-light .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#1c1c1f;}#m-c763b06a1ef1-light rect.text{fill:none;stroke-width:0;}#m-c763b06a1ef1-light .icon-shape,#m-c763b06a1ef1-light .image-shape{background-color:#fafaf7;text-align:center;}#m-c763b06a1ef1-light .icon-shape p,#m-c763b06a1ef1-light .image-shape p{background-color:#fafaf7;padding:2px;}#m-c763b06a1ef1-light .icon-shape .label rect,#m-c763b06a1ef1-light .image-shape .label rect{opacity:0.5;background-color:#fafaf7;fill:#fafaf7;}#m-c763b06a1ef1-light .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#m-c763b06a1ef1-light .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#m-c763b06a1ef1-light .node .neo-node{stroke:#c8c5bb;}#m-c763b06a1ef1-light [data-look="neo"].node rect,#m-c763b06a1ef1-light [data-look="neo"].cluster rect,#m-c763b06a1ef1-light [data-look="neo"].node polygon{stroke:url(#m-c763b06a1ef1-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-c763b06a1ef1-light [data-look="neo"].node path{stroke:url(#m-c763b06a1ef1-light-gradient);stroke-width:1px;}#m-c763b06a1ef1-light [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-c763b06a1ef1-light [data-look="neo"].node .neo-line path{stroke:#c8c5bb;filter:none;}#m-c763b06a1ef1-light [data-look="neo"].node circle{stroke:url(#m-c763b06a1ef1-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-c763b06a1ef1-light [data-look="neo"].node circle .state-start{fill:#000000;}#m-c763b06a1ef1-light [data-look="neo"].icon-shape .icon{fill:url(#m-c763b06a1ef1-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-c763b06a1ef1-light [data-look="neo"].icon-shape .icon-neo path{stroke:url(#m-c763b06a1ef1-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-c763b06a1ef1-light :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="m-c763b06a1ef1-light_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-light_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-light_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-light_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-light_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-light_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-light_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-light_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-light_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-light_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-light_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="m-c763b06a1ef1-light_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M268,68L272.167,68C276.333,68,284.667,68,292.333,68C300,68,307,68,310.5,68L314,68" id="m-c763b06a1ef1-light-L_L3_L2_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_L3_L2_0" data-points="W3sieCI6MjY4LCJ5Ijo2OH0seyJ4IjoyOTMsInkiOjY4fSx7IngiOjMxOCwieSI6Njh9XQ==" data-look="classic" marker-end="url(#m-c763b06a1ef1-light_flowchart-v2-pointEnd)"/><path d="M578,68L582.167,68C586.333,68,594.667,68,602.333,68C610,68,617,68,620.5,68L624,68" id="m-c763b06a1ef1-light-L_L2_L1_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_L2_L1_0" data-points="W3sieCI6NTc4LCJ5Ijo2OH0seyJ4Ijo2MDMsInkiOjY4fSx7IngiOjYyOCwieSI6Njh9XQ==" data-look="classic" marker-end="url(#m-c763b06a1ef1-light_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_L3_L2_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_L2_L1_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="m-c763b06a1ef1-light-flowchart-L1-0" data-look="classic" transform="translate(758, 68)"><rect class="basic label-container" style="" x="-130" y="-60" width="260" height="120"/><g class="label" style="" transform="translate(-100, -45)"><rect/><foreignObject width="200" height="90"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>Слой 1. Надёжность продуктов суммарно<br />вопрос: какую надёжность мы дали бизнесу</p></span></div></foreignObject></g></g><g class="node default" id="m-c763b06a1ef1-light-flowchart-L2-1" data-look="classic" transform="translate(448, 68)"><rect class="basic label-container" style="" x="-130" y="-60" width="260" height="120"/><g class="label" style="" transform="translate(-100, -45)"><rect/><foreignObject width="200" height="90"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>Слой 2. Инженерное усилие команды<br />вопрос: какой ценой и насколько устойчиво</p></span></div></foreignObject></g></g><g class="node default" id="m-c763b06a1ef1-light-flowchart-L3-2" data-look="classic" transform="translate(138, 68)"><rect class="basic label-container" style="" x="-130" y="-48.75" width="260" height="97.5"/><g class="label" style="" transform="translate(-100, -33.75)"><rect/><foreignObject width="200" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>Слой 3. Качество диалога<br />вопрос: встроена ли надёжность в продукт</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="m-c763b06a1ef1-light-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="m-c763b06a1ef1-light-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><linearGradient id="m-c763b06a1ef1-light-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#c8c5bb" stop-opacity="1"/><stop offset="100%" stop-color="#c8c5bb" stop-opacity="1"/></linearGradient></svg>
</div>
<div class="mermaid-svg mermaid-svg--dark">
<svg id="m-c763b06a1ef1-dark" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 896px; background-color: transparent;" viewBox="0 0 896 136" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#m-c763b06a1ef1-dark{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;fill:#e8e6df;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#m-c763b06a1ef1-dark .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#m-c763b06a1ef1-dark .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#m-c763b06a1ef1-dark .error-icon{fill:#7f1d1d;}#m-c763b06a1ef1-dark .error-text{fill:#fecaca;stroke:#fecaca;}#m-c763b06a1ef1-dark .edge-thickness-normal{stroke-width:1px;}#m-c763b06a1ef1-dark .edge-thickness-thick{stroke-width:3.5px;}#m-c763b06a1ef1-dark .edge-pattern-solid{stroke-dasharray:0;}#m-c763b06a1ef1-dark .edge-thickness-invisible{stroke-width:0;fill:none;}#m-c763b06a1ef1-dark .edge-pattern-dashed{stroke-dasharray:3;}#m-c763b06a1ef1-dark .edge-pattern-dotted{stroke-dasharray:2;}#m-c763b06a1ef1-dark .marker{fill:#a8a89e;stroke:#a8a89e;}#m-c763b06a1ef1-dark .marker.cross{stroke:#a8a89e;}#m-c763b06a1ef1-dark svg{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;}#m-c763b06a1ef1-dark p{margin:0;}#m-c763b06a1ef1-dark .label{font-family:Inter,system-ui,-apple-system,sans-serif;color:#e8e6df;}#m-c763b06a1ef1-dark .cluster-label text{fill:#e8e6df;}#m-c763b06a1ef1-dark .cluster-label span{color:#e8e6df;}#m-c763b06a1ef1-dark .cluster-label span p{background-color:transparent;}#m-c763b06a1ef1-dark .label text,#m-c763b06a1ef1-dark span{fill:#e8e6df;color:#e8e6df;}#m-c763b06a1ef1-dark .node rect,#m-c763b06a1ef1-dark .node circle,#m-c763b06a1ef1-dark .node ellipse,#m-c763b06a1ef1-dark .node polygon,#m-c763b06a1ef1-dark .node path{fill:#23252a;stroke:#3f3f46;stroke-width:1px;}#m-c763b06a1ef1-dark .rough-node .label text,#m-c763b06a1ef1-dark .node .label text,#m-c763b06a1ef1-dark .image-shape .label,#m-c763b06a1ef1-dark .icon-shape .label{text-anchor:middle;}#m-c763b06a1ef1-dark .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#m-c763b06a1ef1-dark .rough-node .label,#m-c763b06a1ef1-dark .node .label,#m-c763b06a1ef1-dark .image-shape .label,#m-c763b06a1ef1-dark .icon-shape .label{text-align:center;}#m-c763b06a1ef1-dark .node.clickable{cursor:pointer;}#m-c763b06a1ef1-dark .root .anchor path{fill:#a8a89e!important;stroke-width:0;stroke:#a8a89e;}#m-c763b06a1ef1-dark .arrowheadPath{fill:rgba(255, 255, 255, 0);}#m-c763b06a1ef1-dark .edgePath .path{stroke:#a8a89e;stroke-width:1px;}#m-c763b06a1ef1-dark .flowchart-link{stroke:#a8a89e;fill:none;}#m-c763b06a1ef1-dark .edgeLabel{background-color:#1a1b1e;text-align:center;}#m-c763b06a1ef1-dark .edgeLabel p{background-color:#1a1b1e;}#m-c763b06a1ef1-dark .edgeLabel rect{opacity:0.5;background-color:#1a1b1e;fill:#1a1b1e;}#m-c763b06a1ef1-dark .labelBkg{background-color:rgba(26, 27, 30, 0.5);}#m-c763b06a1ef1-dark .cluster rect{fill:#2a2b2f;stroke:#3f3f46;stroke-width:1px;}#m-c763b06a1ef1-dark .cluster text{fill:#e8e6df;}#m-c763b06a1ef1-dark .cluster span{color:#e8e6df;}#m-c763b06a1ef1-dark div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:12px;background:#7c2d12;border:1px solid #fb923c;border-radius:2px;pointer-events:none;z-index:100;}#m-c763b06a1ef1-dark .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#e8e6df;}#m-c763b06a1ef1-dark rect.text{fill:none;stroke-width:0;}#m-c763b06a1ef1-dark .icon-shape,#m-c763b06a1ef1-dark .image-shape{background-color:#1a1b1e;text-align:center;}#m-c763b06a1ef1-dark .icon-shape p,#m-c763b06a1ef1-dark .image-shape p{background-color:#1a1b1e;padding:2px;}#m-c763b06a1ef1-dark .icon-shape .label rect,#m-c763b06a1ef1-dark .image-shape .label rect{opacity:0.5;background-color:#1a1b1e;fill:#1a1b1e;}#m-c763b06a1ef1-dark .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#m-c763b06a1ef1-dark .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#m-c763b06a1ef1-dark .node .neo-node{stroke:#3f3f46;}#m-c763b06a1ef1-dark [data-look="neo"].node rect,#m-c763b06a1ef1-dark [data-look="neo"].cluster rect,#m-c763b06a1ef1-dark [data-look="neo"].node polygon{stroke:url(#m-c763b06a1ef1-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-c763b06a1ef1-dark [data-look="neo"].node path{stroke:url(#m-c763b06a1ef1-dark-gradient);stroke-width:1px;}#m-c763b06a1ef1-dark [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-c763b06a1ef1-dark [data-look="neo"].node .neo-line path{stroke:#3f3f46;filter:none;}#m-c763b06a1ef1-dark [data-look="neo"].node circle{stroke:url(#m-c763b06a1ef1-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-c763b06a1ef1-dark [data-look="neo"].node circle .state-start{fill:#000000;}#m-c763b06a1ef1-dark [data-look="neo"].icon-shape .icon{fill:url(#m-c763b06a1ef1-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-c763b06a1ef1-dark [data-look="neo"].icon-shape .icon-neo path{stroke:url(#m-c763b06a1ef1-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-c763b06a1ef1-dark :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="m-c763b06a1ef1-dark_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-dark_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-dark_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-dark_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-dark_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-dark_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-dark_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-dark_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-dark_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-dark_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-dark_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="m-c763b06a1ef1-dark_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M268,68L272.167,68C276.333,68,284.667,68,292.333,68C300,68,307,68,310.5,68L314,68" id="m-c763b06a1ef1-dark-L_L3_L2_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_L3_L2_0" data-points="W3sieCI6MjY4LCJ5Ijo2OH0seyJ4IjoyOTMsInkiOjY4fSx7IngiOjMxOCwieSI6Njh9XQ==" data-look="classic" marker-end="url(#m-c763b06a1ef1-dark_flowchart-v2-pointEnd)"/><path d="M578,68L582.167,68C586.333,68,594.667,68,602.333,68C610,68,617,68,620.5,68L624,68" id="m-c763b06a1ef1-dark-L_L2_L1_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_L2_L1_0" data-points="W3sieCI6NTc4LCJ5Ijo2OH0seyJ4Ijo2MDMsInkiOjY4fSx7IngiOjYyOCwieSI6Njh9XQ==" data-look="classic" marker-end="url(#m-c763b06a1ef1-dark_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_L3_L2_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_L2_L1_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="m-c763b06a1ef1-dark-flowchart-L1-0" data-look="classic" transform="translate(758, 68)"><rect class="basic label-container" style="" x="-130" y="-60" width="260" height="120"/><g class="label" style="" transform="translate(-100, -45)"><rect/><foreignObject width="200" height="90"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>Слой 1. Надёжность продуктов суммарно<br />вопрос: какую надёжность мы дали бизнесу</p></span></div></foreignObject></g></g><g class="node default" id="m-c763b06a1ef1-dark-flowchart-L2-1" data-look="classic" transform="translate(448, 68)"><rect class="basic label-container" style="" x="-130" y="-60" width="260" height="120"/><g class="label" style="" transform="translate(-100, -45)"><rect/><foreignObject width="200" height="90"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>Слой 2. Инженерное усилие команды<br />вопрос: какой ценой и насколько устойчиво</p></span></div></foreignObject></g></g><g class="node default" id="m-c763b06a1ef1-dark-flowchart-L3-2" data-look="classic" transform="translate(138, 68)"><rect class="basic label-container" style="" x="-130" y="-48.75" width="260" height="97.5"/><g class="label" style="" transform="translate(-100, -33.75)"><rect/><foreignObject width="200" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>Слой 3. Качество диалога<br />вопрос: встроена ли надёжность в продукт</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="m-c763b06a1ef1-dark-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="m-c763b06a1ef1-dark-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><linearGradient id="m-c763b06a1ef1-dark-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#3f3f46" stop-opacity="1"/><stop offset="100%" stop-color="#3f3f46" stop-opacity="1"/></linearGradient></svg>
</div>
</figure><h4 id="слой-1-надёжность-продуктов-суммарно-бизнес-слой">Слой 1. Надёжность продуктов суммарно (бизнес-слой)</h4>
<p>Не «средний SLO», а покрытие и распределение:</p>
<ul>
<li><strong>Доля продуктов, у которых SLO существует, написан в терминах CUJ и формально подписан продактом.</strong> Это метрика зрелости, а не надёжности. «6 из 8 продуктов имеют подписанный SLO» говорит больше, чем любой композит.</li>
<li><strong>Доля продуктов с действующей error budget policy.</strong> Не «есть SLO», а «есть записанное правило, что делать при сгорании». Обычно эта доля сильно меньше первой — и разрыв между ними и есть фронт работ.</li>
<li><strong>Burn-rate бюджетов по всем продуктам как тепловая карта, а не среднее.</strong> Восемь строк, в каждой — сгорание за квартал. Красные клетки видно сразу, и ни одна не тонет в зелёных соседях.</li>
<li><strong>Сумма money loss за квартал</strong> — если связка <code>SLI → ₽</code> настроена. Это единственная цифра из этого слоя, которую менеджмент понимает без перевода.</li>
</ul>
<h4 id="слой-2-инженерное-усилие-команды-продуктивность">Слой 2. Инженерное усилие команды (продуктивность)</h4>
<p>Сколько стоит надёжность в человекочасах и насколько это устойчиво:</p>
<ul>
<li><strong>Toil как % времени команды.</strong> Гугловский потолок — 50% (правило из главы <a href="https://sre.google/sre-book/eliminating-toil/" rel="noopener noreferrer" target="_blank">«Eliminating Toil»</a>
 в Google SRE Book); всё, что выше, означает, что команда тонет в ручной рутине и не строит автоматизацию. Toil — отличная инженерная метрика зрелости именно потому, что растёт незаметно и душит команду медленно.</li>
<li><strong>Доля задач, переходящих от SRE обратно в продуктовую команду.</strong> Антипаттерн — «SRE как owner навсегда»: команда взяла продукт на поддержку и больше его не отпускает. Здоровая динамика — знания и ответственность постепенно возвращаются в продуктовую команду, а SRE остаётся на инструментарии и сложных случаях.</li>
<li><strong>Время от инцидента до закрытого action item</strong> — не до восстановления. Восстановили за 20 минут, а исправили причину через полгода — это плохо, и средний MTTR это скрывает, а эта метрика показывает.</li>
<li><strong>Доля постмортемов с реализованными action items.</strong> Постмортем, после которого ничего не сделали, — это терапия, а не инженерия. Эта доля показывает, учится ли команда на самом деле.</li>
</ul>
<h4 id="слой-3-качество-диалога-управленческий-слой">Слой 3. Качество диалога (управленческий слой)</h4>
<p>Самый неочевидный и самый важный слой — он меряет ровно то, о чём вся статья: встроена ли надёжность в продукт или живёт в инженерной резервации.</p>
<ul>
<li><strong>Регулярность product reliability review.</strong> Проводится ли квартальный разбор бюджета с каждым продактом — или только с теми, кто сам пришёл. Цель — со всеми и по расписанию.</li>
<li><strong>Доля продуктов, где бизнес сам приходит за обсуждением бюджета.</strong> Это лакмус. Если продакт сам спрашивает «сколько у нас бюджета осталось» — диалог здоров. Если SRE его догоняет — нет. Эта доля растёт медленно и означает культурный сдвиг, а не процессный.</li>
<li><strong>NPS/CSAT-аналог от команд разработки на сервис SRE.</strong> Команда SRE — это тоже сервис, у него есть внутренние пользователи (продуктовые команды), и их удовлетворённость измерима. Низкий внутренний CSAT при хороших технических метриках — сигнал, что SRE воспринимают как тормоз, а не как партнёра.</li>
</ul>
<aside class="callout callout--note" role="note">
  <div class="callout__icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg></div>
  <div class="callout__body"><p class="callout__title">Слой 3 и культурная готовность</p>
    <div class="callout__content"><p>Третий слой пересекается с фазой 0 «cultural preparation» в Bear SRE Framework: SRE-практики невозможны без готовности бизнеса разговаривать. Метрики этого слоя, по сути, измеряют, насколько эта готовность реальна, а не декларирована. Можно вести их и как самостоятельную раскладку — но если у тебя уже есть рамка зрелости, слой 3 хорошо в неё ложится.</p></div>
  </div>
</aside><p>Соберём три слоя в одну таблицу — её удобно держать перед глазами при отчёте:</p>
<table>
  <thead>
      <tr>
          <th>Слой</th>
          <th>Вопрос</th>
          <th>Пример метрики</th>
          <th>Какой агрегат заменяет</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1. Надёжность продуктов</td>
          <td>Какую надёжность мы дали бизнесу</td>
          <td>Доля продуктов с подписанным CUJ-SLO; money loss за квартал; burn-rate тепловой картой</td>
          <td>Composite SLO</td>
      </tr>
      <tr>
          <td>2. Инженерное усилие</td>
          <td>Какой ценой и насколько устойчиво</td>
          <td>Toil %; время до закрытого action item; доля постмортемов с реализованными AI</td>
          <td>Средний MTTR</td>
      </tr>
      <tr>
          <td>3. Качество диалога</td>
          <td>Встроена ли надёжность в продукт</td>
          <td>Регулярность reliability review; доля «бизнес пришёл сам»; внутренний CSAT на SRE</td>
          <td>Число инцидентов</td>
      </tr>
  </tbody>
</table>
<p>Ни одна метрика из правой колонки («какой агрегат заменяет») не исчезает полностью — MTTR и счётчик инцидентов остаются полезными для внутренней диагностики. Но <strong>как метрика команды перед менеджментом</strong> они проигрывают трёхслойной раскладке, потому что усредняют то, что усреднять нельзя.</p>
<h3 id="как-это-звучит-в-отчёте-менеджменту">Как это звучит в отчёте менеджменту</h3>
<p>Финальная проверка всей раскладки — как команда отчитывается наверх. Сравни два варианта.</p>
<aside class="callout callout--warn" role="note">
  <div class="callout__icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg></div>
  <div class="callout__body"><p class="callout__title">Не делай SLO продуктов прямым KPI команды</p>
    <div class="callout__content"><p>Заманчиво объявить «продуктовую надёжность KPI команды SRE» — но это прямой путь к токсичным SLO. По <a href="https://ttttt.me/jtprogru_channel/4460" rel="noopener noreferrer" target="_blank">закону Гудхарта</a>
, как только SLO становится оценкой команды, она начинает оптимизировать цифру, а не надёжность: заниженные таргеты, «неудобные» события вне знаменателя, споры «считать ли инцидент инцидентом». Поэтому меряй команду не <strong>абсолютом</strong> SLO (он про продукт и принадлежит продакту), а <strong>дельтой и охватом</strong> — на сколько продуктов распространили подписанный SLO и policy, сократилось ли сгорание бюджета и money loss, вырос ли охват зрелым диалогом (слой 3). Занижением таргета это не саботируешь — потому и отчёт ниже построен на «было 4 → стало 6», а не на «composite SLO 99.94%».</p></div>
  </div>
</aside><p><strong>Плохо (агрегат):</strong> «У нас средний MTTR 22 минуты и composite SLO 99.94%». Менеджмент кивает, ничего не понимает, ни одно решение не меняется.</p>
<p><strong>Хорошо (три слоя):</strong> «За квартал укрепили подписанный SLO с error budget policy у 6 из 8 продуктов (было 4), суммарное сгорание бюджета упало на 35%, бизнес-потери от инцидентов сократились на N рублей. Toil держим на 40%. Два продукта вернули в зону ответственности продуктовых команд. Осталось два продукта без политики — это фронт на следующий квартал».</p>
<p>Второй отчёт показывает движение, цену и план. Это и есть язык, на котором SRE-команда разговаривает с менеджментом, когда продуктов больше одного, — не «средняя температура», а «вот что мы дали бизнесу и как конвертировали инженерное усилие в продуктовый результат».</p>
<h2 id="что-сделать-завтра-утром">Что сделать завтра утром</h2>
<p>Чек-лист «куда вернуться», когда дочитал. Пять вопросов — если на какой-то нет ответа, там и фронт работ.</p>
<ol>
<li><strong>Какой product reliability review встроен в наш квартальный план?</strong> Если ответ «никакой» или «по запросу» — начни с того, чтобы поставить в календарь регулярную встречу по бюджету с каждым продуктовым владельцем.</li>
<li><strong>Кто из бизнеса формально подписал error budget policy — и подписал ли вообще?</strong> Если не можешь назвать имя — у тебя SLO-артефакт, а не контракт. Это задача номер один.</li>
<li><strong>На какой панели я вижу „health по сценарию“, а не „health по сервису“?</strong> Если только по сервису — твои SLI повешены на ручки, а не на пути, и ты не видишь того, что чувствует пользователь.</li>
<li><strong>Сколько раз за последний квартал бизнес сам поднял разговор о трейд-оффе „фича против надёжности“?</strong> Если ноль — диалог пока односторонний, и слой 3 у тебя в красной зоне.</li>
<li><strong>Какой из метрик трёх слоёв у нас нет — и почему?</strong> Чаще всего отсутствует слой 3 (качество диалога), потому что его сложнее всего мерить. Но именно он отличает зрелую практику от набора дашбордов.</li>
</ol>
<h2 id="заключение">Заключение</h2>
<p>В «чертеже» я доказывал, что архитектура без SLO — это эстетика, а не инженерия. Эта статья добавляет вторую половину: <strong>SLO без диалога — это дашборд, а не управление.</strong></p>
<p>Чертёж надёжности сам по себе мёртв. Его надо защищать, торговать им и переписывать вместе с бизнесом каждый квартал. Технический инструмент — SLI, SLO, error budget — становится управленческим ровно в тот момент, когда у инженеров и бизнеса появляется одна картинка целевой надёжности и одна валюта компромиссов. До этого момента у тебя есть только красивые графики и предчувствия.</p>
<p>Три вещи, ради которых стоило городить всю статью:</p>
<ul>
<li><strong>Диалог — это формат принятия решений</strong>, а не презентация. Его сердце — записанная error budget policy, подписанная продуктовым владельцем.</li>
<li><strong>На собесе по SLO проверяют переговорный навык</strong>, а не арифметику. Сильный ответ начинается со сценария и денег и возвращает бизнесу выбор.</li>
<li><strong>Метрики команды при мультипродукте — это три слоя, а не один агрегат.</strong> Среднее по больнице прячет именно ту боль, ради которой метрику заводили.</li>
</ul>
<p>Надёжность не «достигается». Она каждый квартал заново строится в диалоге — и проигрывается ровно там, где этот диалог замолчал.</p>
<p>Спасибо, что дочитал до конца. Это продолжение цикла, начатого статьёй <a href="/posts/slo-as-architecture-blueprint/">«SLO как чертёж архитектуры»</a>
. Если у тебя есть свой опыт диалога с бизнесом о надёжности — особенно истории, как error budget policy реально остановила релиз или как менялись метрики команды с ростом числа продуктов, — буду рад услышать.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></description>
      <content:encoded><![CDATA[<style>/* Inline-CSS, который тема вкладывает в <description> каждого item'а
   RSS-фида (layouts/index.rss.xml). RSS-ридеры (Feedly, Inoreader,
   NetNewsWire) уважают <style> внутри description с переменной
   степенью энтузиазма — это базовый fallback, достаточный для читаемой
   типографики, не более.

   Цвета продублированы из 00-vars.css (light-палитра) — поправь
   синхронно при изменении --bg / --text / --accent / --border. */

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  line-height: 1.6;
  color: #1c1c1f;
  max-width: 720px;
  margin: 0 auto;
  padding: 1em;
}
h1, h2, h3 { line-height: 1.25; margin-top: 1.4em; }
a { color: #c2410c; }
pre {
  background: #1e1e24;
  color: #e8e6df;
  padding: 1em;
  border-radius: 6px;
  overflow-x: auto;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.9em;
}
code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  background: #f3f1ed;
  padding: 0.1em 0.4em;
  border-radius: 4px;
}
pre code { background: transparent; padding: 0; }
blockquote {
  border-left: 3px solid #c2410c;
  padding-left: 1em;
  color: #5b5b62;
  font-style: italic;
  margin-left: 0;
}
img { max-width: 100%; height: auto; border-radius: 6px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #e5e3dc; padding: 6px 10px; text-align: left; }
</style><div><p>Привет, <code>%username%</code>! В прошлой статье — <a href="/posts/slo-as-architecture-blueprint/">«SLO как чертёж архитектуры»</a>
 — я закончил тезисом, который тут же хочется развить: SLO выбирается не инженерами в одиночку, а вместе с бизнесом, потому что число в нём привязано к деньгам. А «вместе с бизнесом» в реальности чаще всего выглядит так: SRE придумал SLO, нарисовал дашборд, показал на демо, продакт покивал — и все разошлись. Чертёж готов. Надёжность&hellip; не выросла.</p>
<p>Так бывает, потому что чертёж сам по себе не работает. SLO/SLI/error budget — это <strong>не отчётный артефакт, а язык переговоров</strong>. Технический инструмент превращается в управленческий ровно в тот момент, когда у инженеров и у бизнеса одна и та же картинка целевой надёжности и одна и та же валюта компромиссов. Пока этого нет — у тебя есть красивый график, который никто не использует для принятия решений.</p>
<p>В этой статье я разворачиваю три практических следствия из этого тезиса, и все три — продолжение того же кейса с маркетплейсом (поиск каталога, 50M товаров, 30k RPS на пике), который я гонял в «чертеже»:</p>
<ol>
<li><strong>Диалог с бизнесом — это не презентация SLO, а формат принятия решений.</strong> SRE не «продаёт» таргет продакту, а вместе с ним выбирает уровень надёжности, политику бюджета ошибок и порядок разрешения спора «фичи против надёжности».</li>
<li><strong>System Design-собес проверяет именно этот навык.</strong> Большинство «вопросов по SLO» — не про арифметику девяток, а про умение собрать разговор с бизнесом, удержать рамку трейд-оффов и перевести «бизнес хочет 100%» в инженерную работу.</li>
<li><strong>Метрики SRE-команды меняются, когда продуктов больше одного.</strong> Ни «MTTR по компании», ни «SLO по сервису» как метрика команды не работают, когда команда обслуживает 5–10 продуктов. Нужен сводный язык.</li>
</ol>
<p>Если первая статья была про то, <strong>какой</strong> чертёж рисовать, то эта — про то, <strong>как сделать так, чтобы по чертежу действительно построили</strong>, а не повесили его в рамке на стену.</p>
<h2 id="что-ты-унесёшь-из-статьи">Что ты унесёшь из статьи</h2>
<p>Статья длинная (~40 000 знаков). Сразу — что заберёт каждая роль:</p>
<ul>
<li><strong>SRE / SRE-lead.</strong> Как перестать «отдавать SLO» и начать вести по нему диалог: три признака, что разговор не состоялся; error budget policy как продуктовый, а не инженерный артефакт; и — отдельным блоком — какие метрики брать на команду, когда продуктов много, чтобы они не врали.</li>
<li><strong>Продакт / аналитик.</strong> Что именно бизнес должен уметь произнести сам (а не получать от SRE как откровение): где у нас критичные пользовательские пути, сколько стоит девятка в деньгах, кто и когда жмёт на стоп.</li>
<li><strong>Кандидат / интервьюер на System Design.</strong> Пять типовых собес-кейсов «про SLO», которые на самом деле проверяют переговорный навык, и разбор, что в них считается сильным ответом, а что — провалом.</li>
</ul>
<p>Общий блок для всех: почему <strong>надёжность нельзя «сделать», её можно только постоянно переторговывать</strong> — и как выглядит этот процесс в зрелой команде.</p>
<h2 id="tldr-если-читать-дальше-уже-некогда">TL;DR (если читать дальше уже некогда)</h2>
<p>Четыре тезиса, к которым приходит статья:</p>
<ol>
<li><strong>SLO без error budget policy — это украшение дашборда.</strong> Контракт из SLO делает записанное правило: что происходит, когда бюджет сгорел, и кто принимает по этому поводу решение. Само число ничего не гарантирует. Без правила — это график, мимо которого все ходят.</li>
<li><strong>Надёжность — это не состояние, а переговорный процесс.</strong> Её не «достигают» один раз. Каждый квартал бизнес и SRE заново выбирают уровень, потому что меняются нагрузка, деньги и приоритеты. SLO, который не пересматривают, врёт уже через полгода.</li>
<li><strong>На собесе по SLO проверяют не формулы, а умение поменять поведение бизнеса.</strong> Сильный ответ всегда начинается со сценария и денег, а не с топологии и девяток. «100% доступности» — не повод сказать «нельзя», а повод показать цену.</li>
<li><strong>Метрики SRE-команды при мультипродукте раскладываются на три слоя</strong> (надёжность продуктов / инженерное усилие / качество диалога) — один агрегат тут не справляется. Среднее по больнице — MTTR, composite SLO, число инцидентов — прячет ровно то, ради чего метрику заводили.</li>
</ol>
<p>Дальше — как до этого дойти. Если интересует только управленческая кульминация — переходи сразу к разделу <a href="#%d0%bc%d0%b5%d1%82%d1%80%d0%b8%d0%ba%d0%b8-sre-%d0%ba%d0%be%d0%bc%d0%b0%d0%bd%d0%b4%d1%8b-%d0%b4%d0%bb%d1%8f-%d0%bc%d1%83%d0%bb%d1%8c%d1%82%d0%b8%d0%bf%d1%80%d0%be%d0%b4%d1%83%d0%ba%d1%82%d0%b0">Метрики SRE-команды для мультипродукта</a>
.</p>
<h2 id="чертёж-без-переговоров--это-просто-дашборд">Чертёж без переговоров — это просто дашборд</h2>
<p>Начнём с диагноза. В прошлой статье SLO получился как инженерный объект: числитель, знаменатель, окно, бюджет ошибок. Всё аккуратно. Но у этого объекта есть два режима существования, и разница между ними — это и есть вся статья.</p>
<h3 id="slo-как-артефакт-против-slo-как-контракта">SLO как артефакт против SLO как контракта</h3>
<p><strong>SLO-артефакт</strong> — это число на дашборде. Его придумали, согласовали галочкой, поставили мониторинг, иногда даже сделали красивый burn-rate-график. Он существует. Он измеряется. И он ни на что не влияет, потому что ни одно решение в компании не принимается, глядя на него.</p>
<p><strong>SLO-контракт</strong> — это то же число, но вокруг него выстроен процесс. Когда бюджет ошибок тает быстрее плана — кто-то останавливает рискованные деплои. Когда бюджет сгорел — спринт переключается на надёжность, и это не подвиг отдельного SRE, а записанное правило. Когда продакт хочет выкатить фичу к Чёрной пятнице — он сам спрашивает «сколько у нас осталось бюджета», потому что знает, что это его валюта тоже.</p>
<p>Разница видна по тому, как объект ведёт себя в жизни команды:</p>
<table>
  <thead>
      <tr>
          <th></th>
          <th>SLO-артефакт</th>
          <th>SLO-контракт</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Где живёт</td>
          <td>На дашборде</td>
          <td>В процессе принятия решений</td>
      </tr>
      <tr>
          <td>Кто смотрит</td>
          <td>Дежурный SRE</td>
          <td>Продакт и SRE вместе</td>
      </tr>
      <tr>
          <td>Что происходит при сгорании</td>
          <td>Ничего («ну красный»)</td>
          <td>Срабатывает записанное правило</td>
      </tr>
      <tr>
          <td>Кто «владелец» числа</td>
          <td>Инженеры</td>
          <td>Продуктовый владелец + SRE</td>
      </tr>
      <tr>
          <td>Роль в споре «фича vs надёжность»</td>
          <td>Никакой</td>
          <td>Валюта, в которой спор решается</td>
      </tr>
      <tr>
          <td>Пересмотр</td>
          <td>Когда вспомнят</td>
          <td>Раз в квартал, ритуалом</td>
      </tr>
  </tbody>
</table>
<p>Разница между ними — не в качестве дашборда. Она в том, <strong>встроен ли SLO в принятие решений</strong>. И встроить его туда нельзя в одностороннем порядке: SRE не может «назначить» бизнесу, что теперь решения принимаются по бюджету ошибок. Это можно только договорить.</p>
<aside class="callout callout--note" role="note">
  <div class="callout__icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg></div>
  <div class="callout__body"><p class="callout__title">Главная подмена</p>
    <div class="callout__content"><p>«Мы внедрили SLO» почти всегда означает «мы настроили SLI и нарисовали дашборд». Это внедрение <strong>артефакта</strong>. Внедрение <strong>контракта</strong> — это когда на вопрос «что у нас происходит при сгорании бюджета» отвечает не SRE, а продакт, и отвечает одинаково с SRE. Пока ответы расходятся — контракта нет, есть график.</p></div>
  </div>
</aside><h3 id="три-признака-что-разговор-не-состоялся">Три признака, что разговор не состоялся</h3>
<p>Проверить, в каком режиме у тебя SLO, можно по трём симптомам. Если узнаёшь хотя бы один — диалога не было, был монолог SRE.</p>
<ol>
<li><strong>SLO «спущен сверху».</strong> Инженеры посчитали девятки, выбрали таргет «по аналогии с большими» и поставили продакта перед фактом. Продакт не участвовал в выборе числа — значит, он не считает его своим и не будет на него опираться в спорах. Для него это «инженерная штука», а не общий контракт.</li>
<li><strong>Нет error budget policy.</strong> SLO есть, бюджет считается, дашборд горит то зелёным, то красным. Но что конкретно делать, когда бюджет на исходе — нигде не записано. В итоге красный дашборд не меняет ничего: «ну красный, ну ладно, катим дальше».</li>
<li><strong>На пересечении бюджета никто не останавливает фичи.</strong> Самый жёсткий признак. Бюджет сгорел в ноль, а релизы продолжают выкатываться, потому что «дедлайн важнее». Это значит, что SLO проигрывает любому продуктовому приоритету — то есть фактически его нет.</li>
</ol>
<p>Все три признака — про одно: <strong>SLO не имеет оперативных последствий</strong>. А инструмент без последствий — это декорация.</p>
<h3 id="кейс-mercari-переименовать-мало-нужен-ритуал">Кейс Mercari: переименовать мало, нужен ритуал</h3>
<p>Хороший пример того, как легко перепутать артефакт с контрактом, — переход к User Journey SLO. Команды (в том числе Mercari, описавшие это в посте <a href="https://engineering.mercari.com/en/blog/entry/20241204-keeping-user-journey-slos-up-to-date-with-e2e-testing-in-a-microservices-architecture/" rel="noopener noreferrer" target="_blank">«Keeping User Journey SLOs Up-to-Date with E2E Testing»</a>
 в декабре 2024 года) приходят к тому, что SLO «на сервис» прячет пользовательскую боль, и переезжают на SLO, привязанные к пользовательскому пути. Идея правильная — она ровно из «чертежа»: SLI вешаются на шаги критичного пути, а не на сервис целиком.</p>
<p>Но вот ловушка: само по себе переименование «SLO сервиса X» → «SLO пользовательского пути Y» ничего не меняет, если за ним не стоит <strong>сопровождающий ритуал с продактом</strong>. Если User Journey SLO живёт там же, где жил старый — на дашборде, который смотрит только дежурный SRE, — это просто более точный артефакт. Та же декорация, только лучше нарисованная.</p>
<p>Работает переход тогда, когда вместе с новым SLO появляется регулярная встреча, на которой продакт смотрит на бюджет своего пути и принимает по нему решения. Не SRE показывает — продакт смотрит и решает. Переименование — это 10% работы. Остальные 90% — встроить новый объект в процесс продукта.</p>
<h3 id="почему-без-продуктового-владельца-это-не-лечится">Почему без продуктового владельца это не лечится</h3>
<p>Здесь стоит развести два понятия — <strong>продуктовую надёжность</strong> (видит ли пользователь, что сценарий работает) и <strong>техническую доступность</strong> (отвечает ли ручка <code>/search</code> двухсоткой). Важное следствие из этого разведения: продуктовая надёжность по определению не может принадлежать только SRE.</p>
<p>SRE владеет технической доступностью — это его зона: инфраструктура, репликация, failover, capacity. Но «работает ли поиск для пользователя так, что он покупает» — это вопрос, на который SRE физически не может ответить в одиночку, потому что «так, что он покупает» — это продуктовое определение, а не техническое. Кто решает, что пустая выдача по валидному запросу — это провал, а не «технически 200 OK»? Продакт. Кто решает, что цена на карточке старше минуты — это инцидент? Продакт.</p>
<p>Поэтому <strong>у продуктовой надёжности должен быть продуктовый владелец</strong>. Не «SRE отвечает за надёжность» — это и есть корень всех проблем из предыдущего раздела. А «SRE отвечает за инструментарий и техническую доступность, продакт — за то, что считается надёжностью с точки зрения пользователя, и они держат общий SLO». Диалог не состоится, пока с продуктовой стороны нет того, кто за этот SLO отвечает головой.</p>
<h2 id="что-мы-на-самом-деле-обсуждаем-с-бизнесом">Что мы на самом деле обсуждаем с бизнесом</h2>
<p>Допустим, продуктовый владелец есть и готов разговаривать. О чём конкретно идёт разговор? Не «покажи мне дашборд» — это не разговор. Настоящий диалог о надёжности крутится вокруг четырёх вещей.</p>
<h3 id="1-таргет-как-бюджет-на-компромисс">1. Таргет как бюджет на компромисс</h3>
<p>Главное, что должен понять бизнес: <strong>высокая надёжность — это не бесплатно и не всегда хорошо</strong>. Это позиция на шкале трейд-оффов.</p>
<ul>
<li>Высокий SLO = низкая скорость фич (бюджет ошибок мал, каждый релиз — ставка), дорогая инфраструктура (резервирование, регионы), медленные релизы (канарейка, постепенный rollout).</li>
<li>Низкий SLO = быстрые фичи, дешёвая инфраструктура, но больше видимых пользователю сбоев.</li>
</ul>
<p>Из «чертежа» помним конкретные множители для нашего маркетплейса: переход с 99.9% на 99.99% — это <code>4–6×</code> → <code>15–25×</code> baseline по инфраструктуре и <code>2–3×</code> → <code>8–10×</code> по людям. Это не «инженеры хотят красивую цифру». Это бизнес-решение, потому что платит за него бизнес, и отказывается от скорости фич — тоже бизнес.</p>
<p>Ключевая фраза, которую SRE должен уметь произнести в этом разговоре, звучит примерно так:</p>
<blockquote><p>«Если снизим SLO поиска с 99.99% до 99.9% — освободим вот этот регион и вот эту часть дежурной нагрузки, сможем катить фичи в полтора раза быстрее. Заплатим за это вот таким ростом видимых сбоев на пике. Берём?»</p>
</blockquote><p>Это и есть перевод надёжности в валюту, понятную обеим сторонам. Не «давайте сделаем понадёжнее», а «вот цена, вот что освобождается, решаем вместе».</p>
<h3 id="2-error-budget-policy-правила-пишутся-до-пожара-а-не-во-время">2. Error budget policy: правила пишутся до пожара, а не во время</h3>
<p>Error budget policy — это <strong>заранее зафиксированные правила игры</strong>. Не «что мы будем делать, когда бюджет сгорит» (это решается в панике и проигрывается дедлайну), а «что происходит автоматически, когда бюджет сгорел» — написанное и согласованное обеими сторонами заранее.</p>
<p>Минимальная политика отвечает на четыре вопроса:</p>
<ul>
<li><strong>Кто и при каком условии останавливает релизы?</strong> Например: при burn-rate выше <code>14.4×</code> за час — автоматический freeze рискованных деплоев до конца окна.</li>
<li><strong>Кто разрешает продолжить?</strong> Не «инженер решил» и не «продакт продавил», а названная роль с названным условием.</li>
<li><strong>Что переходит в roadmap при сгоревшем бюджете?</strong> Reliability-задачи получают приоритет над фичами — и это записано, а не выпрашивается каждый раз заново.</li>
<li><strong>Когда и как пересматривается сам SLO?</strong> Раз в квартал — короткий ритуал «изменилось ли что-то в бизнесе или системе, что меняет нужное число».</li>
</ul>
<p>На практике это умещается на одну страницу — по образцу error budget policy из главы <a href="https://sre.google/workbook/implementing-slos/" rel="noopener noreferrer" target="_blank">«Implementing SLOs»</a>
 в Google SRE Workbook. Для поиска нашего маркетплейса политика могла бы выглядеть так:</p>
<blockquote><p><strong>Error budget policy — поиск каталога (SLO 99.9%, окно 30 дней)</strong></p>
<ul>
<li><strong>Жёлтая зона</strong> (потрачено 50% бюджета): уведомление в канал продукта, ретроспектива на ближайшем синке, новых рискованных экспериментов не начинаем.</li>
<li><strong>Красная зона</strong> (потрачено 90%): freeze рискованных деплоев — катим только хотфиксы и security-патчи. Reliability-задачи поднимаются над фичами в текущем спринте.</li>
<li><strong>Бюджет исчерпан</strong> (100%): полный freeze фич до конца окна. Эскалация продуктовому владельцу, обязательный разбор причин.</li>
<li><strong>Кто снимает freeze:</strong> продуктовый владелец по согласованию с SRE-lead, не раньше чем burn-rate вернулся к норме.</li>
<li><strong>Пересмотр SLO:</strong> первый понедельник квартала, участвуют продакт и SRE-lead.</li>
<li><strong>Подписали:</strong> <em>имя продуктового владельца</em>, <em>имя SRE-lead</em>, дата.</li>
</ul>
</blockquote><p>Эта страница важнее любого дашборда. Дашборд показывает, что бюджет горит. Страница говорит, что с этим делать и кто за это отвечает.</p>
<aside class="callout callout--warn" role="note">
  <div class="callout__icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg></div>
  <div class="callout__body"><p class="callout__title">Без политики SLO проигрывает всегда</p>
    <div class="callout__content"><p>Если решение «морозим или катим» принимается в момент пожара, оно принимается властью: кто выше по иерархии или ближе к CEO, тот и победил. Записанная заранее политика — это способ вынуть это решение из-под давления момента. Её главная ценность не в тексте, а в том, что её согласовали, когда никто не был в панике.</p></div>
  </div>
</aside><p>Важнейшее уточнение, которое часто упускают: <strong>error budget policy — это продуктовый артефакт, а не инженерный</strong>. Его подписывает не тимлид SRE «для себя», а продуктовый владелец — потому что это он соглашается, что при сгоревшем бюджете его фичи подождут. Подпись здесь не метафора: должно быть понятно, кто конкретно сказал «да» этим правилам. Если не можешь назвать имя — политики нет.</p>
<h3 id="3-перевод-девяток-в-деньги">3. Перевод девяток в деньги</h3>
<p>Бизнесу нужны не проценты, а валюта. «99.9% против 99.95%» для продакта — пустой звук, пока ты не показал, что стоит за этой разницей в деньгах. Поэтому в зрелом диалоге всегда есть связка <code>SLI → ₽</code>.</p>
<p>Берём наш маркетплейс. Из «чертежа»: GMV порядка 1 млрд ₽ в день, поиск кормит 40–70% покупок, каждые <code>+100 ms</code> латентности на ключевом read path стоят примерно <code>−0.5…1.5%</code> конверсии. Отсюда — простой мост:</p>
$$ \text{Стоимость простоя} = \text{GMV в час} \times \text{доля задетого трафика} \times \text{длительность} $$<p>Дальше бюджет ошибок перестаёт быть процентом и становится деньгами. Сгоревший за инцидент бюджет — это не «−2% за час на графике», а «вот столько недополученной выручки, если такой инцидент повторится на пике». Burn-rate из множителя (<code>14.4×</code>, <code>36×</code> — подробно про него в статье <a href="/posts/burn-rate-is-not-speed/">«Скорость сгорания бюджета ошибок»</a>
) превращается в скорость утечки денег: при таком-то burn-rate на пике Чёрной пятницы мы теряем столько-то рублей в минуту.</p>
<p>Посчитаем на пальцах для одного и того же 15-минутного инцидента в поиске — полная недоступность пути. GMV 1 млрд ₽ в день размазан неравномерно: обычным днём через поиск проходит порядка 400 млн ₽ выручки (предположим, 40% покупок стартуют с поиска), на пике распродажи дневной GMV умножается в <code>×3–5</code>, и доля стартующих с поиска покупок растёт.</p>
<table>
  <thead>
      <tr>
          <th></th>
          <th>Обычный вторник</th>
          <th>Пик распродажи</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Выручка через поиск за день</td>
          <td>~400 млн ₽</td>
          <td>~1,5 млрд ₽</td>
      </tr>
      <tr>
          <td>Выручка через поиск в час (грубо)</td>
          <td>~17 млн ₽</td>
          <td>~120 млн ₽</td>
      </tr>
      <tr>
          <td>Полный простой поиска 15 минут</td>
          <td>~4,2 млн ₽</td>
          <td>~30 млн ₽</td>
      </tr>
      <tr>
          <td>Тот же burn-rate в долях бюджета</td>
          <td>один и тот же <code>~50×</code></td>
          <td>один и тот же <code>~50×</code></td>
      </tr>
  </tbody>
</table>
<p>Цифры грубые и зависят от профиля трафика — но порядок и так говорит главное: <strong>один и тот же инцидент с одним и тем же burn-rate стоит на пике в разы дороже</strong>. Поэтому «потеряли 15 минут» — бессмысленная фраза без контекста «когда». А burn-rate как безразмерный множитель тут особенно удобен: <code>50×</code> одинаково тревожен и во вторник, и в Чёрную пятницу, просто в деньгах разворачивается по-разному.</p>
<p>Это разговор, который продакт понимает мгновенно. Не «у нас burn-rate 14.4», а «при текущем burn-rate мы за час пикового трафика теряем выручку, равную недельной зарплате команды — продолжаем катить?». Конвертация в деньги и переводит SLO из инженерной плоскости в управленческую.</p>
<aside class="callout callout--note" role="note">
  <div class="callout__icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg></div>
  <div class="callout__body"><p class="callout__title">Сезонность — это не деталь, это половина разговора</p>
    <div class="callout__content"><p>Пять минут даунтайма обычным вторником и пять минут в Чёрную пятницу — это разные деньги в десятки раз. Бюджет ошибок «горит» неравномерно: на пике RPS ты расходуешь его в разы быстрее. Поэтому проектировать SLO и считать стоимость инцидента надо на пик, а не на среднюю нагрузку. Бизнес это, кстати, обычно понимает лучше инженеров — он живёт сезонностью.</p></div>
  </div>
</aside><h3 id="4-где-у-нас-критичные-пользовательские-пути">4. «Где у нас критичные пользовательские пути»</h3>
<p>И последнее, самое неочевидное. Список критичных пользовательских путей (CUJ — critical user journey) бизнес должен уметь произнести <strong>сам</strong>. Это не то, что SRE приносит продакту как откровение — «смотри, я тут проанализировал, у вас критичен поиск». Если CUJ известны только инженерам, значит, бизнес не владеет собственной надёжностью.</p>
<p>Хорошая проверка зрелости диалога: спроси продакта «назови три сценария, простой которых на 30 минут стоит нам больше всего». Если он отвечает не задумываясь — диалог здоровый. Если лезет к SRE «а какие у нас там пути» — надёжность пока живёт в инженерной резервации.</p>
<p>Для нашего маркетплейса CUJ — это путь «пришёл с намерением купить → нашёл → выбрал → положил в корзину → оплатил». И продакт должен понимать, что поиск (вход в этот путь) и оплата (выход) — разного класса критичности, и что на них вешаются разные SLO. Это понимание — не бонус, это условие, без которого все предыдущие три пункта повисают в воздухе.</p>
<h3 id="диалог--это-цикл-а-не-презентация">Диалог — это цикл, а не презентация</h3>
<p>Сложим четыре пункта вместе. Диалог о надёжности — это не разовое «защитили SLO на демо», а повторяющийся цикл:</p>
<figure class="mermaid mermaid--prerendered" aria-label="Mermaid diagram">
<div class="mermaid-svg mermaid-svg--light">
<svg id="m-6645021c4c1a-light" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 1710.91px; background-color: transparent;" viewBox="0 0 1710.90625 148.5" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#m-6645021c4c1a-light{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;fill:#1c1c1f;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#m-6645021c4c1a-light .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#m-6645021c4c1a-light .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#m-6645021c4c1a-light .error-icon{fill:#fee2e2;}#m-6645021c4c1a-light .error-text{fill:#7f1d1d;stroke:#7f1d1d;}#m-6645021c4c1a-light .edge-thickness-normal{stroke-width:1px;}#m-6645021c4c1a-light .edge-thickness-thick{stroke-width:3.5px;}#m-6645021c4c1a-light .edge-pattern-solid{stroke-dasharray:0;}#m-6645021c4c1a-light .edge-thickness-invisible{stroke-width:0;fill:none;}#m-6645021c4c1a-light .edge-pattern-dashed{stroke-dasharray:3;}#m-6645021c4c1a-light .edge-pattern-dotted{stroke-dasharray:2;}#m-6645021c4c1a-light .marker{fill:#5b5b62;stroke:#5b5b62;}#m-6645021c4c1a-light .marker.cross{stroke:#5b5b62;}#m-6645021c4c1a-light svg{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;}#m-6645021c4c1a-light p{margin:0;}#m-6645021c4c1a-light .label{font-family:Inter,system-ui,-apple-system,sans-serif;color:#1c1c1f;}#m-6645021c4c1a-light .cluster-label text{fill:#1c1c1f;}#m-6645021c4c1a-light .cluster-label span{color:#1c1c1f;}#m-6645021c4c1a-light .cluster-label span p{background-color:transparent;}#m-6645021c4c1a-light .label text,#m-6645021c4c1a-light span{fill:#1c1c1f;color:#1c1c1f;}#m-6645021c4c1a-light .node rect,#m-6645021c4c1a-light .node circle,#m-6645021c4c1a-light .node ellipse,#m-6645021c4c1a-light .node polygon,#m-6645021c4c1a-light .node path{fill:#ffffff;stroke:#c8c5bb;stroke-width:1px;}#m-6645021c4c1a-light .rough-node .label text,#m-6645021c4c1a-light .node .label text,#m-6645021c4c1a-light .image-shape .label,#m-6645021c4c1a-light .icon-shape .label{text-anchor:middle;}#m-6645021c4c1a-light .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#m-6645021c4c1a-light .rough-node .label,#m-6645021c4c1a-light .node .label,#m-6645021c4c1a-light .image-shape .label,#m-6645021c4c1a-light .icon-shape .label{text-align:center;}#m-6645021c4c1a-light .node.clickable{cursor:pointer;}#m-6645021c4c1a-light .root .anchor path{fill:#5b5b62!important;stroke-width:0;stroke:#5b5b62;}#m-6645021c4c1a-light .arrowheadPath{fill:rgba(255, 255, 255, 0);}#m-6645021c4c1a-light .edgePath .path{stroke:#5b5b62;stroke-width:1px;}#m-6645021c4c1a-light .flowchart-link{stroke:#5b5b62;fill:none;}#m-6645021c4c1a-light .edgeLabel{background-color:#fafaf7;text-align:center;}#m-6645021c4c1a-light .edgeLabel p{background-color:#fafaf7;}#m-6645021c4c1a-light .edgeLabel rect{opacity:0.5;background-color:#fafaf7;fill:#fafaf7;}#m-6645021c4c1a-light .labelBkg{background-color:rgba(250, 250, 247, 0.5);}#m-6645021c4c1a-light .cluster rect{fill:#f3f1ed;stroke:#c8c5bb;stroke-width:1px;}#m-6645021c4c1a-light .cluster text{fill:#1c1c1f;}#m-6645021c4c1a-light .cluster span{color:#1c1c1f;}#m-6645021c4c1a-light div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:12px;background:#fed7aa;border:1px solid #c2410c;border-radius:2px;pointer-events:none;z-index:100;}#m-6645021c4c1a-light .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#1c1c1f;}#m-6645021c4c1a-light rect.text{fill:none;stroke-width:0;}#m-6645021c4c1a-light .icon-shape,#m-6645021c4c1a-light .image-shape{background-color:#fafaf7;text-align:center;}#m-6645021c4c1a-light .icon-shape p,#m-6645021c4c1a-light .image-shape p{background-color:#fafaf7;padding:2px;}#m-6645021c4c1a-light .icon-shape .label rect,#m-6645021c4c1a-light .image-shape .label rect{opacity:0.5;background-color:#fafaf7;fill:#fafaf7;}#m-6645021c4c1a-light .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#m-6645021c4c1a-light .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#m-6645021c4c1a-light .node .neo-node{stroke:#c8c5bb;}#m-6645021c4c1a-light [data-look="neo"].node rect,#m-6645021c4c1a-light [data-look="neo"].cluster rect,#m-6645021c4c1a-light [data-look="neo"].node polygon{stroke:url(#m-6645021c4c1a-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-6645021c4c1a-light [data-look="neo"].node path{stroke:url(#m-6645021c4c1a-light-gradient);stroke-width:1px;}#m-6645021c4c1a-light [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-6645021c4c1a-light [data-look="neo"].node .neo-line path{stroke:#c8c5bb;filter:none;}#m-6645021c4c1a-light [data-look="neo"].node circle{stroke:url(#m-6645021c4c1a-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-6645021c4c1a-light [data-look="neo"].node circle .state-start{fill:#000000;}#m-6645021c4c1a-light [data-look="neo"].icon-shape .icon{fill:url(#m-6645021c4c1a-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-6645021c4c1a-light [data-look="neo"].icon-shape .icon-neo path{stroke:url(#m-6645021c4c1a-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-6645021c4c1a-light :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="m-6645021c4c1a-light_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-light_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-light_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-light_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-light_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-light_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-light_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-light_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-light_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-light_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-light_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="m-6645021c4c1a-light_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M254.531,63.811L258.698,62.634C262.865,61.457,271.198,59.104,278.865,57.927C286.531,56.75,293.531,56.75,297.031,56.75L300.531,56.75" id="m-6645021c4c1a-light-L_CUJ_Target_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_CUJ_Target_0" data-points="W3sieCI6MjU0LjUzMTI1LCJ5Ijo2My44MTA4MDcyNTA1MDA1OH0seyJ4IjoyNzkuNTMxMjUsInkiOjU2Ljc1fSx7IngiOjMwNC41MzEyNSwieSI6NTYuNzV9XQ==" data-look="classic" marker-end="url(#m-6645021c4c1a-light_flowchart-v2-pointEnd)"/><path d="M563.578,56.75L567.745,56.75C571.911,56.75,580.245,56.75,587.911,56.75C595.578,56.75,602.578,56.75,606.078,56.75L609.578,56.75" id="m-6645021c4c1a-light-L_Target_Policy_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Target_Policy_0" data-points="W3sieCI6NTYzLjU3ODEyNSwieSI6NTYuNzV9LHsieCI6NTg4LjU3ODEyNSwieSI6NTYuNzV9LHsieCI6NjEzLjU3ODEyNSwieSI6NTYuNzV9XQ==" data-look="classic" marker-end="url(#m-6645021c4c1a-light_flowchart-v2-pointEnd)"/><path d="M873.578,56.75L877.745,56.75C881.911,56.75,890.245,56.75,897.911,56.75C905.578,56.75,912.578,56.75,916.078,56.75L919.578,56.75" id="m-6645021c4c1a-light-L_Policy_Run_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Policy_Run_0" data-points="W3sieCI6ODczLjU3ODEyNSwieSI6NTYuNzV9LHsieCI6ODk4LjU3ODEyNSwieSI6NTYuNzV9LHsieCI6OTIzLjU3ODEyNSwieSI6NTYuNzV9XQ==" data-look="classic" marker-end="url(#m-6645021c4c1a-light_flowchart-v2-pointEnd)"/><path d="M1168.672,56.75L1172.839,56.75C1177.005,56.75,1185.339,56.75,1193.005,56.75C1200.672,56.75,1207.672,56.75,1211.172,56.75L1214.672,56.75" id="m-6645021c4c1a-light-L_Run_Money_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Run_Money_0" data-points="W3sieCI6MTE2OC42NzE4NzUsInkiOjU2Ljc1fSx7IngiOjExOTMuNjcxODc1LCJ5Ijo1Ni43NX0seyJ4IjoxMjE4LjY3MTg3NSwieSI6NTYuNzV9XQ==" data-look="classic" marker-end="url(#m-6645021c4c1a-light_flowchart-v2-pointEnd)"/><path d="M1412.141,56.75L1416.307,56.75C1420.474,56.75,1428.807,56.75,1436.5,57.766C1444.193,58.781,1451.245,60.812,1454.771,61.828L1458.297,62.844" id="m-6645021c4c1a-light-L_Money_Review_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Money_Review_0" data-points="W3sieCI6MTQxMi4xNDA2MjUsInkiOjU2Ljc1fSx7IngiOjE0MzcuMTQwNjI1LCJ5Ijo1Ni43NX0seyJ4IjoxNDYyLjE0MDYyNSwieSI6NjMuOTUwODE2ODA5MDcwODh9XQ==" data-look="classic" marker-end="url(#m-6645021c4c1a-light_flowchart-v2-pointEnd)"/><path d="M1462.141,133.299L1457.974,134.499C1453.807,135.699,1445.474,138.1,1421.018,139.3C1396.563,140.5,1355.984,140.5,1315.406,140.5C1274.828,140.5,1234.25,140.5,1189.37,140.5C1144.49,140.5,1095.307,140.5,1046.125,140.5C996.943,140.5,947.76,140.5,897.336,140.5C846.911,140.5,795.245,140.5,743.578,140.5C691.911,140.5,640.245,140.5,588.658,140.5C537.07,140.5,485.563,140.5,434.055,140.5C382.547,140.5,331.039,140.5,301.76,139.504C272.481,138.509,265.431,136.518,261.906,135.522L258.381,134.526" id="m-6645021c4c1a-light-L_Review_CUJ_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Review_CUJ_0" data-points="W3sieCI6MTQ2Mi4xNDA2MjUsInkiOjEzMy4yOTkxODMxOTA5MjkxfSx7IngiOjE0MzcuMTQwNjI1LCJ5IjoxNDAuNX0seyJ4IjoxMzE1LjQwNjI1LCJ5IjoxNDAuNX0seyJ4IjoxMTkzLjY3MTg3NSwieSI6MTQwLjV9LHsieCI6MTA0Ni4xMjUsInkiOjE0MC41fSx7IngiOjg5OC41NzgxMjUsInkiOjE0MC41fSx7IngiOjc0My41NzgxMjUsInkiOjE0MC41fSx7IngiOjU4OC41NzgxMjUsInkiOjE0MC41fSx7IngiOjQzNC4wNTQ2ODc1LCJ5IjoxNDAuNX0seyJ4IjoyNzkuNTMxMjUsInkiOjE0MC41fSx7IngiOjI1NC41MzEyNSwieSI6MTMzLjQzOTE5Mjc0OTQ5OTQzfV0=" data-look="classic" marker-end="url(#m-6645021c4c1a-light_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_CUJ_Target_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Target_Policy_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Policy_Run_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Run_Money_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Money_Review_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Review_CUJ_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="m-6645021c4c1a-light-flowchart-CUJ-0" data-look="classic" transform="translate(131.265625, 98.625)"><rect class="basic label-container" style="" x="-123.265625" y="-37.5" width="246.53125" height="75"/><g class="label" style="" transform="translate(-93.265625, -22.5)"><rect/><foreignObject width="186.53125" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Бизнес называет<br />критичные пути и их цену</p></span></div></foreignObject></g></g><g class="node default" id="m-6645021c4c1a-light-flowchart-Target-1" data-look="classic" transform="translate(434.0546875, 56.75)"><rect class="basic label-container" style="" x="-129.5234375" y="-37.5" width="259.046875" height="75"/><g class="label" style="" transform="translate(-99.5234375, -22.5)"><rect/><foreignObject width="199.046875" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Вместе выбираем SLO<br />как бюджет на компромисс</p></span></div></foreignObject></g></g><g class="node default" id="m-6645021c4c1a-light-flowchart-Policy-3" data-look="classic" transform="translate(743.578125, 56.75)"><rect class="basic label-container" style="" x="-130" y="-48.75" width="260" height="97.5"/><g class="label" style="" transform="translate(-100, -33.75)"><rect/><foreignObject width="200" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>Записываем error budget policy<br />продакт подписывает</p></span></div></foreignObject></g></g><g class="node default" id="m-6645021c4c1a-light-flowchart-Run-5" data-look="classic" transform="translate(1046.125, 56.75)"><rect class="basic label-container" style="" x="-122.546875" y="-37.5" width="245.09375" height="75"/><g class="label" style="" transform="translate(-92.546875, -22.5)"><rect/><foreignObject width="185.09375" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Живём по бюджету:<br />деплои, инциденты, фичи</p></span></div></foreignObject></g></g><g class="node default" id="m-6645021c4c1a-light-flowchart-Money-7" data-look="classic" transform="translate(1315.40625, 56.75)"><rect class="basic label-container" style="" x="-96.734375" y="-37.5" width="193.46875" height="75"/><g class="label" style="" transform="translate(-66.734375, -22.5)"><rect/><foreignObject width="133.46875" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Считаем сгорание<br />в деньгах</p></span></div></foreignObject></g></g><g class="node default" id="m-6645021c4c1a-light-flowchart-Review-9" data-look="classic" transform="translate(1582.5234375, 98.625)"><rect class="basic label-container" style="" x="-120.3828125" y="-37.5" width="240.765625" height="75"/><g class="label" style="" transform="translate(-90.3828125, -22.5)"><rect/><foreignObject width="180.765625" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Квартальный пересмотр:<br />изменилось ли число</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="m-6645021c4c1a-light-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="m-6645021c4c1a-light-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><linearGradient id="m-6645021c4c1a-light-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#c8c5bb" stop-opacity="1"/><stop offset="100%" stop-color="#c8c5bb" stop-opacity="1"/></linearGradient></svg>
</div>
<div class="mermaid-svg mermaid-svg--dark">
<svg id="m-6645021c4c1a-dark" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 1710.91px; background-color: transparent;" viewBox="0 0 1710.90625 148.5" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#m-6645021c4c1a-dark{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;fill:#e8e6df;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#m-6645021c4c1a-dark .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#m-6645021c4c1a-dark .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#m-6645021c4c1a-dark .error-icon{fill:#7f1d1d;}#m-6645021c4c1a-dark .error-text{fill:#fecaca;stroke:#fecaca;}#m-6645021c4c1a-dark .edge-thickness-normal{stroke-width:1px;}#m-6645021c4c1a-dark .edge-thickness-thick{stroke-width:3.5px;}#m-6645021c4c1a-dark .edge-pattern-solid{stroke-dasharray:0;}#m-6645021c4c1a-dark .edge-thickness-invisible{stroke-width:0;fill:none;}#m-6645021c4c1a-dark .edge-pattern-dashed{stroke-dasharray:3;}#m-6645021c4c1a-dark .edge-pattern-dotted{stroke-dasharray:2;}#m-6645021c4c1a-dark .marker{fill:#a8a89e;stroke:#a8a89e;}#m-6645021c4c1a-dark .marker.cross{stroke:#a8a89e;}#m-6645021c4c1a-dark svg{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;}#m-6645021c4c1a-dark p{margin:0;}#m-6645021c4c1a-dark .label{font-family:Inter,system-ui,-apple-system,sans-serif;color:#e8e6df;}#m-6645021c4c1a-dark .cluster-label text{fill:#e8e6df;}#m-6645021c4c1a-dark .cluster-label span{color:#e8e6df;}#m-6645021c4c1a-dark .cluster-label span p{background-color:transparent;}#m-6645021c4c1a-dark .label text,#m-6645021c4c1a-dark span{fill:#e8e6df;color:#e8e6df;}#m-6645021c4c1a-dark .node rect,#m-6645021c4c1a-dark .node circle,#m-6645021c4c1a-dark .node ellipse,#m-6645021c4c1a-dark .node polygon,#m-6645021c4c1a-dark .node path{fill:#23252a;stroke:#3f3f46;stroke-width:1px;}#m-6645021c4c1a-dark .rough-node .label text,#m-6645021c4c1a-dark .node .label text,#m-6645021c4c1a-dark .image-shape .label,#m-6645021c4c1a-dark .icon-shape .label{text-anchor:middle;}#m-6645021c4c1a-dark .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#m-6645021c4c1a-dark .rough-node .label,#m-6645021c4c1a-dark .node .label,#m-6645021c4c1a-dark .image-shape .label,#m-6645021c4c1a-dark .icon-shape .label{text-align:center;}#m-6645021c4c1a-dark .node.clickable{cursor:pointer;}#m-6645021c4c1a-dark .root .anchor path{fill:#a8a89e!important;stroke-width:0;stroke:#a8a89e;}#m-6645021c4c1a-dark .arrowheadPath{fill:rgba(255, 255, 255, 0);}#m-6645021c4c1a-dark .edgePath .path{stroke:#a8a89e;stroke-width:1px;}#m-6645021c4c1a-dark .flowchart-link{stroke:#a8a89e;fill:none;}#m-6645021c4c1a-dark .edgeLabel{background-color:#1a1b1e;text-align:center;}#m-6645021c4c1a-dark .edgeLabel p{background-color:#1a1b1e;}#m-6645021c4c1a-dark .edgeLabel rect{opacity:0.5;background-color:#1a1b1e;fill:#1a1b1e;}#m-6645021c4c1a-dark .labelBkg{background-color:rgba(26, 27, 30, 0.5);}#m-6645021c4c1a-dark .cluster rect{fill:#2a2b2f;stroke:#3f3f46;stroke-width:1px;}#m-6645021c4c1a-dark .cluster text{fill:#e8e6df;}#m-6645021c4c1a-dark .cluster span{color:#e8e6df;}#m-6645021c4c1a-dark div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:12px;background:#7c2d12;border:1px solid #fb923c;border-radius:2px;pointer-events:none;z-index:100;}#m-6645021c4c1a-dark .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#e8e6df;}#m-6645021c4c1a-dark rect.text{fill:none;stroke-width:0;}#m-6645021c4c1a-dark .icon-shape,#m-6645021c4c1a-dark .image-shape{background-color:#1a1b1e;text-align:center;}#m-6645021c4c1a-dark .icon-shape p,#m-6645021c4c1a-dark .image-shape p{background-color:#1a1b1e;padding:2px;}#m-6645021c4c1a-dark .icon-shape .label rect,#m-6645021c4c1a-dark .image-shape .label rect{opacity:0.5;background-color:#1a1b1e;fill:#1a1b1e;}#m-6645021c4c1a-dark .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#m-6645021c4c1a-dark .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#m-6645021c4c1a-dark .node .neo-node{stroke:#3f3f46;}#m-6645021c4c1a-dark [data-look="neo"].node rect,#m-6645021c4c1a-dark [data-look="neo"].cluster rect,#m-6645021c4c1a-dark [data-look="neo"].node polygon{stroke:url(#m-6645021c4c1a-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-6645021c4c1a-dark [data-look="neo"].node path{stroke:url(#m-6645021c4c1a-dark-gradient);stroke-width:1px;}#m-6645021c4c1a-dark [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-6645021c4c1a-dark [data-look="neo"].node .neo-line path{stroke:#3f3f46;filter:none;}#m-6645021c4c1a-dark [data-look="neo"].node circle{stroke:url(#m-6645021c4c1a-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-6645021c4c1a-dark [data-look="neo"].node circle .state-start{fill:#000000;}#m-6645021c4c1a-dark [data-look="neo"].icon-shape .icon{fill:url(#m-6645021c4c1a-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-6645021c4c1a-dark [data-look="neo"].icon-shape .icon-neo path{stroke:url(#m-6645021c4c1a-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-6645021c4c1a-dark :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="m-6645021c4c1a-dark_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-dark_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-dark_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-dark_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-dark_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-dark_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-dark_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-dark_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-dark_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-dark_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-6645021c4c1a-dark_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="m-6645021c4c1a-dark_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M254.531,63.811L258.698,62.634C262.865,61.457,271.198,59.104,278.865,57.927C286.531,56.75,293.531,56.75,297.031,56.75L300.531,56.75" id="m-6645021c4c1a-dark-L_CUJ_Target_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_CUJ_Target_0" data-points="W3sieCI6MjU0LjUzMTI1LCJ5Ijo2My44MTA4MDcyNTA1MDA1OH0seyJ4IjoyNzkuNTMxMjUsInkiOjU2Ljc1fSx7IngiOjMwNC41MzEyNSwieSI6NTYuNzV9XQ==" data-look="classic" marker-end="url(#m-6645021c4c1a-dark_flowchart-v2-pointEnd)"/><path d="M563.578,56.75L567.745,56.75C571.911,56.75,580.245,56.75,587.911,56.75C595.578,56.75,602.578,56.75,606.078,56.75L609.578,56.75" id="m-6645021c4c1a-dark-L_Target_Policy_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Target_Policy_0" data-points="W3sieCI6NTYzLjU3ODEyNSwieSI6NTYuNzV9LHsieCI6NTg4LjU3ODEyNSwieSI6NTYuNzV9LHsieCI6NjEzLjU3ODEyNSwieSI6NTYuNzV9XQ==" data-look="classic" marker-end="url(#m-6645021c4c1a-dark_flowchart-v2-pointEnd)"/><path d="M873.578,56.75L877.745,56.75C881.911,56.75,890.245,56.75,897.911,56.75C905.578,56.75,912.578,56.75,916.078,56.75L919.578,56.75" id="m-6645021c4c1a-dark-L_Policy_Run_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Policy_Run_0" data-points="W3sieCI6ODczLjU3ODEyNSwieSI6NTYuNzV9LHsieCI6ODk4LjU3ODEyNSwieSI6NTYuNzV9LHsieCI6OTIzLjU3ODEyNSwieSI6NTYuNzV9XQ==" data-look="classic" marker-end="url(#m-6645021c4c1a-dark_flowchart-v2-pointEnd)"/><path d="M1168.672,56.75L1172.839,56.75C1177.005,56.75,1185.339,56.75,1193.005,56.75C1200.672,56.75,1207.672,56.75,1211.172,56.75L1214.672,56.75" id="m-6645021c4c1a-dark-L_Run_Money_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Run_Money_0" data-points="W3sieCI6MTE2OC42NzE4NzUsInkiOjU2Ljc1fSx7IngiOjExOTMuNjcxODc1LCJ5Ijo1Ni43NX0seyJ4IjoxMjE4LjY3MTg3NSwieSI6NTYuNzV9XQ==" data-look="classic" marker-end="url(#m-6645021c4c1a-dark_flowchart-v2-pointEnd)"/><path d="M1412.141,56.75L1416.307,56.75C1420.474,56.75,1428.807,56.75,1436.5,57.766C1444.193,58.781,1451.245,60.812,1454.771,61.828L1458.297,62.844" id="m-6645021c4c1a-dark-L_Money_Review_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Money_Review_0" data-points="W3sieCI6MTQxMi4xNDA2MjUsInkiOjU2Ljc1fSx7IngiOjE0MzcuMTQwNjI1LCJ5Ijo1Ni43NX0seyJ4IjoxNDYyLjE0MDYyNSwieSI6NjMuOTUwODE2ODA5MDcwODh9XQ==" data-look="classic" marker-end="url(#m-6645021c4c1a-dark_flowchart-v2-pointEnd)"/><path d="M1462.141,133.299L1457.974,134.499C1453.807,135.699,1445.474,138.1,1421.018,139.3C1396.563,140.5,1355.984,140.5,1315.406,140.5C1274.828,140.5,1234.25,140.5,1189.37,140.5C1144.49,140.5,1095.307,140.5,1046.125,140.5C996.943,140.5,947.76,140.5,897.336,140.5C846.911,140.5,795.245,140.5,743.578,140.5C691.911,140.5,640.245,140.5,588.658,140.5C537.07,140.5,485.563,140.5,434.055,140.5C382.547,140.5,331.039,140.5,301.76,139.504C272.481,138.509,265.431,136.518,261.906,135.522L258.381,134.526" id="m-6645021c4c1a-dark-L_Review_CUJ_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Review_CUJ_0" data-points="W3sieCI6MTQ2Mi4xNDA2MjUsInkiOjEzMy4yOTkxODMxOTA5MjkxfSx7IngiOjE0MzcuMTQwNjI1LCJ5IjoxNDAuNX0seyJ4IjoxMzE1LjQwNjI1LCJ5IjoxNDAuNX0seyJ4IjoxMTkzLjY3MTg3NSwieSI6MTQwLjV9LHsieCI6MTA0Ni4xMjUsInkiOjE0MC41fSx7IngiOjg5OC41NzgxMjUsInkiOjE0MC41fSx7IngiOjc0My41NzgxMjUsInkiOjE0MC41fSx7IngiOjU4OC41NzgxMjUsInkiOjE0MC41fSx7IngiOjQzNC4wNTQ2ODc1LCJ5IjoxNDAuNX0seyJ4IjoyNzkuNTMxMjUsInkiOjE0MC41fSx7IngiOjI1NC41MzEyNSwieSI6MTMzLjQzOTE5Mjc0OTQ5OTQzfV0=" data-look="classic" marker-end="url(#m-6645021c4c1a-dark_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_CUJ_Target_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Target_Policy_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Policy_Run_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Run_Money_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Money_Review_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Review_CUJ_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="m-6645021c4c1a-dark-flowchart-CUJ-0" data-look="classic" transform="translate(131.265625, 98.625)"><rect class="basic label-container" style="" x="-123.265625" y="-37.5" width="246.53125" height="75"/><g class="label" style="" transform="translate(-93.265625, -22.5)"><rect/><foreignObject width="186.53125" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Бизнес называет<br />критичные пути и их цену</p></span></div></foreignObject></g></g><g class="node default" id="m-6645021c4c1a-dark-flowchart-Target-1" data-look="classic" transform="translate(434.0546875, 56.75)"><rect class="basic label-container" style="" x="-129.5234375" y="-37.5" width="259.046875" height="75"/><g class="label" style="" transform="translate(-99.5234375, -22.5)"><rect/><foreignObject width="199.046875" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Вместе выбираем SLO<br />как бюджет на компромисс</p></span></div></foreignObject></g></g><g class="node default" id="m-6645021c4c1a-dark-flowchart-Policy-3" data-look="classic" transform="translate(743.578125, 56.75)"><rect class="basic label-container" style="" x="-130" y="-48.75" width="260" height="97.5"/><g class="label" style="" transform="translate(-100, -33.75)"><rect/><foreignObject width="200" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>Записываем error budget policy<br />продакт подписывает</p></span></div></foreignObject></g></g><g class="node default" id="m-6645021c4c1a-dark-flowchart-Run-5" data-look="classic" transform="translate(1046.125, 56.75)"><rect class="basic label-container" style="" x="-122.546875" y="-37.5" width="245.09375" height="75"/><g class="label" style="" transform="translate(-92.546875, -22.5)"><rect/><foreignObject width="185.09375" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Живём по бюджету:<br />деплои, инциденты, фичи</p></span></div></foreignObject></g></g><g class="node default" id="m-6645021c4c1a-dark-flowchart-Money-7" data-look="classic" transform="translate(1315.40625, 56.75)"><rect class="basic label-container" style="" x="-96.734375" y="-37.5" width="193.46875" height="75"/><g class="label" style="" transform="translate(-66.734375, -22.5)"><rect/><foreignObject width="133.46875" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Считаем сгорание<br />в деньгах</p></span></div></foreignObject></g></g><g class="node default" id="m-6645021c4c1a-dark-flowchart-Review-9" data-look="classic" transform="translate(1582.5234375, 98.625)"><rect class="basic label-container" style="" x="-120.3828125" y="-37.5" width="240.765625" height="75"/><g class="label" style="" transform="translate(-90.3828125, -22.5)"><rect/><foreignObject width="180.765625" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Квартальный пересмотр:<br />изменилось ли число</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="m-6645021c4c1a-dark-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="m-6645021c4c1a-dark-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><linearGradient id="m-6645021c4c1a-dark-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#3f3f46" stop-opacity="1"/><stop offset="100%" stop-color="#3f3f46" stop-opacity="1"/></linearGradient></svg>
</div>
</figure><p>Каждый виток — это квартал. На входе бизнес приносит «что и сколько стоит», на выходе получает «вот сколько надёжности мы дали и какой ценой». Если хоть одно звено разорвано — цикл рассыпается, и SLO откатывается в режим артефакта. Именно эту целостность и проверяют на собесе — к нему и переходим.</p>
<h2 id="кейсы-с-system-design-собеса">Кейсы с System Design-собеса</h2>
<p>Те же тезисы, но в позе «кандидат под прессом». Когда меня самого недавно гоняли по этой теме на интервью, стало особенно ясно: вопросы «про SLO» почти никогда не про SLO. Они про то, умеешь ли ты вести разговор о надёжности так, чтобы бизнес поменял поведение. Разберу пять типовых сценариев — на том же маркетплейсе.</p>
<h3 id="кейс-1-зачем-тебе-slo-999-а-не-9999">Кейс 1. «Зачем тебе SLO 99.9, а не 99.99?»</h3>
<p><strong>Что проверяют:</strong> умеет ли кандидат держать рамку «бюджет → архитектура → деньги».</p>
<p><strong>Провальный ответ:</strong> начать с топологии. «Ну, 99.99 — это active-active в трёх регионах, а 99.9 — один регион с failover между AZ». Технически верно, но это ответ на вопрос «чем отличаются архитектуры», а не «зачем тебе эта надёжность».</p>
<p><strong>Сильный ответ всегда начинается со сценария бизнеса:</strong></p>
<blockquote><p>«Зависит от того, какой это путь. Если это поиск каталога — главный драйвер конверсии — то считаем: на 99.9% бюджет даунтайма на пике ~14 минут в месяц, на 99.99% — полторы минуты. Разница в архитектуре — лишних <code>15–25×</code> против <code>4–6×</code> baseline. Вопрос к бизнесу: эти 12 минут в месяц на пике стоят нам больше или меньше, чем утроение инфраструктуры? Если GMV такой, что минута пикового даунтайма — сотни тысяч, берём 99.99. Если нет — 99.9 с запасом».</p>
</blockquote><p>Ключевое: кандидат не выбирает девятку сам. Он показывает, что выбор девятки — это разговор с бизнесом, и приносит в этот разговор обе цифры — цену надёжности и цену её отсутствия.</p>
<h3 id="кейс-2-у-вас-9995-по-чекауту-но-30-оплат-не-проходит--что-не-так">Кейс 2. «У вас 99.95 по чекауту, но 30% оплат не проходит — что не так?»</h3>
<p><strong>Что проверяют:</strong> понимает ли кандидат разрыв между технической доступностью и продуктовой надёжностью.</p>
<p>Это мой любимый кейс, потому что он ловит самую частую ошибку. Дашборд зелёный — <code>99.95%</code> по эндпоинту оплаты. А бизнес кричит, что треть оплат не доходит. Противоречие? Нет. SLI повешен не туда.</p>
<p><strong>Что произошло:</strong> SLI считает «доля ответов <code>2xx</code> от ручки <code>/pay</code>». Ручка честно отвечает <code>200 OK</code> — она приняла запрос. А дальше платёж уходит в провайдера, провайдер таймаутит, ретрай не настроен, и для пользователя оплата «не прошла» — но для SLI всё прекрасно, ручка-то ответила.</p>
<p><strong>Сильный ответ:</strong></p>
<blockquote><p>«SLI измеряет здоровье ручки, а не сценарий. Его надо переповесить на пользовательский результат: „доля начатых оплат, завершившихся подтверждённым списанием за <code>&lt; N</code> секунд“. Тогда таймауты провайдера, потерянные колбэки и зависшие платежи попадут в знаменатель, и 99.95% превратятся в честные 70%. Дашборд начнёт показывать ту же боль, что чувствует бизнес».</p>
</blockquote><p>Это ровно разведение «продуктовая надёжность против технической доступности». Кандидат, который видит этот разрыв, понимает, что SLI вешается на сценарий, а не на success rate ручки. Кандидат, который не видит, будет до утра чинить инфраструктуру, которая и так зелёная.</p>
<h3 id="кейс-3-бизнес-требует-100-доступности-что-отвечаешь">Кейс 3. «Бизнес требует 100% доступности. Что отвечаешь?»</h3>
<p><strong>Что проверяют:</strong> переговорный навык в чистом виде.</p>
<p><strong>Провальный ответ:</strong> «100% невозможно». Технически правда, но это ответ инженера, который закрывает разговор, а не ведёт его. Бизнес услышит «не хочу» и пойдёт давить.</p>
<p><strong>Сильный ответ — не «нельзя», а цена:</strong></p>
<blockquote><p>«Окей, давай посчитаем, что такое 100%. Каждая девятка после 99.9 удорожает систему примерно в разы. 99.99 — это уже <code>15–25×</code> baseline и заморозка скорости релизов. 99.999 — это multi-cloud, независимые DNS, частично независимые кодовые базы, подходы из telecom. А 100% — это бесконечность: ноль допустимых сбоев означает ноль деплоев, ноль экспериментов, ноль изменений. Мы перестанем выпускать фичи вообще. Точно нужны эти девятки — или нам нужно, чтобы конкретный сценарий, скажем оплата, не падал заметно для пользователя? Это разные задачи, и вторая решается сильно дешевле».</p>
</blockquote><p>Кандидат переводит абсолютное требование в трейд-офф и возвращает бизнесу выбор. Часто за «хотим 100%» стоит «не хотим терять оплаты в пик» — а это не про 100%, это про правильный SLO на правильный путь плюс graceful degradation.</p>
<h3 id="кейс-4-кто-принимает-решение-о-фризе-релизов-при-сгорании-бюджета">Кейс 4. «Кто принимает решение о фризе релизов при сгорании бюджета?»</h3>
<p><strong>Что проверяют:</strong> есть ли у кандидата error budget policy в голове и понимает ли он, что это продуктовый артефакт.</p>
<p><strong>Провальный ответ:</strong> «SRE решает» или «тимлид решает». Это инженерный ответ, и он выдаёт, что у кандидата SLO живёт в инженерной резервации.</p>
<p><strong>Сильный ответ:</strong></p>
<blockquote><p>«Решает не человек в моменте, а записанная заранее error budget policy. В ней зафиксировано: при таком-то burn-rate за такое-то окно — автоматический freeze рискованных деплоев. И подписана эта политика продуктовым владельцем, потому что это он соглашается, что его фичи подождут. Если решение каждый раз принимается заново и под давлением — значит, политики нет, и побеждает тот, кто громче».</p>
</blockquote><p>Здесь проверяют понимание, что фриз — это не власть SRE над продуктом, а заранее согласованное обеими сторонами правило. Кандидат, который это понимает, не будет воевать с продактом — он сошлётся на то, что они вместе подписали.</p>
<h3 id="кейс-5-покажи-как-сожжённый-бюджет-влияет-на-дорожную-карту">Кейс 5. «Покажи, как сожжённый бюджет влияет на дорожную карту»</h3>
<p><strong>Что проверяют:</strong> встроен ли SRE в плановый цикл или живёт в параллельной вселенной с продуктом.</p>
<p><strong>Провальный ответ:</strong> «при сгорании бюджета мы делаем post-mortem». Post-mortem — это хорошо, но это про прошлое. Вопрос — про будущее, про roadmap.</p>
<p><strong>Сильный ответ:</strong></p>
<blockquote><p>«Сгоревший бюджет — это вход в планирование, а не только разбор инцидента. Механически: при систематическом сгорании reliability-задачи поднимаются в приоритете над фичами на следующий цикл — это записано в policy. На квартальном reliability review мы смотрим burn-rate за квартал по каждому пути и решаем, куда идёт инженерное усилие. Если поиск стабильно жжёт бюджет — значит, в следующем квартале часть roadmap уходит на его укрепление, и продакт это принимает, потому что видит связь „сгорание → потерянная выручка“».</p>
</blockquote><p>Это проверка на то, что SRE и продукт планируют из одного документа, а не из двух. Если бюджет ошибок никак не дотягивается до roadmap — SRE и продукт живут в разных вселенных, и SLO снова декорация.</p>
<h3 id="главный-паттерн-всех-пяти-кейсов">Главный паттерн всех пяти кейсов</h3>
<p>Сведём пять кейсов в одну таблицу — что на самом деле проверяет каждый:</p>
<table>
  <thead>
      <tr>
          <th>Вопрос на собесе</th>
          <th>Что реально проверяют</th>
          <th>Маркер слабого ответа</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Зачем 99.9, а не 99.99?</td>
          <td>Рамка «бюджет → архитектура → деньги»</td>
          <td>Начал с топологии, а не со сценария</td>
      </tr>
      <tr>
          <td>99.95, но 30% оплат не проходит?</td>
          <td>Разрыв «доступность vs надёжность»</td>
          <td>Полез чинить зелёную инфраструктуру</td>
      </tr>
      <tr>
          <td>Бизнес хочет 100%?</td>
          <td>Переговорный навык</td>
          <td>Сказал «невозможно» и закрыл тему</td>
      </tr>
      <tr>
          <td>Кто решает фриз?</td>
          <td>Error budget policy как продуктовый артефакт</td>
          <td>«SRE решает» / «тимлид решает»</td>
      </tr>
      <tr>
          <td>Бюджет → roadmap?</td>
          <td>Встроен ли SRE в плановый цикл</td>
          <td>«Делаем post-mortem» (про прошлое)</td>
      </tr>
  </tbody>
</table>
<p>На собесе не проверяют знание формул сгорания бюджета — это гуглится за минуту. Проверяют, <strong>можешь ли ты вести разговор о надёжности так, чтобы бизнес поменял своё поведение</strong>. Все пять сильных ответов имеют одну форму: начать со сценария и денег, перевести требование в трейд-офф, вернуть выбор бизнесу, сослаться на заранее согласованное правило. Это и есть навык, который «чертёж» описывал как «SLO — интерфейс между System Design и бизнесом», только теперь — со стороны человека, который этим интерфейсом пользуется вживую.</p>
<h2 id="метрики-sre-команды-для-мультипродукта">Метрики SRE-команды для мультипродукта</h2>
<p>Третий тезис — и самый практически болезненный. Пока продукт один, метрики команды SRE совпадают с метриками продукта: SLO продукта, его бюджет, его инциденты. Команда отчитывается надёжностью своего единственного сервиса, и всё сходится.</p>
<p>Когда продуктов становится 5–10, эта простая картина ломается. Команда обслуживает зоопарк сервисов с разными CUJ, разной критичностью, разной зрелостью. И тут возникает вопрос, на который у большинства команд нет хорошего ответа: <strong>как одной цифрой отчитаться перед менеджментом за надёжность, которую ты дал восьми разным продуктам?</strong> Соблазн — взять среднее. На нём всё и ломается.</p>
<h3 id="что-не-работает-как-метрика-команды">Что не работает как метрика команды</h3>
<p>Три популярных агрегата, каждый из которых врёт по-своему:</p>
<ul>
<li><strong>MTTR в среднем по всем инцидентам.</strong> Растворяет редкие тяжёлые случаи в массе мелких. Команда, которая быстро закрывает сто пустяковых алертов и месяц не может починить один критичный, покажет прекрасный средний MTTR. Хуже того, метрика поощряет «закрыть быстро, не разбираясь» — лишь бы цифра была хорошей.</li>
<li><strong>Composite SLO по всем продуктам.</strong> «Средняя надёжность по компании 99.94%» — это средняя температура по больнице. Она теряет CUJ: упавший в ноль критичный путь одного продукта тонет в здоровье семи остальных. Наивная агрегация SLO в мультипродукте математически врёт — этот эффект хорошо разобран в посте Алекса Идальго <a href="https://blog.relyabilit.ie/implicit-slos-and-their-dangers/" rel="noopener noreferrer" target="_blank">«Implicit SLOs and their dangers»</a>
: композит почти всегда оптимистичнее, чем худший из путей, а пользователю больно именно от худшего.</li>
<li><strong>Количество инцидентов в абсолюте.</strong> Стимулирует молчать о мелких. Если команду меряют числом инцидентов, она перестаёт их заводить — и ты теряешь сигнал. Это классический закон Гудхарта: метрика, ставшая целью, перестаёт быть метрикой.</li>
</ul>
<p>Общая болезнь всех трёх — они сжимают разнородное в одно число, и в этом сжатии теряется ровно то, ради чего метрику заводили.</p>
<h3 id="что-осмысленно-мерить-три-слоя">Что осмысленно мерить: три слоя</h3>
<p>Вместо одного агрегата — раскладка по трём слоям, параллельная трём ролям из «чертежа»: бизнес / инженерия / управление. Каждый слой отвечает на свой вопрос и не пытается заменить остальные.</p>
<figure class="mermaid mermaid--prerendered" aria-label="Mermaid diagram">
<div class="mermaid-svg mermaid-svg--light">
<svg id="m-c763b06a1ef1-light" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 896px; background-color: transparent;" viewBox="0 0 896 136" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#m-c763b06a1ef1-light{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;fill:#1c1c1f;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#m-c763b06a1ef1-light .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#m-c763b06a1ef1-light .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#m-c763b06a1ef1-light .error-icon{fill:#fee2e2;}#m-c763b06a1ef1-light .error-text{fill:#7f1d1d;stroke:#7f1d1d;}#m-c763b06a1ef1-light .edge-thickness-normal{stroke-width:1px;}#m-c763b06a1ef1-light .edge-thickness-thick{stroke-width:3.5px;}#m-c763b06a1ef1-light .edge-pattern-solid{stroke-dasharray:0;}#m-c763b06a1ef1-light .edge-thickness-invisible{stroke-width:0;fill:none;}#m-c763b06a1ef1-light .edge-pattern-dashed{stroke-dasharray:3;}#m-c763b06a1ef1-light .edge-pattern-dotted{stroke-dasharray:2;}#m-c763b06a1ef1-light .marker{fill:#5b5b62;stroke:#5b5b62;}#m-c763b06a1ef1-light .marker.cross{stroke:#5b5b62;}#m-c763b06a1ef1-light svg{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;}#m-c763b06a1ef1-light p{margin:0;}#m-c763b06a1ef1-light .label{font-family:Inter,system-ui,-apple-system,sans-serif;color:#1c1c1f;}#m-c763b06a1ef1-light .cluster-label text{fill:#1c1c1f;}#m-c763b06a1ef1-light .cluster-label span{color:#1c1c1f;}#m-c763b06a1ef1-light .cluster-label span p{background-color:transparent;}#m-c763b06a1ef1-light .label text,#m-c763b06a1ef1-light span{fill:#1c1c1f;color:#1c1c1f;}#m-c763b06a1ef1-light .node rect,#m-c763b06a1ef1-light .node circle,#m-c763b06a1ef1-light .node ellipse,#m-c763b06a1ef1-light .node polygon,#m-c763b06a1ef1-light .node path{fill:#ffffff;stroke:#c8c5bb;stroke-width:1px;}#m-c763b06a1ef1-light .rough-node .label text,#m-c763b06a1ef1-light .node .label text,#m-c763b06a1ef1-light .image-shape .label,#m-c763b06a1ef1-light .icon-shape .label{text-anchor:middle;}#m-c763b06a1ef1-light .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#m-c763b06a1ef1-light .rough-node .label,#m-c763b06a1ef1-light .node .label,#m-c763b06a1ef1-light .image-shape .label,#m-c763b06a1ef1-light .icon-shape .label{text-align:center;}#m-c763b06a1ef1-light .node.clickable{cursor:pointer;}#m-c763b06a1ef1-light .root .anchor path{fill:#5b5b62!important;stroke-width:0;stroke:#5b5b62;}#m-c763b06a1ef1-light .arrowheadPath{fill:rgba(255, 255, 255, 0);}#m-c763b06a1ef1-light .edgePath .path{stroke:#5b5b62;stroke-width:1px;}#m-c763b06a1ef1-light .flowchart-link{stroke:#5b5b62;fill:none;}#m-c763b06a1ef1-light .edgeLabel{background-color:#fafaf7;text-align:center;}#m-c763b06a1ef1-light .edgeLabel p{background-color:#fafaf7;}#m-c763b06a1ef1-light .edgeLabel rect{opacity:0.5;background-color:#fafaf7;fill:#fafaf7;}#m-c763b06a1ef1-light .labelBkg{background-color:rgba(250, 250, 247, 0.5);}#m-c763b06a1ef1-light .cluster rect{fill:#f3f1ed;stroke:#c8c5bb;stroke-width:1px;}#m-c763b06a1ef1-light .cluster text{fill:#1c1c1f;}#m-c763b06a1ef1-light .cluster span{color:#1c1c1f;}#m-c763b06a1ef1-light div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:12px;background:#fed7aa;border:1px solid #c2410c;border-radius:2px;pointer-events:none;z-index:100;}#m-c763b06a1ef1-light .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#1c1c1f;}#m-c763b06a1ef1-light rect.text{fill:none;stroke-width:0;}#m-c763b06a1ef1-light .icon-shape,#m-c763b06a1ef1-light .image-shape{background-color:#fafaf7;text-align:center;}#m-c763b06a1ef1-light .icon-shape p,#m-c763b06a1ef1-light .image-shape p{background-color:#fafaf7;padding:2px;}#m-c763b06a1ef1-light .icon-shape .label rect,#m-c763b06a1ef1-light .image-shape .label rect{opacity:0.5;background-color:#fafaf7;fill:#fafaf7;}#m-c763b06a1ef1-light .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#m-c763b06a1ef1-light .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#m-c763b06a1ef1-light .node .neo-node{stroke:#c8c5bb;}#m-c763b06a1ef1-light [data-look="neo"].node rect,#m-c763b06a1ef1-light [data-look="neo"].cluster rect,#m-c763b06a1ef1-light [data-look="neo"].node polygon{stroke:url(#m-c763b06a1ef1-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-c763b06a1ef1-light [data-look="neo"].node path{stroke:url(#m-c763b06a1ef1-light-gradient);stroke-width:1px;}#m-c763b06a1ef1-light [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-c763b06a1ef1-light [data-look="neo"].node .neo-line path{stroke:#c8c5bb;filter:none;}#m-c763b06a1ef1-light [data-look="neo"].node circle{stroke:url(#m-c763b06a1ef1-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-c763b06a1ef1-light [data-look="neo"].node circle .state-start{fill:#000000;}#m-c763b06a1ef1-light [data-look="neo"].icon-shape .icon{fill:url(#m-c763b06a1ef1-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-c763b06a1ef1-light [data-look="neo"].icon-shape .icon-neo path{stroke:url(#m-c763b06a1ef1-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-c763b06a1ef1-light :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="m-c763b06a1ef1-light_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-light_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-light_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-light_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-light_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-light_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-light_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-light_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-light_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-light_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-light_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="m-c763b06a1ef1-light_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M268,68L272.167,68C276.333,68,284.667,68,292.333,68C300,68,307,68,310.5,68L314,68" id="m-c763b06a1ef1-light-L_L3_L2_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_L3_L2_0" data-points="W3sieCI6MjY4LCJ5Ijo2OH0seyJ4IjoyOTMsInkiOjY4fSx7IngiOjMxOCwieSI6Njh9XQ==" data-look="classic" marker-end="url(#m-c763b06a1ef1-light_flowchart-v2-pointEnd)"/><path d="M578,68L582.167,68C586.333,68,594.667,68,602.333,68C610,68,617,68,620.5,68L624,68" id="m-c763b06a1ef1-light-L_L2_L1_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_L2_L1_0" data-points="W3sieCI6NTc4LCJ5Ijo2OH0seyJ4Ijo2MDMsInkiOjY4fSx7IngiOjYyOCwieSI6Njh9XQ==" data-look="classic" marker-end="url(#m-c763b06a1ef1-light_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_L3_L2_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_L2_L1_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="m-c763b06a1ef1-light-flowchart-L1-0" data-look="classic" transform="translate(758, 68)"><rect class="basic label-container" style="" x="-130" y="-60" width="260" height="120"/><g class="label" style="" transform="translate(-100, -45)"><rect/><foreignObject width="200" height="90"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>Слой 1. Надёжность продуктов суммарно<br />вопрос: какую надёжность мы дали бизнесу</p></span></div></foreignObject></g></g><g class="node default" id="m-c763b06a1ef1-light-flowchart-L2-1" data-look="classic" transform="translate(448, 68)"><rect class="basic label-container" style="" x="-130" y="-60" width="260" height="120"/><g class="label" style="" transform="translate(-100, -45)"><rect/><foreignObject width="200" height="90"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>Слой 2. Инженерное усилие команды<br />вопрос: какой ценой и насколько устойчиво</p></span></div></foreignObject></g></g><g class="node default" id="m-c763b06a1ef1-light-flowchart-L3-2" data-look="classic" transform="translate(138, 68)"><rect class="basic label-container" style="" x="-130" y="-48.75" width="260" height="97.5"/><g class="label" style="" transform="translate(-100, -33.75)"><rect/><foreignObject width="200" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>Слой 3. Качество диалога<br />вопрос: встроена ли надёжность в продукт</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="m-c763b06a1ef1-light-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="m-c763b06a1ef1-light-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><linearGradient id="m-c763b06a1ef1-light-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#c8c5bb" stop-opacity="1"/><stop offset="100%" stop-color="#c8c5bb" stop-opacity="1"/></linearGradient></svg>
</div>
<div class="mermaid-svg mermaid-svg--dark">
<svg id="m-c763b06a1ef1-dark" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 896px; background-color: transparent;" viewBox="0 0 896 136" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#m-c763b06a1ef1-dark{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;fill:#e8e6df;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#m-c763b06a1ef1-dark .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#m-c763b06a1ef1-dark .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#m-c763b06a1ef1-dark .error-icon{fill:#7f1d1d;}#m-c763b06a1ef1-dark .error-text{fill:#fecaca;stroke:#fecaca;}#m-c763b06a1ef1-dark .edge-thickness-normal{stroke-width:1px;}#m-c763b06a1ef1-dark .edge-thickness-thick{stroke-width:3.5px;}#m-c763b06a1ef1-dark .edge-pattern-solid{stroke-dasharray:0;}#m-c763b06a1ef1-dark .edge-thickness-invisible{stroke-width:0;fill:none;}#m-c763b06a1ef1-dark .edge-pattern-dashed{stroke-dasharray:3;}#m-c763b06a1ef1-dark .edge-pattern-dotted{stroke-dasharray:2;}#m-c763b06a1ef1-dark .marker{fill:#a8a89e;stroke:#a8a89e;}#m-c763b06a1ef1-dark .marker.cross{stroke:#a8a89e;}#m-c763b06a1ef1-dark svg{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;}#m-c763b06a1ef1-dark p{margin:0;}#m-c763b06a1ef1-dark .label{font-family:Inter,system-ui,-apple-system,sans-serif;color:#e8e6df;}#m-c763b06a1ef1-dark .cluster-label text{fill:#e8e6df;}#m-c763b06a1ef1-dark .cluster-label span{color:#e8e6df;}#m-c763b06a1ef1-dark .cluster-label span p{background-color:transparent;}#m-c763b06a1ef1-dark .label text,#m-c763b06a1ef1-dark span{fill:#e8e6df;color:#e8e6df;}#m-c763b06a1ef1-dark .node rect,#m-c763b06a1ef1-dark .node circle,#m-c763b06a1ef1-dark .node ellipse,#m-c763b06a1ef1-dark .node polygon,#m-c763b06a1ef1-dark .node path{fill:#23252a;stroke:#3f3f46;stroke-width:1px;}#m-c763b06a1ef1-dark .rough-node .label text,#m-c763b06a1ef1-dark .node .label text,#m-c763b06a1ef1-dark .image-shape .label,#m-c763b06a1ef1-dark .icon-shape .label{text-anchor:middle;}#m-c763b06a1ef1-dark .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#m-c763b06a1ef1-dark .rough-node .label,#m-c763b06a1ef1-dark .node .label,#m-c763b06a1ef1-dark .image-shape .label,#m-c763b06a1ef1-dark .icon-shape .label{text-align:center;}#m-c763b06a1ef1-dark .node.clickable{cursor:pointer;}#m-c763b06a1ef1-dark .root .anchor path{fill:#a8a89e!important;stroke-width:0;stroke:#a8a89e;}#m-c763b06a1ef1-dark .arrowheadPath{fill:rgba(255, 255, 255, 0);}#m-c763b06a1ef1-dark .edgePath .path{stroke:#a8a89e;stroke-width:1px;}#m-c763b06a1ef1-dark .flowchart-link{stroke:#a8a89e;fill:none;}#m-c763b06a1ef1-dark .edgeLabel{background-color:#1a1b1e;text-align:center;}#m-c763b06a1ef1-dark .edgeLabel p{background-color:#1a1b1e;}#m-c763b06a1ef1-dark .edgeLabel rect{opacity:0.5;background-color:#1a1b1e;fill:#1a1b1e;}#m-c763b06a1ef1-dark .labelBkg{background-color:rgba(26, 27, 30, 0.5);}#m-c763b06a1ef1-dark .cluster rect{fill:#2a2b2f;stroke:#3f3f46;stroke-width:1px;}#m-c763b06a1ef1-dark .cluster text{fill:#e8e6df;}#m-c763b06a1ef1-dark .cluster span{color:#e8e6df;}#m-c763b06a1ef1-dark div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:12px;background:#7c2d12;border:1px solid #fb923c;border-radius:2px;pointer-events:none;z-index:100;}#m-c763b06a1ef1-dark .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#e8e6df;}#m-c763b06a1ef1-dark rect.text{fill:none;stroke-width:0;}#m-c763b06a1ef1-dark .icon-shape,#m-c763b06a1ef1-dark .image-shape{background-color:#1a1b1e;text-align:center;}#m-c763b06a1ef1-dark .icon-shape p,#m-c763b06a1ef1-dark .image-shape p{background-color:#1a1b1e;padding:2px;}#m-c763b06a1ef1-dark .icon-shape .label rect,#m-c763b06a1ef1-dark .image-shape .label rect{opacity:0.5;background-color:#1a1b1e;fill:#1a1b1e;}#m-c763b06a1ef1-dark .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#m-c763b06a1ef1-dark .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#m-c763b06a1ef1-dark .node .neo-node{stroke:#3f3f46;}#m-c763b06a1ef1-dark [data-look="neo"].node rect,#m-c763b06a1ef1-dark [data-look="neo"].cluster rect,#m-c763b06a1ef1-dark [data-look="neo"].node polygon{stroke:url(#m-c763b06a1ef1-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-c763b06a1ef1-dark [data-look="neo"].node path{stroke:url(#m-c763b06a1ef1-dark-gradient);stroke-width:1px;}#m-c763b06a1ef1-dark [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-c763b06a1ef1-dark [data-look="neo"].node .neo-line path{stroke:#3f3f46;filter:none;}#m-c763b06a1ef1-dark [data-look="neo"].node circle{stroke:url(#m-c763b06a1ef1-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-c763b06a1ef1-dark [data-look="neo"].node circle .state-start{fill:#000000;}#m-c763b06a1ef1-dark [data-look="neo"].icon-shape .icon{fill:url(#m-c763b06a1ef1-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-c763b06a1ef1-dark [data-look="neo"].icon-shape .icon-neo path{stroke:url(#m-c763b06a1ef1-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-c763b06a1ef1-dark :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="m-c763b06a1ef1-dark_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-dark_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-dark_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-dark_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-dark_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-dark_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-dark_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-dark_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-dark_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-dark_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-c763b06a1ef1-dark_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="m-c763b06a1ef1-dark_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M268,68L272.167,68C276.333,68,284.667,68,292.333,68C300,68,307,68,310.5,68L314,68" id="m-c763b06a1ef1-dark-L_L3_L2_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_L3_L2_0" data-points="W3sieCI6MjY4LCJ5Ijo2OH0seyJ4IjoyOTMsInkiOjY4fSx7IngiOjMxOCwieSI6Njh9XQ==" data-look="classic" marker-end="url(#m-c763b06a1ef1-dark_flowchart-v2-pointEnd)"/><path d="M578,68L582.167,68C586.333,68,594.667,68,602.333,68C610,68,617,68,620.5,68L624,68" id="m-c763b06a1ef1-dark-L_L2_L1_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_L2_L1_0" data-points="W3sieCI6NTc4LCJ5Ijo2OH0seyJ4Ijo2MDMsInkiOjY4fSx7IngiOjYyOCwieSI6Njh9XQ==" data-look="classic" marker-end="url(#m-c763b06a1ef1-dark_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_L3_L2_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_L2_L1_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="m-c763b06a1ef1-dark-flowchart-L1-0" data-look="classic" transform="translate(758, 68)"><rect class="basic label-container" style="" x="-130" y="-60" width="260" height="120"/><g class="label" style="" transform="translate(-100, -45)"><rect/><foreignObject width="200" height="90"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>Слой 1. Надёжность продуктов суммарно<br />вопрос: какую надёжность мы дали бизнесу</p></span></div></foreignObject></g></g><g class="node default" id="m-c763b06a1ef1-dark-flowchart-L2-1" data-look="classic" transform="translate(448, 68)"><rect class="basic label-container" style="" x="-130" y="-60" width="260" height="120"/><g class="label" style="" transform="translate(-100, -45)"><rect/><foreignObject width="200" height="90"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>Слой 2. Инженерное усилие команды<br />вопрос: какой ценой и насколько устойчиво</p></span></div></foreignObject></g></g><g class="node default" id="m-c763b06a1ef1-dark-flowchart-L3-2" data-look="classic" transform="translate(138, 68)"><rect class="basic label-container" style="" x="-130" y="-48.75" width="260" height="97.5"/><g class="label" style="" transform="translate(-100, -33.75)"><rect/><foreignObject width="200" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>Слой 3. Качество диалога<br />вопрос: встроена ли надёжность в продукт</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="m-c763b06a1ef1-dark-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="m-c763b06a1ef1-dark-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><linearGradient id="m-c763b06a1ef1-dark-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#3f3f46" stop-opacity="1"/><stop offset="100%" stop-color="#3f3f46" stop-opacity="1"/></linearGradient></svg>
</div>
</figure><h4 id="слой-1-надёжность-продуктов-суммарно-бизнес-слой">Слой 1. Надёжность продуктов суммарно (бизнес-слой)</h4>
<p>Не «средний SLO», а покрытие и распределение:</p>
<ul>
<li><strong>Доля продуктов, у которых SLO существует, написан в терминах CUJ и формально подписан продактом.</strong> Это метрика зрелости, а не надёжности. «6 из 8 продуктов имеют подписанный SLO» говорит больше, чем любой композит.</li>
<li><strong>Доля продуктов с действующей error budget policy.</strong> Не «есть SLO», а «есть записанное правило, что делать при сгорании». Обычно эта доля сильно меньше первой — и разрыв между ними и есть фронт работ.</li>
<li><strong>Burn-rate бюджетов по всем продуктам как тепловая карта, а не среднее.</strong> Восемь строк, в каждой — сгорание за квартал. Красные клетки видно сразу, и ни одна не тонет в зелёных соседях.</li>
<li><strong>Сумма money loss за квартал</strong> — если связка <code>SLI → ₽</code> настроена. Это единственная цифра из этого слоя, которую менеджмент понимает без перевода.</li>
</ul>
<h4 id="слой-2-инженерное-усилие-команды-продуктивность">Слой 2. Инженерное усилие команды (продуктивность)</h4>
<p>Сколько стоит надёжность в человекочасах и насколько это устойчиво:</p>
<ul>
<li><strong>Toil как % времени команды.</strong> Гугловский потолок — 50% (правило из главы <a href="https://sre.google/sre-book/eliminating-toil/" rel="noopener noreferrer" target="_blank">«Eliminating Toil»</a>
 в Google SRE Book); всё, что выше, означает, что команда тонет в ручной рутине и не строит автоматизацию. Toil — отличная инженерная метрика зрелости именно потому, что растёт незаметно и душит команду медленно.</li>
<li><strong>Доля задач, переходящих от SRE обратно в продуктовую команду.</strong> Антипаттерн — «SRE как owner навсегда»: команда взяла продукт на поддержку и больше его не отпускает. Здоровая динамика — знания и ответственность постепенно возвращаются в продуктовую команду, а SRE остаётся на инструментарии и сложных случаях.</li>
<li><strong>Время от инцидента до закрытого action item</strong> — не до восстановления. Восстановили за 20 минут, а исправили причину через полгода — это плохо, и средний MTTR это скрывает, а эта метрика показывает.</li>
<li><strong>Доля постмортемов с реализованными action items.</strong> Постмортем, после которого ничего не сделали, — это терапия, а не инженерия. Эта доля показывает, учится ли команда на самом деле.</li>
</ul>
<h4 id="слой-3-качество-диалога-управленческий-слой">Слой 3. Качество диалога (управленческий слой)</h4>
<p>Самый неочевидный и самый важный слой — он меряет ровно то, о чём вся статья: встроена ли надёжность в продукт или живёт в инженерной резервации.</p>
<ul>
<li><strong>Регулярность product reliability review.</strong> Проводится ли квартальный разбор бюджета с каждым продактом — или только с теми, кто сам пришёл. Цель — со всеми и по расписанию.</li>
<li><strong>Доля продуктов, где бизнес сам приходит за обсуждением бюджета.</strong> Это лакмус. Если продакт сам спрашивает «сколько у нас бюджета осталось» — диалог здоров. Если SRE его догоняет — нет. Эта доля растёт медленно и означает культурный сдвиг, а не процессный.</li>
<li><strong>NPS/CSAT-аналог от команд разработки на сервис SRE.</strong> Команда SRE — это тоже сервис, у него есть внутренние пользователи (продуктовые команды), и их удовлетворённость измерима. Низкий внутренний CSAT при хороших технических метриках — сигнал, что SRE воспринимают как тормоз, а не как партнёра.</li>
</ul>
<aside class="callout callout--note" role="note">
  <div class="callout__icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg></div>
  <div class="callout__body"><p class="callout__title">Слой 3 и культурная готовность</p>
    <div class="callout__content"><p>Третий слой пересекается с фазой 0 «cultural preparation» в Bear SRE Framework: SRE-практики невозможны без готовности бизнеса разговаривать. Метрики этого слоя, по сути, измеряют, насколько эта готовность реальна, а не декларирована. Можно вести их и как самостоятельную раскладку — но если у тебя уже есть рамка зрелости, слой 3 хорошо в неё ложится.</p></div>
  </div>
</aside><p>Соберём три слоя в одну таблицу — её удобно держать перед глазами при отчёте:</p>
<table>
  <thead>
      <tr>
          <th>Слой</th>
          <th>Вопрос</th>
          <th>Пример метрики</th>
          <th>Какой агрегат заменяет</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1. Надёжность продуктов</td>
          <td>Какую надёжность мы дали бизнесу</td>
          <td>Доля продуктов с подписанным CUJ-SLO; money loss за квартал; burn-rate тепловой картой</td>
          <td>Composite SLO</td>
      </tr>
      <tr>
          <td>2. Инженерное усилие</td>
          <td>Какой ценой и насколько устойчиво</td>
          <td>Toil %; время до закрытого action item; доля постмортемов с реализованными AI</td>
          <td>Средний MTTR</td>
      </tr>
      <tr>
          <td>3. Качество диалога</td>
          <td>Встроена ли надёжность в продукт</td>
          <td>Регулярность reliability review; доля «бизнес пришёл сам»; внутренний CSAT на SRE</td>
          <td>Число инцидентов</td>
      </tr>
  </tbody>
</table>
<p>Ни одна метрика из правой колонки («какой агрегат заменяет») не исчезает полностью — MTTR и счётчик инцидентов остаются полезными для внутренней диагностики. Но <strong>как метрика команды перед менеджментом</strong> они проигрывают трёхслойной раскладке, потому что усредняют то, что усреднять нельзя.</p>
<h3 id="как-это-звучит-в-отчёте-менеджменту">Как это звучит в отчёте менеджменту</h3>
<p>Финальная проверка всей раскладки — как команда отчитывается наверх. Сравни два варианта.</p>
<aside class="callout callout--warn" role="note">
  <div class="callout__icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg></div>
  <div class="callout__body"><p class="callout__title">Не делай SLO продуктов прямым KPI команды</p>
    <div class="callout__content"><p>Заманчиво объявить «продуктовую надёжность KPI команды SRE» — но это прямой путь к токсичным SLO. По <a href="https://ttttt.me/jtprogru_channel/4460" rel="noopener noreferrer" target="_blank">закону Гудхарта</a>
, как только SLO становится оценкой команды, она начинает оптимизировать цифру, а не надёжность: заниженные таргеты, «неудобные» события вне знаменателя, споры «считать ли инцидент инцидентом». Поэтому меряй команду не <strong>абсолютом</strong> SLO (он про продукт и принадлежит продакту), а <strong>дельтой и охватом</strong> — на сколько продуктов распространили подписанный SLO и policy, сократилось ли сгорание бюджета и money loss, вырос ли охват зрелым диалогом (слой 3). Занижением таргета это не саботируешь — потому и отчёт ниже построен на «было 4 → стало 6», а не на «composite SLO 99.94%».</p></div>
  </div>
</aside><p><strong>Плохо (агрегат):</strong> «У нас средний MTTR 22 минуты и composite SLO 99.94%». Менеджмент кивает, ничего не понимает, ни одно решение не меняется.</p>
<p><strong>Хорошо (три слоя):</strong> «За квартал укрепили подписанный SLO с error budget policy у 6 из 8 продуктов (было 4), суммарное сгорание бюджета упало на 35%, бизнес-потери от инцидентов сократились на N рублей. Toil держим на 40%. Два продукта вернули в зону ответственности продуктовых команд. Осталось два продукта без политики — это фронт на следующий квартал».</p>
<p>Второй отчёт показывает движение, цену и план. Это и есть язык, на котором SRE-команда разговаривает с менеджментом, когда продуктов больше одного, — не «средняя температура», а «вот что мы дали бизнесу и как конвертировали инженерное усилие в продуктовый результат».</p>
<h2 id="что-сделать-завтра-утром">Что сделать завтра утром</h2>
<p>Чек-лист «куда вернуться», когда дочитал. Пять вопросов — если на какой-то нет ответа, там и фронт работ.</p>
<ol>
<li><strong>Какой product reliability review встроен в наш квартальный план?</strong> Если ответ «никакой» или «по запросу» — начни с того, чтобы поставить в календарь регулярную встречу по бюджету с каждым продуктовым владельцем.</li>
<li><strong>Кто из бизнеса формально подписал error budget policy — и подписал ли вообще?</strong> Если не можешь назвать имя — у тебя SLO-артефакт, а не контракт. Это задача номер один.</li>
<li><strong>На какой панели я вижу „health по сценарию“, а не „health по сервису“?</strong> Если только по сервису — твои SLI повешены на ручки, а не на пути, и ты не видишь того, что чувствует пользователь.</li>
<li><strong>Сколько раз за последний квартал бизнес сам поднял разговор о трейд-оффе „фича против надёжности“?</strong> Если ноль — диалог пока односторонний, и слой 3 у тебя в красной зоне.</li>
<li><strong>Какой из метрик трёх слоёв у нас нет — и почему?</strong> Чаще всего отсутствует слой 3 (качество диалога), потому что его сложнее всего мерить. Но именно он отличает зрелую практику от набора дашбордов.</li>
</ol>
<h2 id="заключение">Заключение</h2>
<p>В «чертеже» я доказывал, что архитектура без SLO — это эстетика, а не инженерия. Эта статья добавляет вторую половину: <strong>SLO без диалога — это дашборд, а не управление.</strong></p>
<p>Чертёж надёжности сам по себе мёртв. Его надо защищать, торговать им и переписывать вместе с бизнесом каждый квартал. Технический инструмент — SLI, SLO, error budget — становится управленческим ровно в тот момент, когда у инженеров и бизнеса появляется одна картинка целевой надёжности и одна валюта компромиссов. До этого момента у тебя есть только красивые графики и предчувствия.</p>
<p>Три вещи, ради которых стоило городить всю статью:</p>
<ul>
<li><strong>Диалог — это формат принятия решений</strong>, а не презентация. Его сердце — записанная error budget policy, подписанная продуктовым владельцем.</li>
<li><strong>На собесе по SLO проверяют переговорный навык</strong>, а не арифметику. Сильный ответ начинается со сценария и денег и возвращает бизнесу выбор.</li>
<li><strong>Метрики команды при мультипродукте — это три слоя, а не один агрегат.</strong> Среднее по больнице прячет именно ту боль, ради которой метрику заводили.</li>
</ul>
<p>Надёжность не «достигается». Она каждый квартал заново строится в диалоге — и проигрывается ровно там, где этот диалог замолчал.</p>
<p>Спасибо, что дочитал до конца. Это продолжение цикла, начатого статьёй <a href="/posts/slo-as-architecture-blueprint/">«SLO как чертёж архитектуры»</a>
. Если у тебя есть свой опыт диалога с бизнесом о надёжности — особенно истории, как error budget policy реально остановила релиз или как менялись метрики команды с ростом числа продуктов, — буду рад услышать.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></content:encoded>
    </item><item>
      <title>Как декодировать QR-код руками</title>
      <link>https://jtprog.ru/posts/how-read-qr-code/</link>
      <pubDate>Wed, 20 May 2026 11:07:45 +0300</pubDate>
      <dc:creator>jtprogru</dc:creator>
      <guid isPermaLink="true">https://jtprog.ru/posts/how-read-qr-code/</guid>
      <category>QR</category>
      <category>Декодирование</category>
      <category>Стандарты</category>
      <category>Howto</category>
      <category domain="category">Howto</category>
      <enclosure url="https://jtprog.ru/howto.png" type="image/jpeg" length="0" />
      <media:thumbnail url="https://jtprog.ru/howto.png" /><description><![CDATA[<div><p>Привет, <code>%username%</code>! QR-коды в 2026 году встречаются буквально везде: меню в кафе, оплата в магазине, ссылка на Wi-Fi в аэропорту, чек из терминала. Камера телефона декодирует такой код за десятки миллисекунд, и большинство людей воспринимают QR как магический чёрно-белый прямоугольник, который «как-то превращается в URL». А внутри — обычный документированный стандарт ISO/IEC 18004, и при желании его реально разобрать вручную: с карандашом, бумагой и базовой арифметикой.</p>
<p>В этом разборе пройдём по шагам, как декодировать QR-код глазами: что такое finder patterns и тайминг-полоски, где зашиты маска и уровень коррекции ошибок, как читать данные зигзагом снизу-справа вверх и собирать из битов исходную строку. В качестве подопытного — самый маленький Version 1 (21×21) с содержимым <code>&quot;HI&quot;</code>, чтобы маска и зигзаг укладывались в голове, а не в Excel.</p>
<h2 id="tldr">TL;DR</h2>
<ul>
<li>Стандарт — <strong>ISO/IEC 18004</strong>, всего 40 версий: V1 — 21×21 модуль, дальше шаг +4 модуля на сторону до V40 (177×177).</li>
<li>Три больших квадрата по углам — <strong>finder patterns</strong>, задают ориентацию. Четвёртого (в правом нижнем углу) нет — это и есть «низ-право».</li>
<li>15 бит <strong>format info</strong> вокруг finder-ов хранят уровень коррекции (L/M/Q/H) и номер маски (0–7); защищены своим BCH-кодом и продублированы дважды.</li>
<li>Маска нужна, чтобы зона данных не складывалась в длинные одноцветные полосы и не имитировала случайно finder-паттерн — сканер бы поплыл. После XOR с правильной маской биты читаются «честно».</li>
<li>Данные читаются <strong>зигзагом снизу-справа вверх</strong>, парами столбцов, перепрыгивая тайминг-колонку №6, по 8 бит на байт.</li>
<li>Первые 4 бита — <strong>Mode Indicator</strong> (numeric / alphanumeric / byte / kanji), дальше <strong>Character Count Indicator</strong> переменной длины, потом сами данные, терминатор <code>0000</code> и padding <code>EC 11 EC 11 ...</code>.</li>
<li>За payload идут <strong>байты Reed-Solomon</strong> для коррекции ошибок: код над полем GF(256), число codeword&rsquo;ов зависит от версии и уровня (для V1-L — 7, для V1-H — уже 17). В этом разборе их сознательно пропускаем — без таблиц и GF-арифметики на бумаге не возьмёшь.</li>
</ul>
<p>После пары часов практики можно вытащить из небольшого кода (V1, 21×21) короткую строку вроде URL без сканера. До «прочитал визитку взглядом за секунду» — уже из области цирковых номеров: Reed-Solomon без вычислений в уме не выкрутишь, а на V10+ зигзаг становится ощутимо больно держать в голове.</p>
<hr>
<h2 id="подопытный">Подопытный</h2>
<p>Самый маленький размер — <strong>Version 1 (21×21 модуль)</strong>. Содержимое: <code>&quot;HI&quot;</code>. Раскрашены функциональные зоны.</p>
<figure class="post-figure">
    <img loading="lazy" decoding="async"
         src="/qr_labeled.png?v=1783493271"
         alt="Схема Version 1 QR-кода 21×21 с раскрашенными зонами: finder patterns, тайминг, format info, dark module, данные"></figure><hr>
<h2 id="шаг-1-ориентируемся">Шаг 1. Ориентируемся</h2>
<p>Три синих квадрата 7×7 — <strong>finder patterns</strong>. Они нужны сканеру, чтобы понять, где верх и поворот кода. Правило простое: три есть, а четвёртого (в правом нижнем углу) нет — туда смотрит «низ-право».</p>
<p>Вокруг каждого finder-а идёт <strong>separator</strong> — белая рамка в один модуль шириной (на схеме это пустая полоса между синим квадратом и всем остальным). Назначение прямолинейное: изолировать finder от данных, чтобы сканер не пытался разобрать «полуfinder-полуданные» на стыке и не плыл по координатам.</p>
<p>Между ними тянутся <strong>красные тайминг-полоски</strong> (строка 6 и столбец 6) — чередование чёрный-белый-чёрный. Они задают «линейку», по которой считаются координаты модулей. Если что-то поплыло — выравниваешься по ним.</p>
<p>Фиолетовый одиночный модуль — <strong>dark module</strong>, всегда чёрный по стандарту. Просто маркер, не несёт смысла.</p>
<p>Оранжевая зона — <strong>format info</strong>. 15 бит, продублированные дважды (для надёжности): одна копия идёт буквой Г вокруг левого верхнего finder-а, вторая — полоской справа от правого верхнего и снизу от левого нижнего. В ней зашифрованы две критичные вещи: <strong>уровень коррекции ошибок</strong> (L/M/Q/H) и <strong>номер маски</strong> (0–7).</p>
<p>Всё зелёное — это собственно данные плюс байты Рида-Соломона.</p>
<h3 id="чего-в-v1-ещё-нет-но-в-больших-версиях-встретишь">Чего в V1 ещё нет, но в больших версиях встретишь</h3>
<p>В нашей маленькой сетке всё описанное выше — это полный набор функциональных зон. Но как только переходишь к версиям побольше, появляются ещё две вещи:</p>
<ul>
<li><strong>Alignment patterns</strong> — маленькие квадраты 5×5 с чёрной точкой в центре, разбросанные по полю. Появляются с V2 (один штук, в правом нижнем углу), к V7 их уже шесть, а у V40 — целых 46. Нужны для <strong>локальной</strong> компенсации искажений сетки: V1 ещё читается «по линейке тайминга», а у большого QR на смятой или сфотографированной под углом картинке координаты модулей плывут, и без локальных якорей сканер промахивается.</li>
<li><strong>Version info</strong> — два блока 6×3 рядом с правым верхним и левым нижним finder-ами, появляются с V7. Внутри 18 бит: 6 бит самого номера версии и 12 бит BCH-чётности. Подход тот же, что у format info, только код покрупнее — BCH(18, 6), тоже исправляет до 3 ошибок. Декодеру эта зона нужна, чтобы достоверно определить размер кода, не доверяя «посчитаю клетки по краю» (на размытом снимке такой подсчёт ломается легко).</li>
</ul>
<p>В V1 этого ничего нет, поэтому в нашем разборе обходимся без них — но если ты потом возьмёшь V3 с того же чека, держи их в голове: чёрная точка в правом нижнем — не часть данных, а alignment.</p>
<hr>
<h2 id="шаг-2-снимаем-format-info">Шаг 2. Снимаем format info</h2>
<p>Биты идут: вдоль строки 8 слева направо (с пропуском тайминг-колонки), а потом по столбцу 8 снизу вверх (тоже с пропуском тайминг-строки). Старший бит = #14, младший = #0.</p>
<figure class="post-figure">
    <img loading="lazy" decoding="async"
         src="/format_info.png?v=1783493271"
         alt="Фокус на левый верхний угол: 15 клеток format info с номерами #14…#0 и их значениями"></figure><p>Считываем по порядку от #14 до #0:</p>
<div class="codeblock"><button class="codeblock__copy" type="button" data-copy aria-label="Скопировать" title="Скопировать"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button><pre tabindex="0"><code>сырые биты : 1 1 0 1 1 0 0 0 1 0 0 0 0 0 1
XOR-маска  : 1 0 1 0 1 0 0 0 0 0 1 0 0 1 0
─────────────────────────────────────────
результат  : 0 1 1 1 0 0 0 0 1 0 1 0 0 1 1</code></pre>
</div>
<p>Маска <code>101010000010010</code> зашита в стандарте — иначе формат, состоящий из нулей, тоже был бы валидным, и любая дырка на пустом месте всё ломала бы.</p>
<p>Разбираем результат <code>011100001010011</code>:</p>
<ul>
<li><strong>биты 14–13</strong> = <code>01</code> → уровень коррекции <strong>L</strong> (~7 % избыточности)</li>
<li><strong>биты 12–10</strong> = <code>110</code> → <strong>маска №6</strong></li>
<li>остальные 10 бит — BCH-код для коррекции ошибок в самих этих 15 битах (нам не нужны).</li>
</ul>
<p>Теперь самое важное: мы знаем маску. Значит, можно <strong>снять её</strong> с зелёной зоны данных и прочитать настоящие биты.</p>
<p>Маска №6 задаётся формулой: клетка <code>(r, c)</code> инвертируется, если</p>
$$
((r \cdot c) \bmod 2 + (r \cdot c) \bmod 3) \bmod 2 == 0
$$<h3 id="кодирование-уровня-коррекции">Кодирование уровня коррекции</h3>
<table>
  <thead>
      <tr>
          <th>биты</th>
          <th>уровень</th>
          <th>избыточность</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>01</code></td>
          <td>L</td>
          <td>~7 %</td>
      </tr>
      <tr>
          <td><code>00</code></td>
          <td>M</td>
          <td>~15 %</td>
      </tr>
      <tr>
          <td><code>11</code></td>
          <td>Q</td>
          <td>~25 %</td>
      </tr>
      <tr>
          <td><code>10</code></td>
          <td>H</td>
          <td>~30 %</td>
      </tr>
  </tbody>
</table>
<h3 id="bch15-5-под-капотом">BCH(15, 5) под капотом</h3>
<p>Format info — это не просто 15 случайных бит. Это <strong>BCH-код (15, 5)</strong> над <code>GF(2)</code>: 5 содержательных бит (2 на EC level + 3 на номер маски) защищаются 10 битами чётности. Такой код <strong>исправляет до 3 ошибочных бит</strong> внутри своих 15 — то есть даже если три клетки в зоне format info замазаны или прокрашены неправильно, декодер всё равно вытянет верный уровень коррекции и маску.</p>
<p>Кодирование считается через <strong>порождающий полином</strong></p>
$$
G(x) = x^{10} + x^8 + x^5 + x^4 + x^2 + x + 1
$$<p>в двоичном виде — <code>10100110111</code>. Алгоритм такой:</p>
<ol>
<li>Берём 5 бит данных <code>d</code> = <code>[EC level (2 бита)] [mask (3 бита)]</code>.</li>
<li>Сдвигаем влево на 10 позиций: получаем <code>d · x^{10}</code>.</li>
<li>Делим в <code>GF(2)</code> (по сути — длинное XOR-вычитание) на <code>G(x)</code>, остаток — это 10 бит чётности.</li>
<li>Склеиваем: <code>[5 бит данных] [10 бит остатка]</code> = 15-битное кодовое слово.</li>
</ol>
<p>Чтобы проверить целостность при чтении, декодер делает то же самое в обратную сторону: делит прочитанные 15 бит на <code>G(x)</code>. Если остаток нулевой — ошибок не было. Если ненулевой — это <strong>синдром</strong>, по которому находятся испорченные биты. Для коротких BCH вроде нашего (всего 32 валидных слова, по числу комбинаций <code>EC × mask</code>) обычно держат готовую таблицу синдромов — это быстрее, чем гонять полный алгоритм исправления каждый раз.</p>
<p>Теперь становится понятно, <strong>зачем нужна XOR-маска</strong> <code>101010000010010</code>. Без неё формат из одних нулей был бы валидным кодовым словом («EC level M, маска 0, нулевой остаток») — а это совпадает с пустой или замазанной белой областью QR. После XOR-а сплошные нули или единицы гарантированно дают невалидный синдром, и декодер не примет шум за легитимный формат.</p>
<p>И ещё деталь: те же 15 бит <strong>продублированы дважды</strong>, причём копии разнесены по разным углам — буква Г вокруг левого верхнего finder-а и полоска снизу от правого верхнего + справа от левого нижнего. Это страховка от случая, когда одна копия повреждена сильнее, чем BCH способен починить (больше 3 ошибок): декодер читает обе, считает синдром у каждой и берёт ту, что чище.</p>
<hr>
<h2 id="шаг-3-зигзаг-и-снятие-маски">Шаг 3. Зигзаг и снятие маски</h2>
<p>Биты данных читаются <strong>парами столбцов справа налево, зигзагом</strong>: пара (20, 19) — снизу вверх, пара (18, 17) — сверху вниз, и так далее, перепрыгивая тайминг-колонку №6. Внутри каждого ряда читается сначала правая клетка, потом левая. Все функциональные модули (finder, тайминг, format, dark) — пропускаются.</p>
<figure class="post-figure">
    <img loading="lazy" decoding="async"
         src="/zigzag.png?v=1783493271"
         alt="Путь обхода данных: первые 32 бита подсвечены цветовой шкалой от красного к зелёному, серым — функциональные модули"></figure><p>Видно, как поток идёт парами столбцов: красный (биты 1–2) внизу справа, поднимается вверх по правым двум колонкам до битов 15–16, потом перепрыгивает в следующую пару (зелёный, биты 17–32) и идёт <strong>вниз</strong>.</p>
<p>Каждый бит, прочитанный из решётки, <strong>XOR-им с маской 6</strong>: если для координаты <code>(r, c)</code> маска срабатывает — бит инвертируется.</p>
<p>После маскинга первые 4 байта получаются такими:</p>
<div class="codeblock"><button class="codeblock__copy" type="button" data-copy aria-label="Скопировать" title="Скопировать"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button><pre tabindex="0"><code>байт 1: 00100000  = 0x20
байт 2: 00010011  = 0x13
байт 3: 00001111  = 0x0F
байт 4: 00000000  = 0x00</code></pre>
</div>
<h3 id="восемь-масок-и-их-формулы">Восемь масок и их формулы</h3>
<p>Полный набор из стандарта — клетка <code>(r, c)</code> (строка, колонка) инвертируется, если выражение даёт <code>true</code>:</p>
<table>
  <thead>
      <tr>
          <th>№</th>
          <th>формула</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>0</td>
          <td><code>(r + c) mod 2 == 0</code></td>
      </tr>
      <tr>
          <td>1</td>
          <td><code>r mod 2 == 0</code></td>
      </tr>
      <tr>
          <td>2</td>
          <td><code>c mod 3 == 0</code></td>
      </tr>
      <tr>
          <td>3</td>
          <td><code>(r + c) mod 3 == 0</code></td>
      </tr>
      <tr>
          <td>4</td>
          <td><code>(⌊r/2⌋ + ⌊c/3⌋) mod 2 == 0</code></td>
      </tr>
      <tr>
          <td>5</td>
          <td><code>(r · c) mod 2 + (r · c) mod 3 == 0</code></td>
      </tr>
      <tr>
          <td>6</td>
          <td><code>((r · c) mod 2 + (r · c) mod 3) mod 2 == 0</code></td>
      </tr>
      <tr>
          <td>7</td>
          <td><code>((r + c) mod 2 + (r · c) mod 3) mod 2 == 0</code></td>
      </tr>
  </tbody>
</table>
<p>Маски устроены по-разному осмысленно: №0–№3 — простые «шахматные» / «полосатые» шаблоны, №4–№7 — более «шумные», с произведениями координат. Чем разнообразнее набор, тем больше шанс, что хотя бы одна из восьми разломает любой неудачный битовый рисунок в payload.</p>
<p>А выбирает кодировщик так: накладывает поочерёдно каждую из восьми масок на черновой код и считает <strong>штрафную функцию</strong> (penalty score). Штрафы накапливаются за длинные одноцветные полосы (5+ модулей подряд), за блоки 2×2 одного цвета, за паттерны, похожие на finder (<code>1:1:3:1:1</code>), и за дисбаланс чёрного и белого. Маска с минимальной суммой штрафов уходит в финальный QR. Поэтому маска №6 в нашем подопытном — не «любимая маска автора», а просто та, что для конкретного payload <code>&quot;HI&quot;</code> сложилась с минимальным penalty.</p>
<hr>
<h2 id="шаг-4-парсим-payload">Шаг 4. Парсим payload</h2>
<p>Первые 32 бита склеиваем в один поток и режем по логике формата:</p>
<div class="codeblock"><button class="codeblock__copy" type="button" data-copy aria-label="Скопировать" title="Скопировать"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button><pre tabindex="0"><code>0010 | 000000010 | 01100001111 | 0000
 ↑         ↑            ↑         ↑
 │         │            │         └─ терминатор «конец данных»
 │         │            └─ символы (11 бит на пару)
 │         └─ счётчик: 2 символа (9 бит для V1 alpha)
 └─ режим: 0010 = alphanumeric</code></pre>
</div>
<p>Каждый payload в QR начинается одинаково: <strong>Mode Indicator</strong> (4 бита) + <strong>Character Count Indicator</strong> (CCI, ширина зависит от пары version+mode) + сами данные. Ширина CCI меняется ступеньками: для alphanumeric это 9 бит на V1–V9, 11 бит на V10–V26 и 13 бит на V27–V40. Сделано осмысленно: в маленьком V1 пол-байта не хочется тратить на нули перед длиной, а в большом V40 9 бит уже банально не хватит — туда влезает до 4296 alphanumeric-символов. Поэтому при ручном декодировании всегда первым делом смотришь на версию (размер сетки), и только потом — где у CCI заканчиваются биты.</p>
<h3 id="декодируем-сами-символы">Декодируем сами символы</h3>
<p>Декодируем 11 бит данных: <code>01100001111</code> в десятичном = <strong>783</strong>.</p>
<p>В alphanumeric-режиме два символа упаковываются как <code>c1 × 45 + c2</code>. Делим: <code>783 = 17 × 45 + 18</code>. Таблица alphanumeric-алфавита: <code>0-9, A-Z, [space] $ % * + - . / :</code> — итого 45 значений, отсюда и множитель.</p>
<ul>
<li>17 → <strong>H</strong></li>
<li>18 → <strong>I</strong></li>
</ul>
<p>Получили <code>&quot;HI&quot;</code>.</p>
<p>Если бы строка была нечётной длины, последний символ кодировался бы отдельно — не 11, а 6 бит. Это полезно держать в голове: после CCI всегда сначала идут полные пары, а потом — возможно — «хвост» в 6 бит. Аналогично numeric-режим режется тройками по 10 бит, а одиночный/парный хвост — 4 и 7 бит соответственно. Стандарт педантично оптимизирует каждый бит: считает, что место в QR — это дорого.</p>
<h3 id="терминатор-padding-и-reed-solomon">Терминатор, padding и Reed-Solomon</h3>
<p>Сразу за данными идёт терминатор <code>0000</code> — четыре нуля, говорящие «всё, payload закончился». По стандарту терминатор можно укоротить или вовсе выкинуть, если данные ровно дотягиваются до конца блока — но обычно его пишут целиком, и декодер на него ориентируется.</p>
<p>Дальше биты добиваются нулями до ближайшей границы байта, и потом блок данных заполняется до своей ёмкости чередующимися <strong>padding-байтами</strong> <code>0xEC</code> (<code>11101100</code>) и <code>0x11</code> (<code>00010001</code>). Эти два конкретных значения зашиты в стандарте — выбраны они так, чтобы их битовый рисунок под любой из восьми масок ломал длинные одноцветные полосы и не складывался во что-то, похожее на finder-pattern (1:1:3:1:1). Поэтому если вытащил из кода строку «HI», а дальше пошло <code>EC 11 EC 11 EC 11 ...</code> — это не повреждение, это норма. И наоборот: если padding выглядит как-то иначе — где-то в зигзаге ошибся.</p>
<p>Для V1 с уровнем коррекции L общий размер блока — <strong>26 codeword&rsquo;ов</strong> (байт), из которых под данные отведено 19, а остальные 7 — это <strong>байты Reed-Solomon</strong>: код над полем GF(256), способный поднять до 3 искажённых байт на блок. Для нашего <code>&quot;HI&quot;</code> это значит: 4 уже прочитанных байта (<code>20 13 0F 00</code>) + 15 байт padding&rsquo;а (<code>EC 11 EC 11 ... EC</code>) + 7 байт RS = ровно 26, полная ёмкость V1-L.</p>
<p>Раскручивать Reed-Solomon руками — занятие на отдельный пост: нужно считать синдромы, через алгоритм Берлекэмпа-Месси искать полином-локатор ошибок, потом Chien-search&rsquo;ем — позиции, потом формулой Форни — значения, и всё это в арифметике GF(256). В декодере без ошибок RS-байты можно просто игнорировать — и в этом разборе мы именно так и поступим. Поднимется тема — вернёмся.</p>
<h3 id="режимы-данных">Режимы данных</h3>
<table>
  <thead>
      <tr>
          <th>код</th>
          <th>режим</th>
          <th>бит на символ</th>
          <th>счётчик в V1</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>0001</code></td>
          <td>numeric</td>
          <td>3.33 (10 бит на 3 цифры)</td>
          <td>10 бит</td>
      </tr>
      <tr>
          <td><code>0010</code></td>
          <td>alphanumeric</td>
          <td>5.5 (11 бит на 2 символа)</td>
          <td>9 бит</td>
      </tr>
      <tr>
          <td><code>0100</code></td>
          <td>byte</td>
          <td>8</td>
          <td>8 бит</td>
      </tr>
      <tr>
          <td><code>1000</code></td>
          <td>kanji</td>
          <td>13</td>
          <td>8 бит</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="тонкие-места-на-которых-легко-споткнуться">Тонкие места, на которых легко споткнуться</h2>
<p>Когда сидишь с распечатанным QR и разбираешь его руками, есть пара мест, где мозг гарантированно даст осечку. Перечислю те, что встречал чаще всего — и в собственных первых попытках, и в чужих разборах в чате.</p>
<ul>
<li><strong>Забыл пропустить тайминг-колонку №6 в зигзаге.</strong> Самый популярный баг: пары столбцов должны «перепрыгивать» эту колонку, а не читать её клетки как данные. Если payload пошёл бредом с первого же байта — почти наверняка дело именно тут.</li>
<li><strong>Снял маску не только с данных.</strong> Маска накладывается <strong>исключительно</strong> на data + EC, то есть на зелёную зону. Finder, separators, тайминг, format info, dark module — не трогаем. Если случайно проинвертировал маской finder-патерны, дальше развалится всё, включая саму ориентацию.</li>
<li><strong>Перепутал порядок битов внутри пары столбцов.</strong> В зигзаге в каждой строке сначала правая клетка, потом левая. Прочитал наоборот — payload идёт зеркально по 2 бита, терминатор находится где-то в середине, и парсинг падает.</li>
<li><strong>Забыл, что зигзаг bounce-ит.</strong> Пары столбцов чередуют направление: (20, 19) — снизу вверх, (18, 17) — сверху вниз, (16, 15) — снова вверх. Это не «всегда снизу вверх», это «змейка». На стыках пар легко проскочить инерцией.</li>
<li><strong>Принял <code>EC 11 EC 11 ...</code> за продолжение данных.</strong> После терминатора <code>0000</code> идёт padding до конца блока данных. Если в декодированном байт-потоке после реального payload пошли повторяющиеся <code>EC 11</code> — не пытайся их парсить как «следующее сообщение», это просто забивание блока до 19 байт (для V1-L).</li>
</ul>
<hr>
<h2 id="что-с-этим-делать-на-практике">Что с этим делать на практике</h2>
<p>Чтобы из теории получилось ощущение «руками потрогал», самый рабочий заход — такой:</p>
<ol>
<li><strong>Сгенерируй V1 QR с заранее известным содержимым.</strong> Удобнее всего — через <a href="https://www.nayuki.io/page/qr-code-generator-library" rel="noopener noreferrer" target="_blank">онлайн-демо Nayuki</a>
 или через мой <a href="https://github.com/jtprogru/wifi-qr" rel="noopener noreferrer" target="_blank">wifi-qr</a>
 (для коротких SSID он как раз выдаёт V1–V2). Возьми короткую alphanumeric-строку: <code>&quot;HI&quot;</code>, <code>&quot;OK&quot;</code>, <code>&quot;TEST&quot;</code>. Не забудь зафиксировать <strong>уровень коррекции</strong> (L) и <strong>номер маски</strong> — потом будет с чем сверять.</li>
<li><strong>Распечатай крупно</strong> — A4 на 21×21 хватает с запасом. Альтернатива — нарисовать сетку на бумаге в клетку и закрасить модули вручную. Звучит занудно, но именно ручная отрисовка лучше всего ломает «магический квадратик» в голове.</li>
<li><strong>Подсвети функциональные зоны</strong> карандашом или маркерами разных цветов: три finder-а, separators, обе тайминг-полоски, dark module, обе копии format info. После этого зелёная зона данных выделится сама собой.</li>
<li><strong>Прочитай format info</strong> → XOR с <code>101010000010010</code> → выпиши уровень коррекции и номер маски. Сверь с тем, что задал в генераторе. Сошлось — значит, Шаг 2 ты понял правильно.</li>
<li><strong>Обведи клетки, инвертируемые выбранной маской.</strong> Берёшь формулу из таблицы выше и проходишь по всей data-зоне: где условие — <code>true</code>, ставишь крестик. Эти клетки будешь инвертировать при чтении.</li>
<li><strong>Пройди зигзагом первые 32 бита</strong>, для каждого инвертируй или нет в зависимости от маски, и распарси: 4 бита mode → CCI → данные. Должна получиться твоя исходная строка.</li>
</ol>
<p>Когда «свой» QR разобрался — попробуй на чужом: возьми QR с любого чека из магазина или с Wi-Fi-стикера в кофейне. Только сразу проверь, что это <strong>V1 или V2</strong> (для V1 сетка 21×21, для V2 — 25×25, считается по краю). На больших версиях ручной зигзаг быстро превращается в подвиг ради подвига.</p>
<hr>
<h2 id="итог">Итог</h2>
<p>Если потренироваться, то для маленьких QR (V1, alphanumeric, короткий текст) реально читать глазами за пару минут. Узкое горлышко — держать в голове маску и зигзаг, две операции, которые мозг плохо параллелит. Помогает распечатать QR на бумаге и фломастером заштриховывать клетки, которые маска инвертирует — после этого данные читаются «как обычный бинарный поток».</p>
<h3 id="алгоритм-по-шагам">Алгоритм по шагам</h3>
<ol>
<li>Найти три finder patterns → определить ориентацию.</li>
<li>Прочитать format info → XOR с <code>101010000010010</code> → выделить EC level и mask number.</li>
<li>Применить маску к данным (XOR по формуле выбранной маски).</li>
<li>Прочитать биты зигзагом снизу-справа вверх, парами столбцов.</li>
<li>Распарсить: 4 бита режим → N бит счётчик → данные → терминатор.</li>
<li>(Опционально) проверить Reed-Solomon коды.</li>
</ol>
<h3 id="дальше-копать">Дальше копать</h3>
<ul>
<li><a href="https://robertheaton.com/2018/05/03/decoding-a-qr-code-by-hand/" rel="noopener noreferrer" target="_blank">How to decode a QR code by hand — Robert Heaton</a>
 — пошаговый разбор того же V1 «HI», только не моими словами. Хорошо для проверки себя: если в каком-то месте разошлись — значит, не до конца понял шаг.</li>
<li><a href="https://www.thonky.com/qr-code-tutorial/" rel="noopener noreferrer" target="_blank">Thonky&rsquo;s QR Code Tutorial</a>
 — самый полный учебник в сети: все 40 версий, восемь масок с примерами, готовые таблицы для Reed-Solomon, разбор форматов. Если Heaton — обзорная статья, Thonky тянет уже на 30-страничный курс.</li>
<li><a href="https://github.com/nayuki/QR-Code-generator" rel="noopener noreferrer" target="_blank">nayuki/QR-Code-generator</a>
 — каноническая референсная реализация на C/C++/Java/JS/Python/Rust. Читается как продолжение этого поста: чёткие имена, в комментариях — формулы из стандарта, никакой магии. У того же автора на <code>nayuki.io</code> лежит онлайн-демо с настраиваемой версией и маской — удобно сверять свои выкладки с эталоном.</li>
<li><a href="https://github.com/jtprogru/wifi-qr" rel="noopener noreferrer" target="_blank">jtprogru/wifi-qr</a>
 — мой собственный мини-проектик «с обратной стороны»: тащит <code>WIFI_SSID</code> и <code>WIFI_PASSWD</code> из <code>.env</code> и собирает Wi-Fi-QR в PNG одной командой <code>make run</code>. Внутри — крошечный Python-скрипт поверх библиотеки <code>qrcode</code>. Удобный мостик от «понимаю по битам» к «генерирую за секунду», заодно — готовый QR для гостевой Wi-Fi.</li>
<li><a href="https://github.com/zxing/zxing" rel="noopener noreferrer" target="_blank">zxing/zxing</a>
 — production-grade декодер от Google, тот самый, который много лет крутился в Barcode Scanner на Android. Полезно посмотреть, чтобы понять разницу между «вытащить V1 в идеальных условиях» и «прочитать URL с мятого чека под углом 30° при тусклом свете».</li>
<li><a href="https://en.wikiversity.org/wiki/Reed-Solomon_codes_for_coders" rel="noopener noreferrer" target="_blank">Reed–Solomon codes for coders</a>
 на Wikiversity — лучший learn-by-doing разбор RS-кодов из всех, что попадались. GF(256), порождающие полиномы, синдромы, исправление ошибок — всё последовательно разложено по шагам, с примерами на Python. Без этой статьи в RS-кодах было сложно ухватиться хоть за что-то.</li>
<li><a href="https://en.wikipedia.org/wiki/QR_code" rel="noopener noreferrer" target="_blank">QR code — Wikipedia</a>
 — на удивление приличная обзорная статья: версии, режимы, история Denso Wave, лимиты по объёму данных, эволюция стандарта. Хорошо стартовать с неё, если QR в голове пока «магический квадратик».</li>
<li><strong>ISO/IEC 18004:2015</strong> — сам стандарт. Платный, но если возишься со штрихкодами всерьёз — без него никак: только там нормально расписаны все 40 версий, все 4 режима кодирования и точные алгоритмы коррекции.</li>
</ul>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></description>
      <content:encoded><![CDATA[<style>/* Inline-CSS, который тема вкладывает в <description> каждого item'а
   RSS-фида (layouts/index.rss.xml). RSS-ридеры (Feedly, Inoreader,
   NetNewsWire) уважают <style> внутри description с переменной
   степенью энтузиазма — это базовый fallback, достаточный для читаемой
   типографики, не более.

   Цвета продублированы из 00-vars.css (light-палитра) — поправь
   синхронно при изменении --bg / --text / --accent / --border. */

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  line-height: 1.6;
  color: #1c1c1f;
  max-width: 720px;
  margin: 0 auto;
  padding: 1em;
}
h1, h2, h3 { line-height: 1.25; margin-top: 1.4em; }
a { color: #c2410c; }
pre {
  background: #1e1e24;
  color: #e8e6df;
  padding: 1em;
  border-radius: 6px;
  overflow-x: auto;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.9em;
}
code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  background: #f3f1ed;
  padding: 0.1em 0.4em;
  border-radius: 4px;
}
pre code { background: transparent; padding: 0; }
blockquote {
  border-left: 3px solid #c2410c;
  padding-left: 1em;
  color: #5b5b62;
  font-style: italic;
  margin-left: 0;
}
img { max-width: 100%; height: auto; border-radius: 6px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #e5e3dc; padding: 6px 10px; text-align: left; }
</style><div><p>Привет, <code>%username%</code>! QR-коды в 2026 году встречаются буквально везде: меню в кафе, оплата в магазине, ссылка на Wi-Fi в аэропорту, чек из терминала. Камера телефона декодирует такой код за десятки миллисекунд, и большинство людей воспринимают QR как магический чёрно-белый прямоугольник, который «как-то превращается в URL». А внутри — обычный документированный стандарт ISO/IEC 18004, и при желании его реально разобрать вручную: с карандашом, бумагой и базовой арифметикой.</p>
<p>В этом разборе пройдём по шагам, как декодировать QR-код глазами: что такое finder patterns и тайминг-полоски, где зашиты маска и уровень коррекции ошибок, как читать данные зигзагом снизу-справа вверх и собирать из битов исходную строку. В качестве подопытного — самый маленький Version 1 (21×21) с содержимым <code>&quot;HI&quot;</code>, чтобы маска и зигзаг укладывались в голове, а не в Excel.</p>
<h2 id="tldr">TL;DR</h2>
<ul>
<li>Стандарт — <strong>ISO/IEC 18004</strong>, всего 40 версий: V1 — 21×21 модуль, дальше шаг +4 модуля на сторону до V40 (177×177).</li>
<li>Три больших квадрата по углам — <strong>finder patterns</strong>, задают ориентацию. Четвёртого (в правом нижнем углу) нет — это и есть «низ-право».</li>
<li>15 бит <strong>format info</strong> вокруг finder-ов хранят уровень коррекции (L/M/Q/H) и номер маски (0–7); защищены своим BCH-кодом и продублированы дважды.</li>
<li>Маска нужна, чтобы зона данных не складывалась в длинные одноцветные полосы и не имитировала случайно finder-паттерн — сканер бы поплыл. После XOR с правильной маской биты читаются «честно».</li>
<li>Данные читаются <strong>зигзагом снизу-справа вверх</strong>, парами столбцов, перепрыгивая тайминг-колонку №6, по 8 бит на байт.</li>
<li>Первые 4 бита — <strong>Mode Indicator</strong> (numeric / alphanumeric / byte / kanji), дальше <strong>Character Count Indicator</strong> переменной длины, потом сами данные, терминатор <code>0000</code> и padding <code>EC 11 EC 11 ...</code>.</li>
<li>За payload идут <strong>байты Reed-Solomon</strong> для коррекции ошибок: код над полем GF(256), число codeword&rsquo;ов зависит от версии и уровня (для V1-L — 7, для V1-H — уже 17). В этом разборе их сознательно пропускаем — без таблиц и GF-арифметики на бумаге не возьмёшь.</li>
</ul>
<p>После пары часов практики можно вытащить из небольшого кода (V1, 21×21) короткую строку вроде URL без сканера. До «прочитал визитку взглядом за секунду» — уже из области цирковых номеров: Reed-Solomon без вычислений в уме не выкрутишь, а на V10+ зигзаг становится ощутимо больно держать в голове.</p>
<hr>
<h2 id="подопытный">Подопытный</h2>
<p>Самый маленький размер — <strong>Version 1 (21×21 модуль)</strong>. Содержимое: <code>&quot;HI&quot;</code>. Раскрашены функциональные зоны.</p>
<figure class="post-figure">
    <img loading="lazy" decoding="async"
         src="/qr_labeled.png?v=1783493271"
         alt="Схема Version 1 QR-кода 21×21 с раскрашенными зонами: finder patterns, тайминг, format info, dark module, данные"></figure><hr>
<h2 id="шаг-1-ориентируемся">Шаг 1. Ориентируемся</h2>
<p>Три синих квадрата 7×7 — <strong>finder patterns</strong>. Они нужны сканеру, чтобы понять, где верх и поворот кода. Правило простое: три есть, а четвёртого (в правом нижнем углу) нет — туда смотрит «низ-право».</p>
<p>Вокруг каждого finder-а идёт <strong>separator</strong> — белая рамка в один модуль шириной (на схеме это пустая полоса между синим квадратом и всем остальным). Назначение прямолинейное: изолировать finder от данных, чтобы сканер не пытался разобрать «полуfinder-полуданные» на стыке и не плыл по координатам.</p>
<p>Между ними тянутся <strong>красные тайминг-полоски</strong> (строка 6 и столбец 6) — чередование чёрный-белый-чёрный. Они задают «линейку», по которой считаются координаты модулей. Если что-то поплыло — выравниваешься по ним.</p>
<p>Фиолетовый одиночный модуль — <strong>dark module</strong>, всегда чёрный по стандарту. Просто маркер, не несёт смысла.</p>
<p>Оранжевая зона — <strong>format info</strong>. 15 бит, продублированные дважды (для надёжности): одна копия идёт буквой Г вокруг левого верхнего finder-а, вторая — полоской справа от правого верхнего и снизу от левого нижнего. В ней зашифрованы две критичные вещи: <strong>уровень коррекции ошибок</strong> (L/M/Q/H) и <strong>номер маски</strong> (0–7).</p>
<p>Всё зелёное — это собственно данные плюс байты Рида-Соломона.</p>
<h3 id="чего-в-v1-ещё-нет-но-в-больших-версиях-встретишь">Чего в V1 ещё нет, но в больших версиях встретишь</h3>
<p>В нашей маленькой сетке всё описанное выше — это полный набор функциональных зон. Но как только переходишь к версиям побольше, появляются ещё две вещи:</p>
<ul>
<li><strong>Alignment patterns</strong> — маленькие квадраты 5×5 с чёрной точкой в центре, разбросанные по полю. Появляются с V2 (один штук, в правом нижнем углу), к V7 их уже шесть, а у V40 — целых 46. Нужны для <strong>локальной</strong> компенсации искажений сетки: V1 ещё читается «по линейке тайминга», а у большого QR на смятой или сфотографированной под углом картинке координаты модулей плывут, и без локальных якорей сканер промахивается.</li>
<li><strong>Version info</strong> — два блока 6×3 рядом с правым верхним и левым нижним finder-ами, появляются с V7. Внутри 18 бит: 6 бит самого номера версии и 12 бит BCH-чётности. Подход тот же, что у format info, только код покрупнее — BCH(18, 6), тоже исправляет до 3 ошибок. Декодеру эта зона нужна, чтобы достоверно определить размер кода, не доверяя «посчитаю клетки по краю» (на размытом снимке такой подсчёт ломается легко).</li>
</ul>
<p>В V1 этого ничего нет, поэтому в нашем разборе обходимся без них — но если ты потом возьмёшь V3 с того же чека, держи их в голове: чёрная точка в правом нижнем — не часть данных, а alignment.</p>
<hr>
<h2 id="шаг-2-снимаем-format-info">Шаг 2. Снимаем format info</h2>
<p>Биты идут: вдоль строки 8 слева направо (с пропуском тайминг-колонки), а потом по столбцу 8 снизу вверх (тоже с пропуском тайминг-строки). Старший бит = #14, младший = #0.</p>
<figure class="post-figure">
    <img loading="lazy" decoding="async"
         src="/format_info.png?v=1783493271"
         alt="Фокус на левый верхний угол: 15 клеток format info с номерами #14…#0 и их значениями"></figure><p>Считываем по порядку от #14 до #0:</p>
<div class="codeblock"><button class="codeblock__copy" type="button" data-copy aria-label="Скопировать" title="Скопировать"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button><pre tabindex="0"><code>сырые биты : 1 1 0 1 1 0 0 0 1 0 0 0 0 0 1
XOR-маска  : 1 0 1 0 1 0 0 0 0 0 1 0 0 1 0
─────────────────────────────────────────
результат  : 0 1 1 1 0 0 0 0 1 0 1 0 0 1 1</code></pre>
</div>
<p>Маска <code>101010000010010</code> зашита в стандарте — иначе формат, состоящий из нулей, тоже был бы валидным, и любая дырка на пустом месте всё ломала бы.</p>
<p>Разбираем результат <code>011100001010011</code>:</p>
<ul>
<li><strong>биты 14–13</strong> = <code>01</code> → уровень коррекции <strong>L</strong> (~7 % избыточности)</li>
<li><strong>биты 12–10</strong> = <code>110</code> → <strong>маска №6</strong></li>
<li>остальные 10 бит — BCH-код для коррекции ошибок в самих этих 15 битах (нам не нужны).</li>
</ul>
<p>Теперь самое важное: мы знаем маску. Значит, можно <strong>снять её</strong> с зелёной зоны данных и прочитать настоящие биты.</p>
<p>Маска №6 задаётся формулой: клетка <code>(r, c)</code> инвертируется, если</p>
$$
((r \cdot c) \bmod 2 + (r \cdot c) \bmod 3) \bmod 2 == 0
$$<h3 id="кодирование-уровня-коррекции">Кодирование уровня коррекции</h3>
<table>
  <thead>
      <tr>
          <th>биты</th>
          <th>уровень</th>
          <th>избыточность</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>01</code></td>
          <td>L</td>
          <td>~7 %</td>
      </tr>
      <tr>
          <td><code>00</code></td>
          <td>M</td>
          <td>~15 %</td>
      </tr>
      <tr>
          <td><code>11</code></td>
          <td>Q</td>
          <td>~25 %</td>
      </tr>
      <tr>
          <td><code>10</code></td>
          <td>H</td>
          <td>~30 %</td>
      </tr>
  </tbody>
</table>
<h3 id="bch15-5-под-капотом">BCH(15, 5) под капотом</h3>
<p>Format info — это не просто 15 случайных бит. Это <strong>BCH-код (15, 5)</strong> над <code>GF(2)</code>: 5 содержательных бит (2 на EC level + 3 на номер маски) защищаются 10 битами чётности. Такой код <strong>исправляет до 3 ошибочных бит</strong> внутри своих 15 — то есть даже если три клетки в зоне format info замазаны или прокрашены неправильно, декодер всё равно вытянет верный уровень коррекции и маску.</p>
<p>Кодирование считается через <strong>порождающий полином</strong></p>
$$
G(x) = x^{10} + x^8 + x^5 + x^4 + x^2 + x + 1
$$<p>в двоичном виде — <code>10100110111</code>. Алгоритм такой:</p>
<ol>
<li>Берём 5 бит данных <code>d</code> = <code>[EC level (2 бита)] [mask (3 бита)]</code>.</li>
<li>Сдвигаем влево на 10 позиций: получаем <code>d · x^{10}</code>.</li>
<li>Делим в <code>GF(2)</code> (по сути — длинное XOR-вычитание) на <code>G(x)</code>, остаток — это 10 бит чётности.</li>
<li>Склеиваем: <code>[5 бит данных] [10 бит остатка]</code> = 15-битное кодовое слово.</li>
</ol>
<p>Чтобы проверить целостность при чтении, декодер делает то же самое в обратную сторону: делит прочитанные 15 бит на <code>G(x)</code>. Если остаток нулевой — ошибок не было. Если ненулевой — это <strong>синдром</strong>, по которому находятся испорченные биты. Для коротких BCH вроде нашего (всего 32 валидных слова, по числу комбинаций <code>EC × mask</code>) обычно держат готовую таблицу синдромов — это быстрее, чем гонять полный алгоритм исправления каждый раз.</p>
<p>Теперь становится понятно, <strong>зачем нужна XOR-маска</strong> <code>101010000010010</code>. Без неё формат из одних нулей был бы валидным кодовым словом («EC level M, маска 0, нулевой остаток») — а это совпадает с пустой или замазанной белой областью QR. После XOR-а сплошные нули или единицы гарантированно дают невалидный синдром, и декодер не примет шум за легитимный формат.</p>
<p>И ещё деталь: те же 15 бит <strong>продублированы дважды</strong>, причём копии разнесены по разным углам — буква Г вокруг левого верхнего finder-а и полоска снизу от правого верхнего + справа от левого нижнего. Это страховка от случая, когда одна копия повреждена сильнее, чем BCH способен починить (больше 3 ошибок): декодер читает обе, считает синдром у каждой и берёт ту, что чище.</p>
<hr>
<h2 id="шаг-3-зигзаг-и-снятие-маски">Шаг 3. Зигзаг и снятие маски</h2>
<p>Биты данных читаются <strong>парами столбцов справа налево, зигзагом</strong>: пара (20, 19) — снизу вверх, пара (18, 17) — сверху вниз, и так далее, перепрыгивая тайминг-колонку №6. Внутри каждого ряда читается сначала правая клетка, потом левая. Все функциональные модули (finder, тайминг, format, dark) — пропускаются.</p>
<figure class="post-figure">
    <img loading="lazy" decoding="async"
         src="/zigzag.png?v=1783493271"
         alt="Путь обхода данных: первые 32 бита подсвечены цветовой шкалой от красного к зелёному, серым — функциональные модули"></figure><p>Видно, как поток идёт парами столбцов: красный (биты 1–2) внизу справа, поднимается вверх по правым двум колонкам до битов 15–16, потом перепрыгивает в следующую пару (зелёный, биты 17–32) и идёт <strong>вниз</strong>.</p>
<p>Каждый бит, прочитанный из решётки, <strong>XOR-им с маской 6</strong>: если для координаты <code>(r, c)</code> маска срабатывает — бит инвертируется.</p>
<p>После маскинга первые 4 байта получаются такими:</p>
<div class="codeblock"><button class="codeblock__copy" type="button" data-copy aria-label="Скопировать" title="Скопировать"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button><pre tabindex="0"><code>байт 1: 00100000  = 0x20
байт 2: 00010011  = 0x13
байт 3: 00001111  = 0x0F
байт 4: 00000000  = 0x00</code></pre>
</div>
<h3 id="восемь-масок-и-их-формулы">Восемь масок и их формулы</h3>
<p>Полный набор из стандарта — клетка <code>(r, c)</code> (строка, колонка) инвертируется, если выражение даёт <code>true</code>:</p>
<table>
  <thead>
      <tr>
          <th>№</th>
          <th>формула</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>0</td>
          <td><code>(r + c) mod 2 == 0</code></td>
      </tr>
      <tr>
          <td>1</td>
          <td><code>r mod 2 == 0</code></td>
      </tr>
      <tr>
          <td>2</td>
          <td><code>c mod 3 == 0</code></td>
      </tr>
      <tr>
          <td>3</td>
          <td><code>(r + c) mod 3 == 0</code></td>
      </tr>
      <tr>
          <td>4</td>
          <td><code>(⌊r/2⌋ + ⌊c/3⌋) mod 2 == 0</code></td>
      </tr>
      <tr>
          <td>5</td>
          <td><code>(r · c) mod 2 + (r · c) mod 3 == 0</code></td>
      </tr>
      <tr>
          <td>6</td>
          <td><code>((r · c) mod 2 + (r · c) mod 3) mod 2 == 0</code></td>
      </tr>
      <tr>
          <td>7</td>
          <td><code>((r + c) mod 2 + (r · c) mod 3) mod 2 == 0</code></td>
      </tr>
  </tbody>
</table>
<p>Маски устроены по-разному осмысленно: №0–№3 — простые «шахматные» / «полосатые» шаблоны, №4–№7 — более «шумные», с произведениями координат. Чем разнообразнее набор, тем больше шанс, что хотя бы одна из восьми разломает любой неудачный битовый рисунок в payload.</p>
<p>А выбирает кодировщик так: накладывает поочерёдно каждую из восьми масок на черновой код и считает <strong>штрафную функцию</strong> (penalty score). Штрафы накапливаются за длинные одноцветные полосы (5+ модулей подряд), за блоки 2×2 одного цвета, за паттерны, похожие на finder (<code>1:1:3:1:1</code>), и за дисбаланс чёрного и белого. Маска с минимальной суммой штрафов уходит в финальный QR. Поэтому маска №6 в нашем подопытном — не «любимая маска автора», а просто та, что для конкретного payload <code>&quot;HI&quot;</code> сложилась с минимальным penalty.</p>
<hr>
<h2 id="шаг-4-парсим-payload">Шаг 4. Парсим payload</h2>
<p>Первые 32 бита склеиваем в один поток и режем по логике формата:</p>
<div class="codeblock"><button class="codeblock__copy" type="button" data-copy aria-label="Скопировать" title="Скопировать"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button><pre tabindex="0"><code>0010 | 000000010 | 01100001111 | 0000
 ↑         ↑            ↑         ↑
 │         │            │         └─ терминатор «конец данных»
 │         │            └─ символы (11 бит на пару)
 │         └─ счётчик: 2 символа (9 бит для V1 alpha)
 └─ режим: 0010 = alphanumeric</code></pre>
</div>
<p>Каждый payload в QR начинается одинаково: <strong>Mode Indicator</strong> (4 бита) + <strong>Character Count Indicator</strong> (CCI, ширина зависит от пары version+mode) + сами данные. Ширина CCI меняется ступеньками: для alphanumeric это 9 бит на V1–V9, 11 бит на V10–V26 и 13 бит на V27–V40. Сделано осмысленно: в маленьком V1 пол-байта не хочется тратить на нули перед длиной, а в большом V40 9 бит уже банально не хватит — туда влезает до 4296 alphanumeric-символов. Поэтому при ручном декодировании всегда первым делом смотришь на версию (размер сетки), и только потом — где у CCI заканчиваются биты.</p>
<h3 id="декодируем-сами-символы">Декодируем сами символы</h3>
<p>Декодируем 11 бит данных: <code>01100001111</code> в десятичном = <strong>783</strong>.</p>
<p>В alphanumeric-режиме два символа упаковываются как <code>c1 × 45 + c2</code>. Делим: <code>783 = 17 × 45 + 18</code>. Таблица alphanumeric-алфавита: <code>0-9, A-Z, [space] $ % * + - . / :</code> — итого 45 значений, отсюда и множитель.</p>
<ul>
<li>17 → <strong>H</strong></li>
<li>18 → <strong>I</strong></li>
</ul>
<p>Получили <code>&quot;HI&quot;</code>.</p>
<p>Если бы строка была нечётной длины, последний символ кодировался бы отдельно — не 11, а 6 бит. Это полезно держать в голове: после CCI всегда сначала идут полные пары, а потом — возможно — «хвост» в 6 бит. Аналогично numeric-режим режется тройками по 10 бит, а одиночный/парный хвост — 4 и 7 бит соответственно. Стандарт педантично оптимизирует каждый бит: считает, что место в QR — это дорого.</p>
<h3 id="терминатор-padding-и-reed-solomon">Терминатор, padding и Reed-Solomon</h3>
<p>Сразу за данными идёт терминатор <code>0000</code> — четыре нуля, говорящие «всё, payload закончился». По стандарту терминатор можно укоротить или вовсе выкинуть, если данные ровно дотягиваются до конца блока — но обычно его пишут целиком, и декодер на него ориентируется.</p>
<p>Дальше биты добиваются нулями до ближайшей границы байта, и потом блок данных заполняется до своей ёмкости чередующимися <strong>padding-байтами</strong> <code>0xEC</code> (<code>11101100</code>) и <code>0x11</code> (<code>00010001</code>). Эти два конкретных значения зашиты в стандарте — выбраны они так, чтобы их битовый рисунок под любой из восьми масок ломал длинные одноцветные полосы и не складывался во что-то, похожее на finder-pattern (1:1:3:1:1). Поэтому если вытащил из кода строку «HI», а дальше пошло <code>EC 11 EC 11 EC 11 ...</code> — это не повреждение, это норма. И наоборот: если padding выглядит как-то иначе — где-то в зигзаге ошибся.</p>
<p>Для V1 с уровнем коррекции L общий размер блока — <strong>26 codeword&rsquo;ов</strong> (байт), из которых под данные отведено 19, а остальные 7 — это <strong>байты Reed-Solomon</strong>: код над полем GF(256), способный поднять до 3 искажённых байт на блок. Для нашего <code>&quot;HI&quot;</code> это значит: 4 уже прочитанных байта (<code>20 13 0F 00</code>) + 15 байт padding&rsquo;а (<code>EC 11 EC 11 ... EC</code>) + 7 байт RS = ровно 26, полная ёмкость V1-L.</p>
<p>Раскручивать Reed-Solomon руками — занятие на отдельный пост: нужно считать синдромы, через алгоритм Берлекэмпа-Месси искать полином-локатор ошибок, потом Chien-search&rsquo;ем — позиции, потом формулой Форни — значения, и всё это в арифметике GF(256). В декодере без ошибок RS-байты можно просто игнорировать — и в этом разборе мы именно так и поступим. Поднимется тема — вернёмся.</p>
<h3 id="режимы-данных">Режимы данных</h3>
<table>
  <thead>
      <tr>
          <th>код</th>
          <th>режим</th>
          <th>бит на символ</th>
          <th>счётчик в V1</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>0001</code></td>
          <td>numeric</td>
          <td>3.33 (10 бит на 3 цифры)</td>
          <td>10 бит</td>
      </tr>
      <tr>
          <td><code>0010</code></td>
          <td>alphanumeric</td>
          <td>5.5 (11 бит на 2 символа)</td>
          <td>9 бит</td>
      </tr>
      <tr>
          <td><code>0100</code></td>
          <td>byte</td>
          <td>8</td>
          <td>8 бит</td>
      </tr>
      <tr>
          <td><code>1000</code></td>
          <td>kanji</td>
          <td>13</td>
          <td>8 бит</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="тонкие-места-на-которых-легко-споткнуться">Тонкие места, на которых легко споткнуться</h2>
<p>Когда сидишь с распечатанным QR и разбираешь его руками, есть пара мест, где мозг гарантированно даст осечку. Перечислю те, что встречал чаще всего — и в собственных первых попытках, и в чужих разборах в чате.</p>
<ul>
<li><strong>Забыл пропустить тайминг-колонку №6 в зигзаге.</strong> Самый популярный баг: пары столбцов должны «перепрыгивать» эту колонку, а не читать её клетки как данные. Если payload пошёл бредом с первого же байта — почти наверняка дело именно тут.</li>
<li><strong>Снял маску не только с данных.</strong> Маска накладывается <strong>исключительно</strong> на data + EC, то есть на зелёную зону. Finder, separators, тайминг, format info, dark module — не трогаем. Если случайно проинвертировал маской finder-патерны, дальше развалится всё, включая саму ориентацию.</li>
<li><strong>Перепутал порядок битов внутри пары столбцов.</strong> В зигзаге в каждой строке сначала правая клетка, потом левая. Прочитал наоборот — payload идёт зеркально по 2 бита, терминатор находится где-то в середине, и парсинг падает.</li>
<li><strong>Забыл, что зигзаг bounce-ит.</strong> Пары столбцов чередуют направление: (20, 19) — снизу вверх, (18, 17) — сверху вниз, (16, 15) — снова вверх. Это не «всегда снизу вверх», это «змейка». На стыках пар легко проскочить инерцией.</li>
<li><strong>Принял <code>EC 11 EC 11 ...</code> за продолжение данных.</strong> После терминатора <code>0000</code> идёт padding до конца блока данных. Если в декодированном байт-потоке после реального payload пошли повторяющиеся <code>EC 11</code> — не пытайся их парсить как «следующее сообщение», это просто забивание блока до 19 байт (для V1-L).</li>
</ul>
<hr>
<h2 id="что-с-этим-делать-на-практике">Что с этим делать на практике</h2>
<p>Чтобы из теории получилось ощущение «руками потрогал», самый рабочий заход — такой:</p>
<ol>
<li><strong>Сгенерируй V1 QR с заранее известным содержимым.</strong> Удобнее всего — через <a href="https://www.nayuki.io/page/qr-code-generator-library" rel="noopener noreferrer" target="_blank">онлайн-демо Nayuki</a>
 или через мой <a href="https://github.com/jtprogru/wifi-qr" rel="noopener noreferrer" target="_blank">wifi-qr</a>
 (для коротких SSID он как раз выдаёт V1–V2). Возьми короткую alphanumeric-строку: <code>&quot;HI&quot;</code>, <code>&quot;OK&quot;</code>, <code>&quot;TEST&quot;</code>. Не забудь зафиксировать <strong>уровень коррекции</strong> (L) и <strong>номер маски</strong> — потом будет с чем сверять.</li>
<li><strong>Распечатай крупно</strong> — A4 на 21×21 хватает с запасом. Альтернатива — нарисовать сетку на бумаге в клетку и закрасить модули вручную. Звучит занудно, но именно ручная отрисовка лучше всего ломает «магический квадратик» в голове.</li>
<li><strong>Подсвети функциональные зоны</strong> карандашом или маркерами разных цветов: три finder-а, separators, обе тайминг-полоски, dark module, обе копии format info. После этого зелёная зона данных выделится сама собой.</li>
<li><strong>Прочитай format info</strong> → XOR с <code>101010000010010</code> → выпиши уровень коррекции и номер маски. Сверь с тем, что задал в генераторе. Сошлось — значит, Шаг 2 ты понял правильно.</li>
<li><strong>Обведи клетки, инвертируемые выбранной маской.</strong> Берёшь формулу из таблицы выше и проходишь по всей data-зоне: где условие — <code>true</code>, ставишь крестик. Эти клетки будешь инвертировать при чтении.</li>
<li><strong>Пройди зигзагом первые 32 бита</strong>, для каждого инвертируй или нет в зависимости от маски, и распарси: 4 бита mode → CCI → данные. Должна получиться твоя исходная строка.</li>
</ol>
<p>Когда «свой» QR разобрался — попробуй на чужом: возьми QR с любого чека из магазина или с Wi-Fi-стикера в кофейне. Только сразу проверь, что это <strong>V1 или V2</strong> (для V1 сетка 21×21, для V2 — 25×25, считается по краю). На больших версиях ручной зигзаг быстро превращается в подвиг ради подвига.</p>
<hr>
<h2 id="итог">Итог</h2>
<p>Если потренироваться, то для маленьких QR (V1, alphanumeric, короткий текст) реально читать глазами за пару минут. Узкое горлышко — держать в голове маску и зигзаг, две операции, которые мозг плохо параллелит. Помогает распечатать QR на бумаге и фломастером заштриховывать клетки, которые маска инвертирует — после этого данные читаются «как обычный бинарный поток».</p>
<h3 id="алгоритм-по-шагам">Алгоритм по шагам</h3>
<ol>
<li>Найти три finder patterns → определить ориентацию.</li>
<li>Прочитать format info → XOR с <code>101010000010010</code> → выделить EC level и mask number.</li>
<li>Применить маску к данным (XOR по формуле выбранной маски).</li>
<li>Прочитать биты зигзагом снизу-справа вверх, парами столбцов.</li>
<li>Распарсить: 4 бита режим → N бит счётчик → данные → терминатор.</li>
<li>(Опционально) проверить Reed-Solomon коды.</li>
</ol>
<h3 id="дальше-копать">Дальше копать</h3>
<ul>
<li><a href="https://robertheaton.com/2018/05/03/decoding-a-qr-code-by-hand/" rel="noopener noreferrer" target="_blank">How to decode a QR code by hand — Robert Heaton</a>
 — пошаговый разбор того же V1 «HI», только не моими словами. Хорошо для проверки себя: если в каком-то месте разошлись — значит, не до конца понял шаг.</li>
<li><a href="https://www.thonky.com/qr-code-tutorial/" rel="noopener noreferrer" target="_blank">Thonky&rsquo;s QR Code Tutorial</a>
 — самый полный учебник в сети: все 40 версий, восемь масок с примерами, готовые таблицы для Reed-Solomon, разбор форматов. Если Heaton — обзорная статья, Thonky тянет уже на 30-страничный курс.</li>
<li><a href="https://github.com/nayuki/QR-Code-generator" rel="noopener noreferrer" target="_blank">nayuki/QR-Code-generator</a>
 — каноническая референсная реализация на C/C++/Java/JS/Python/Rust. Читается как продолжение этого поста: чёткие имена, в комментариях — формулы из стандарта, никакой магии. У того же автора на <code>nayuki.io</code> лежит онлайн-демо с настраиваемой версией и маской — удобно сверять свои выкладки с эталоном.</li>
<li><a href="https://github.com/jtprogru/wifi-qr" rel="noopener noreferrer" target="_blank">jtprogru/wifi-qr</a>
 — мой собственный мини-проектик «с обратной стороны»: тащит <code>WIFI_SSID</code> и <code>WIFI_PASSWD</code> из <code>.env</code> и собирает Wi-Fi-QR в PNG одной командой <code>make run</code>. Внутри — крошечный Python-скрипт поверх библиотеки <code>qrcode</code>. Удобный мостик от «понимаю по битам» к «генерирую за секунду», заодно — готовый QR для гостевой Wi-Fi.</li>
<li><a href="https://github.com/zxing/zxing" rel="noopener noreferrer" target="_blank">zxing/zxing</a>
 — production-grade декодер от Google, тот самый, который много лет крутился в Barcode Scanner на Android. Полезно посмотреть, чтобы понять разницу между «вытащить V1 в идеальных условиях» и «прочитать URL с мятого чека под углом 30° при тусклом свете».</li>
<li><a href="https://en.wikiversity.org/wiki/Reed-Solomon_codes_for_coders" rel="noopener noreferrer" target="_blank">Reed–Solomon codes for coders</a>
 на Wikiversity — лучший learn-by-doing разбор RS-кодов из всех, что попадались. GF(256), порождающие полиномы, синдромы, исправление ошибок — всё последовательно разложено по шагам, с примерами на Python. Без этой статьи в RS-кодах было сложно ухватиться хоть за что-то.</li>
<li><a href="https://en.wikipedia.org/wiki/QR_code" rel="noopener noreferrer" target="_blank">QR code — Wikipedia</a>
 — на удивление приличная обзорная статья: версии, режимы, история Denso Wave, лимиты по объёму данных, эволюция стандарта. Хорошо стартовать с неё, если QR в голове пока «магический квадратик».</li>
<li><strong>ISO/IEC 18004:2015</strong> — сам стандарт. Платный, но если возишься со штрихкодами всерьёз — без него никак: только там нормально расписаны все 40 версий, все 4 режима кодирования и точные алгоритмы коррекции.</li>
</ul>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></content:encoded>
    </item><item>
      <title>SLO как чертёж архитектуры</title>
      <link>https://jtprog.ru/posts/slo-as-architecture-blueprint/</link>
      <pubDate>Sun, 10 May 2026 20:57:37 +0300</pubDate>
      <dc:creator>jtprogru</dc:creator>
      <guid isPermaLink="true">https://jtprog.ru/posts/slo-as-architecture-blueprint/</guid>
      <category>SRE</category>
      <category>SLO</category>
      <category>SLI</category>
      <category>System Design</category>
      <category>Error Budget</category>
      <category>Архитектура</category>
      <category domain="category">SRE</category>
      <enclosure url="https://jtprog.ru/devops.png" type="image/jpeg" length="0" />
      <media:thumbnail url="https://jtprog.ru/devops.png" /><description><![CDATA[<div><p>Привет, <code>%username%</code>! На системном дизайне 9 из 10 кандидатов начинают с компонентов: API gateway, Kafka, Redis, Postgres-реплики, шардинг, CDN. Это не дизайн — это плакат с логотипами. Дизайн начинается с вопроса, на который почти никто не отвечает первым: «какой надёжности я обещаю и почему именно этой, а не другой?».</p>
<p>Без числа в этом ответе — <code>99.5</code>, <code>99.9</code>, <code>99.99</code> — все архитектурные решения ниже становятся вопросом эстетики. С числом — превращаются в инженерные ограничения, которые решают за тебя, нужна ли вторая БД-реплика, имеет ли смысл repair-aware кэш и сколько регионов держать в active-active.</p>
<p>В этой статье я беру одну каноничную задачу с собеса — <strong>поиск каталога маркетплейса</strong> — и прокручиваю её сквозь три уровня SLO: <code>99.0%</code>, <code>99.9%</code>, <code>99.99%</code>. На каждом уровне меняется не «настройка пары флагов», а сама архитектура. Главный тезис: SLI/SLO — это не SRE-декорация поверх готовой системы, а <strong>интерфейс между System Design и бизнесом</strong>. Тот самый, через который аналитик, бэкенд и SRE говорят на одном языке.</p>
<h2 id="что-ты-унесёшь-из-статьи">Что ты унесёшь из статьи</h2>
<p>Статья длинная (~55 000 знаков), поэтому сразу — что заберёт каждая ЦА:</p>
<ul>
<li><strong>Аналитик / продакт.</strong> Рамка для перевода бизнес-метрик в SLI и для разговора с инженерами в стиле «а если снизим SLO с 99.99% до 99.9% — что освободится?».</li>
<li><strong>Бэкенд-инженер.</strong> Как один и тот же поиск каталога превращается в три разные системы при смене таргета SLO — read path, кэш, индекс, failover.</li>
<li><strong>SRE / DevOps.</strong> Error budget как валюта в спорах «фича vs рефакторинг» + типовые ошибки выбора SLI: что делать, когда дашборд зелёный, а пользователи — в саппорте.</li>
</ul>
<p>Общий блок для всех: разница между <strong>Observability</strong>, <strong>Monitoring</strong> и <strong>Alerting</strong> — в одной схеме.</p>
<h2 id="tldr-если-читать-дальше-уже-некогда">TL;DR (если читать дальше уже некогда)</h2>
<p>Если у тебя нет 30 минут на длинный разбор — четыре тезиса, к которым приходит статья:</p>
<ol>
<li><strong>SLO выбирается до архитектуры, а не после.</strong> Поднять SLO задним числом — это переписать систему, а не «добавить мониторинга». Снизить — освободить бюджет, но не вернуть деньги.</li>
<li><strong>Один и тот же кейс на трёх SLO (<code>99.0%</code> / <code>99.9%</code> / <code>99.99%</code>) — это три разные системы.</strong> Меняется не «настройка флагов», а топология, технологии, capacity, RTO/RPO, операционная модель и стоимость (<code>1×</code> → <code>4–6×</code> → <code>15–25×</code> baseline).</li>
<li><strong>SLI вешаются на шаги критичного пользовательского пути (CUJ), а не «на сервис в целом».</strong> «99.9% по системе» — это псевдо-метрика, которая прячет деградацию ключевого шага за здоровьем фоновых эндпоинтов.</li>
<li><strong>Error budget работает как валюта в спорах «фича vs рефакторинг», только если есть записанная error budget policy.</strong> Без неё SLO — это график на дашборде, а не дисциплина.</li>
</ol>
<p>Дальше — как до этих четырёх тезисов прийти через один сквозной кейс. Если интересует только инженерная кульминация — переходи сразу к разделу <a href="#%d0%be%d0%b4%d0%b8%d0%bd-%d0%ba%d0%b5%d0%b9%d1%81--%d1%82%d1%80%d0%b8-slo--%d1%82%d1%80%d0%b8-%d0%b0%d1%80%d1%85%d0%b8%d1%82%d0%b5%d0%ba%d1%82%d1%83%d1%80%d1%8b">Один кейс — три SLO — три архитектуры</a>
.</p>
<h2 id="кейс-поиск-каталога-маркетплейса">Кейс: поиск каталога маркетплейса</h2>
<p>Чтобы не разговаривать абстракциями, возьмём одну сквозную задачу. Формулирую как на собеседовании:</p>
<blockquote><p>Спроектируйте сервис поиска и выдачи карточек товаров для крупного маркетплейса. На вход — поисковый запрос пользователя и фильтры (категория, цена, доставка, регион). На выход — отранжированный список карточек с превью, пагинация, фасеты.</p>
</blockquote><p>Параметры — реалистичные для маркетплейса масштаба Ozon / Wildberries / Avito, но «приглаженные» под удобство арифметики:</p>
<table>
  <thead>
      <tr>
          <th>Характеристика</th>
          <th>Значение</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Активный каталог</td>
          <td>~50M товаров</td>
      </tr>
      <tr>
          <td>Пиковый RPS на поиск</td>
          <td>~30 000 запросов/сек</td>
      </tr>
      <tr>
          <td>Активных одновременных пользователей</td>
          <td>~200 000</td>
      </tr>
      <tr>
          <td>Доля mobile-трафика</td>
          <td>~70%</td>
      </tr>
      <tr>
          <td>География</td>
          <td>5 регионов, основной — central RU</td>
      </tr>
      <tr>
          <td>Целевая P50 латентность read path</td>
          <td>&lt; 150 ms</td>
      </tr>
      <tr>
          <td>Целевая P99 латентность read path</td>
          <td>&lt; 500 ms</td>
      </tr>
      <tr>
          <td>Сезонные пики (BF, распродажи)</td>
          <td>x3–x5 от обычного RPS</td>
      </tr>
  </tbody>
</table>
<p>Бизнес-контекст, про который часто забывают на собесе, и зря:</p>
<ul>
<li><strong>Поиск — главный драйвер конверсии.</strong> По публичным отчётам (SimilarWeb, ContentSquare, материалы крупных маркетплейсов) на больших площадках 40–70% покупок начинается с поисковой строки, не с категорий или баннеров. Конкретный процент гуляет по сегментам и площадкам, но порядок одинаков. Любая деградация поиска — это прямая просадка GMV, не «инженерная неприятность».</li>
<li><strong>Эластичность по latency измерима.</strong> Цифры из публикаций Amazon (Greg Linden, 2006), Akamai (2017), Google/SOASTA (2017) и Deloitte (2020) разнятся по методологии и сегменту, но порядок сходится: каждые <code>+100 ms</code> latency на ключевом read path стоят примерно <code>−0.5…1.5%</code> конверсии. Для маркетплейса с GMV $10M в день это $50–150k недополученной выручки <strong>в день</strong>, если регресс закрепится. Это не разовый ущерб, а просадка, в которую конвертируется latency на ключевом read path.</li>
<li><strong>Стоимость недоступности нелинейна.</strong> 5 минут даунтайма обычным вторником и 5 минут даунтайма в Чёрную пятницу — это разные деньги в десятки раз. SLO должно учитывать сезонность, иначе оно меряет не то.</li>
</ul>
<p>Эти три факта — ровно то, что превращает SLI/SLO из «инженерной гигиены» в инструмент бизнес-разговора. Я буду к ним возвращаться в каждом следующем разделе.</p>
<h2 id="что-обычно-ломается-на-собесе-без-slo">Что обычно ломается на собесе без SLO</h2>
<p>Послушаешь сотню system-design интервью — и складывается узнаваемый паттерн ответа.</p>
<h3 id="типичная-траектория">Типичная траектория</h3>
<ol>
<li><strong>Уточнили требования.</strong> «Сколько пользователей? Какая нагрузка?» — кандидат услышал «много», и в голове щёлкнуло «значит, надо много всего».</li>
<li><strong>Нарисовали API.</strong> REST с парой эндпоинтов, gateway, auth-middleware. Пока без сюрпризов.</li>
<li><strong>Добавили слой данных.</strong> Postgres / MySQL — «реляционка для каталога норм». Кто-то сразу предложит Elasticsearch, потому что слышал про full-text search.</li>
<li><strong>Поставили кэш.</strong> Redis — потому что «Redis fast». Без обсуждения, что именно кэшируем, какой hit rate ожидаем, как инвалидируем при изменении цены или остатков.</li>
<li><strong>Подняли реплики.</strong> «На чтение пойдут реплики, на запись — мастер». Без обсуждения, насколько асинхронная репликация критична: а если пользователь не увидит свой только что выложенный товар?</li>
<li><strong>Зашардировали.</strong> Чаще всего по <code>category_id</code> или <code>seller_id</code>. Потому что «у больших так».</li>
<li><strong>Накинули CDN и очередь.</strong> Kafka — куда же без неё. Async-обработка событий, чтобы «развязать сервисы».</li>
</ol>
<p>К концу интервью на доске — красивая распределённая система. Интервьюер кивает. Кандидат уверен, что справился.</p>
<h3 id="что-в-этой-траектории-не-так">Что в этой траектории не так</h3>
<p>Простой тест. Ответь сам себе: <strong>какое из решений выше изменилось бы, если бы требование к доступности было <code>99.0%</code>, а не <code>99.99%</code>?</strong> А если бы P99 была не 500 ms, а 2 секунды?</p>
<p>Если ответ «никакое» — значит, дизайн не привязан к требованиям к надёжности. Кандидат строил систему «как принято», а не «как нужно бизнесу». А раз все решения принимались независимо от целевого SLO — значит, любые из них могут быть и преждевременными, и недостаточными одновременно. Точно сказать нельзя, потому что точки отсчёта нет.</p>
<p>Чтобы было совсем больно — разберём по решениям:</p>
<ul>
<li><strong>Кэш Redis.</strong> Имеет смысл, если твой SLO по latency — десятки миллисекунд для горячих запросов или ты упираешься в нагрузку на БД при текущем availability-таргете. При расслабленном SLO P99 = 2 секунды кэш в read path — преждевременная оптимизация: ты поднимаешь эксплуатационную сложность (инвалидация, прогрев, репликация Redis-кластера, отдельный SLO на сам кэш) ради цели, которая выполнима и без него.</li>
<li><strong>Реплики на чтение.</strong> Имеют смысл, если твой SLO availability такой, что мастер-only архитектура не уложится в бюджет ошибок при типовом MTTR. На SLO <code>99.0%</code> (~7 часов даунтайма в месяц) одного хорошо настроенного primary с мониторингом и быстрым backup-восстановлением часто достаточно.</li>
<li><strong>Шардинг.</strong> Оправдан, когда объём данных или write QPS упирается в один инстанс физически. До этого — это удвоение операционной нагрузки (rebalancing, hot shards, резолв cross-shard запросов) без выигрыша по SLI, ради которого его делают.</li>
<li><strong>Multi-region active-active.</strong> Имеет смысл при SLO availability <code>99.99%</code>+ или когда регуляторика обязывает (data residency, ФЗ-149/ФЗ-152/ФЗ-242/GDPR-аналоги). На <code>99.9%</code> обычно дешевле и предсказуемее active-passive с автоматическим failover и RTO в минутах.</li>
</ul>
<p>Каждое из этих решений — правильное в одних условиях и преждевременное в других. Условия задаёт SLO. Без него ты выбираешь архитектуру не под задачу, а под насмотренность.</p>
<h3 id="главный-сдвиг--направление-дизайна">Главный сдвиг — направление дизайна</h3>
<p>Хороший дизайн идёт <strong>сверху вниз</strong>: бизнес-цель → критичный пользовательский путь (CUJ, critical user journey) → SLI на каждый шаг этого пути → SLO как контракт → архитектура, которая в этот SLO укладывается с разумным запасом.</p>
<p>Плохой дизайн идёт <strong>снизу вверх</strong>: «у крутых ребят такая схема — нарисуем такую же». На выходе получается архитектура, в которую любой SLO «впихнуть можно постфактум» — потому что под её требования не задавали ни одного числа, и теперь любая цифра одинаково годится для отчётности и одинаково плохо отражает реальное поведение системы.</p>
<p>В следующих разделах я разворачиваю верхний путь — сверху вниз — на нашем кейсе с маркетплейсом. Начнём с шага 1: как из функциональных требований получается тот самый критичный пользовательский путь.</p>
<h2 id="шаг-1-от-фт-к-критичному-пользовательскому-пути">Шаг 1: от ФТ к критичному пользовательскому пути</h2>
<p>Раз направление дизайна сверху вниз — нужна точка отсчёта на самом верху. Это <strong>функциональные требования (ФТ)</strong>: что система делает в терминах пользователя и продукта. Не «использует Elasticsearch», а «возвращает релевантную выдачу по запросу».</p>
<h3 id="фт-для-нашего-кейса">ФТ для нашего кейса</h3>
<ul>
<li>Принять поисковый запрос (текст + фильтры) от авторизованного и анонимного пользователя.</li>
<li>Подбирать товары из активного каталога с учётом региона и доступной доставки.</li>
<li>Ранжировать результаты с учётом релевантности, цены, рейтинга продавца и персонализации.</li>
<li>Возвращать пагинированную выдачу с фасетами (категории, ценовые диапазоны, бренды).</li>
<li>Поддерживать sorting (price asc/desc, popularity, rating).</li>
<li>Подсказки и автодополнение по мере набора запроса.</li>
</ul>
<p>Это всё одинаково «функциональные требования» — но <strong>не одинаково критичные</strong>. Если автодополнение тормозит на 200 ms, пользователь поморщится. Если выдача не приходит вовсе — он закроет вкладку и пойдёт к конкуренту. ФТ сами по себе плоские, в них нет приоритета. Этот приоритет приносит <strong>критичный пользовательский путь</strong>.</p>
<h3 id="критичный-пользовательский-путь-cuj--critical-user-journey">Критичный пользовательский путь (CUJ — critical user journey)</h3>
<p>Это сценарий пользователя, который напрямую кормит ключевую бизнес-метрику. У маркетплейса бизнес-метрика — GMV, точка входа в неё — поиск, точка выхода — клик в карточку и далее в корзину. Получаем такой путь:</p>
<blockquote><p>Пользователь приходит на сайт с намерением купить → формулирует запрос → получает релевантную выдачу → выбирает товар → переходит в карточку.</p>
</blockquote><p>Это и есть «золотой путь», за который держимся в дизайне. Всё, что не обслуживает этот путь напрямую (статистика для аналитики, A/B-эксперименты, персональные рекомендации в стороннем виджете), может быть менее надёжным — и это нормально.</p>
<aside class="callout callout--note" role="note">
  <div class="callout__icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg></div>
  <div class="callout__body"><p class="callout__title">Терминологическая дисциплина</p>
    <div class="callout__content"><p>Дальше по тексту слово <strong>«сервис»</strong> работает в двух разных значениях, и я их буду стараться разводить явно:</p>
<ul>
<li><strong>Пользовательский сервис</strong> — это CUJ (поиск каталога целиком). К нему привязаны SLI и SLO.</li>
<li><strong>Микросервис</strong> — это юнит деплоя (Search Service, Ranking Service на схеме архитектуры). К нему привязаны Golden Signals для внутренней диагностики, но <strong>не отдельный набор SLI</strong>.</li>
</ul>
<p>Один пользовательский сервис может реализовываться десятью микросервисами — но SLI по-прежнему 4–8, не 4–8 × 10. К этому различию ещё вернёмся в разделе про типичные ошибки.</p></div>
  </div>
</aside><h3 id="декомпозиция-пути-на-шаги">Декомпозиция пути на шаги</h3>
<p>Дальше путь режется на дискретные шаги, каждый из которых станет отдельной точкой измерения:</p>
<table>
  <thead>
      <tr>
          <th>#</th>
          <th>Шаг</th>
          <th>Что делает система</th>
          <th>Что замечает пользователь</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1</td>
          <td>Загрузка поискового интерфейса</td>
          <td>Отдать HTML/SPA-bundle, инициализировать клиент</td>
          <td>Страница появилась, поле поиска кликабельно</td>
      </tr>
      <tr>
          <td>2</td>
          <td>Автодополнение (suggest)</td>
          <td>На каждое нажатие клавиши вернуть top-N подсказок</td>
          <td>Подсказки появляются «без задержки»</td>
      </tr>
      <tr>
          <td>3</td>
          <td>Отправка запроса</td>
          <td>Получить query + фильтры, направить в search backend</td>
          <td>Лоадер крутится недолго</td>
      </tr>
      <tr>
          <td>4</td>
          <td>Получение выдачи</td>
          <td>Поиск в индексе, ранжирование, обогащение карточек</td>
          <td>Выдача отрисовалась, скроллится плавно</td>
      </tr>
      <tr>
          <td>5</td>
          <td>Применение фильтра / сортировки</td>
          <td>Реквест с уточнёнными параметрами</td>
          <td>Список перестроился без рывков</td>
      </tr>
      <tr>
          <td>6</td>
          <td>Клик в карточку</td>
          <td>Переход на страницу товара, прелоад данных</td>
          <td>Карточка открылась, цена и наличие актуальны</td>
      </tr>
  </tbody>
</table>
<p>Эти шесть шагов — каркас, на котором будет висеть всё дальнейшее. На каждый шаг повесим SLI, на каждый SLI — SLO. И увидим, что они <strong>не равноценны</strong>: шаг 4 (получение выдачи) для бизнеса принципиально важнее, чем шаг 2 (автодополнение). А значит, и инженерных усилий на их надёжность нужно несоизмеримо больше.</p>
<h3 id="почему-это-важно-ловушка-среднего-по-системе">Почему это важно: ловушка «среднего по системе»</h3>
<p>На многих собеседованиях кандидат, отвечая на «какую ты доступность хочешь», говорит «99.9% по системе». Это бесполезное число: если оно посчитано как «суммарный аптайм всех эндпоинтов», оно скрывает то, что выдача упала на 30 минут, а суммарно «вышло 99.9%, потому что autocomplete и health-чеки крутились». Пользователь страдал, дашборд зелёный.</p>
<p>Шаги критичного пути — антидот этой ловушки. Каждый шаг получает свою цифру, и провал шага 4 невозможно «размазать» доступностью соседних шагов.</p>
<h2 id="шаг-2-нфт-как-свойства-шагов-а-не-системы">Шаг 2: НФТ как свойства шагов, а не системы</h2>
<p>Когда есть карта шагов, нефункциональные требования (НФТ) перестают быть размытым «надёжно, быстро, безопасно». Они становятся набором конкретных свойств <strong>каждого шага</strong>.</p>
<h3 id="свойства-которые-нас-интересуют">Свойства, которые нас интересуют</h3>
<p>Для read-heavy критичного пути маркетплейса базовый набор НФТ выглядит так:</p>
<ul>
<li><strong>Латентность.</strong> Сколько миллисекунд занял шаг. Меряем перцентилями (P50/P95/P99), не средним — оно скрывает хвосты, а хвосты и есть пользовательская боль.</li>
<li><strong>Доступность.</strong> Доля успешных шагов. Не «200/всего HTTP», а именно «шаг выполнен корректно с точки зрения сценария».</li>
<li><strong>Корректность.</strong> Получил ли пользователь ожидаемый результат. Для шага 4 — вернулась ли релевантная выдача или 0 результатов из-за бага в ранжировании.</li>
<li><strong>Свежесть.</strong> Насколько актуальны данные. Цена и наличие на карточке после клика — критичная свежесть; popularity-score в ранжировании — терпит часовую задержку.</li>
<li><strong>Целостность.</strong> Не «исчезает» ли часть результатов из-за частичного сбоя ноды или таймаута к шарду. Это специфично для распределённого поиска и шардированных индексов.</li>
</ul>
<h3 id="привязка-свойств-к-шагам-пути">Привязка свойств к шагам пути</h3>
<p>Не каждое свойство одинаково важно на каждом шаге. Покажу таблицей, какие НФТ для каких шагов нашего кейса критичны:</p>
<table>
  <thead>
      <tr>
          <th>Шаг</th>
          <th>Латентность</th>
          <th>Доступность</th>
          <th>Корректность</th>
          <th>Свежесть</th>
          <th>Целостность</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1. Загрузка интерфейса</td>
          <td>средне</td>
          <td>высоко</td>
          <td>низко</td>
          <td>низко</td>
          <td>низко</td>
      </tr>
      <tr>
          <td>2. Autocomplete</td>
          <td>высоко</td>
          <td>средне</td>
          <td>средне</td>
          <td>низко</td>
          <td>низко</td>
      </tr>
      <tr>
          <td>3. Отправка запроса</td>
          <td>средне</td>
          <td>высоко</td>
          <td>низко</td>
          <td>низко</td>
          <td>низко</td>
      </tr>
      <tr>
          <td>4. Получение выдачи</td>
          <td><strong>высоко</strong></td>
          <td><strong>высоко</strong></td>
          <td><strong>высоко</strong></td>
          <td>средне</td>
          <td><strong>высоко</strong></td>
      </tr>
      <tr>
          <td>5. Фильтр / сортировка</td>
          <td>высоко</td>
          <td>высоко</td>
          <td>высоко</td>
          <td>средне</td>
          <td>высоко</td>
      </tr>
      <tr>
          <td>6. Клик в карточку</td>
          <td>средне</td>
          <td>высоко</td>
          <td>высоко</td>
          <td><strong>высоко</strong></td>
          <td>низко</td>
      </tr>
  </tbody>
</table>
<p>Сразу видно: шаг 4 — концентратор НФТ, на нём горят почти все колонки. Шаг 6 особенно требователен к свежести — потому что показать пользователю карточку с «вчерашней» ценой (а на чекауте уже другая) — это худший UX и часто прямой ущерб бизнесу через возвраты и репутацию.</p>
<h3 id="главное-смещение-от-привычных-нфт-из-тз">Главное смещение от привычных НФТ из ТЗ</h3>
<p>Классические нефункциональные требования — «система должна обеспечивать 99.9% доступности» — это <strong>средневзвешенное по чему попало</strong>. Они одинаково оценивают и autocomplete, и финальную выдачу. В реальной эксплуатации это приводит к двум симметричным болям:</p>
<ol>
<li><strong>Деньги тратятся не туда.</strong> Команда вкладывает усилия в надёжность шагов, которые этого не требуют (autocomplete с 99.99% — приятно, но конверсию не трогает), а критичные шаги остаются на «общем уровне».</li>
<li><strong>Алерты молчат, когда болит.</strong> Дашборд показывает зелёный «99.9% по системе», пока шаг 4 деградирует и теряет каждую десятую выдачу. Эту потерю топит «здоровье» десятка других эндпоинтов и фоновых хелсчеков.</li>
</ol>
<p>НФТ-по-шагам убирают эту усреднённость. Следующий шаг сверху вниз — превращаем эти свойства в <strong>измеримые SLI</strong>, чтобы было что мерить и за что отчитываться. Но прежде чем давать формулу — нужен общий словарь, без него разговор про SLI получится поверхностным.</p>
<h2 id="шаг-3-sli-как-индикатор-пользовательского-опыта">Шаг 3: SLI как индикатор пользовательского опыта</h2>
<h3 id="сначала--общий-словарь-observability--monitoring--alerting">Сначала — общий словарь: Observability ≠ Monitoring ≠ Alerting</h3>
<p>В SRE-практике три термина часто валят в одну кучу, и тогда любой разговор про SLI разваливается на терминологические уточнения. Развожу их через <strong>цель</strong> каждой практики:</p>
<ul>
<li><strong>Monitoring (мониторинг)</strong> отвечает на заранее заданные вопросы. Ты знаешь, что хочешь видеть: «жив ли primary», «какая P99 у эндпоинта <code>/search</code>», «не растёт ли latency». На каждую заготовку — метрика или дашборд. Это про <strong>known unknowns</strong> — вещи, о которых ты знаешь, что они могут пойти не так, и хочешь их видеть.</li>
<li><strong>Observability (наблюдаемость)</strong> — свойство системы, которое позволяет дойти до <strong>нового</strong> вопроса. Не «жив ли primary», а «почему именно в этом конкретном запросе latency 4 секунды». Высокая observability означает, что у тебя достаточно данных (метрик, структурированных логов, трейсов с tail-based sampling, событий) и инструментов поверх них, чтобы задать системе вопрос, который ты не предусмотрел заранее. Это про <strong>unknown unknowns</strong> — про неожиданности, которых ты не ждал. Такое разведение «monitoring = known unknowns / observability = unknown unknowns» — рамка из «Distributed Systems Observability» Cindy Sridharan (O&rsquo;Reilly, 2018) и развитая инженерами Honeycomb (Charity Majors et al.); внутри Google SRE Workbook грань между ними размытее, и я сознательно беру более жёсткую формулировку — на ней легче строить дизайн.</li>
<li><strong>Alerting (алертинг)</strong> — действие по событию. Это слой, надстроенный над мониторингом и observability: правила, которые превращают наблюдаемое состояние в инцидент с пейджингом. Алерт — это не метрика, это <strong>обещание разбудить человека</strong>, и за него надо отвечать. Alert fatigue — отдельная боль, и лечится она burn-rate-алертами, а не увеличением количества правил.</li>
</ul>
<p>Связь между ними — на одной схеме:</p>
<figure class="mermaid mermaid--prerendered" aria-label="Mermaid diagram">
<div class="mermaid-svg mermaid-svg--light">
<svg id="m-02e1152b1ac5-light" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 1109.69px; background-color: transparent;" viewBox="0 0 1109.6875 390.375" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#m-02e1152b1ac5-light{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;fill:#1c1c1f;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#m-02e1152b1ac5-light .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#m-02e1152b1ac5-light .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#m-02e1152b1ac5-light .error-icon{fill:#fee2e2;}#m-02e1152b1ac5-light .error-text{fill:#7f1d1d;stroke:#7f1d1d;}#m-02e1152b1ac5-light .edge-thickness-normal{stroke-width:1px;}#m-02e1152b1ac5-light .edge-thickness-thick{stroke-width:3.5px;}#m-02e1152b1ac5-light .edge-pattern-solid{stroke-dasharray:0;}#m-02e1152b1ac5-light .edge-thickness-invisible{stroke-width:0;fill:none;}#m-02e1152b1ac5-light .edge-pattern-dashed{stroke-dasharray:3;}#m-02e1152b1ac5-light .edge-pattern-dotted{stroke-dasharray:2;}#m-02e1152b1ac5-light .marker{fill:#5b5b62;stroke:#5b5b62;}#m-02e1152b1ac5-light .marker.cross{stroke:#5b5b62;}#m-02e1152b1ac5-light svg{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;}#m-02e1152b1ac5-light p{margin:0;}#m-02e1152b1ac5-light .label{font-family:Inter,system-ui,-apple-system,sans-serif;color:#1c1c1f;}#m-02e1152b1ac5-light .cluster-label text{fill:#1c1c1f;}#m-02e1152b1ac5-light .cluster-label span{color:#1c1c1f;}#m-02e1152b1ac5-light .cluster-label span p{background-color:transparent;}#m-02e1152b1ac5-light .label text,#m-02e1152b1ac5-light span{fill:#1c1c1f;color:#1c1c1f;}#m-02e1152b1ac5-light .node rect,#m-02e1152b1ac5-light .node circle,#m-02e1152b1ac5-light .node ellipse,#m-02e1152b1ac5-light .node polygon,#m-02e1152b1ac5-light .node path{fill:#ffffff;stroke:#c8c5bb;stroke-width:1px;}#m-02e1152b1ac5-light .rough-node .label text,#m-02e1152b1ac5-light .node .label text,#m-02e1152b1ac5-light .image-shape .label,#m-02e1152b1ac5-light .icon-shape .label{text-anchor:middle;}#m-02e1152b1ac5-light .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#m-02e1152b1ac5-light .rough-node .label,#m-02e1152b1ac5-light .node .label,#m-02e1152b1ac5-light .image-shape .label,#m-02e1152b1ac5-light .icon-shape .label{text-align:center;}#m-02e1152b1ac5-light .node.clickable{cursor:pointer;}#m-02e1152b1ac5-light .root .anchor path{fill:#5b5b62!important;stroke-width:0;stroke:#5b5b62;}#m-02e1152b1ac5-light .arrowheadPath{fill:rgba(255, 255, 255, 0);}#m-02e1152b1ac5-light .edgePath .path{stroke:#5b5b62;stroke-width:1px;}#m-02e1152b1ac5-light .flowchart-link{stroke:#5b5b62;fill:none;}#m-02e1152b1ac5-light .edgeLabel{background-color:#fafaf7;text-align:center;}#m-02e1152b1ac5-light .edgeLabel p{background-color:#fafaf7;}#m-02e1152b1ac5-light .edgeLabel rect{opacity:0.5;background-color:#fafaf7;fill:#fafaf7;}#m-02e1152b1ac5-light .labelBkg{background-color:rgba(250, 250, 247, 0.5);}#m-02e1152b1ac5-light .cluster rect{fill:#f3f1ed;stroke:#c8c5bb;stroke-width:1px;}#m-02e1152b1ac5-light .cluster text{fill:#1c1c1f;}#m-02e1152b1ac5-light .cluster span{color:#1c1c1f;}#m-02e1152b1ac5-light div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:12px;background:#fed7aa;border:1px solid #c2410c;border-radius:2px;pointer-events:none;z-index:100;}#m-02e1152b1ac5-light .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#1c1c1f;}#m-02e1152b1ac5-light rect.text{fill:none;stroke-width:0;}#m-02e1152b1ac5-light .icon-shape,#m-02e1152b1ac5-light .image-shape{background-color:#fafaf7;text-align:center;}#m-02e1152b1ac5-light .icon-shape p,#m-02e1152b1ac5-light .image-shape p{background-color:#fafaf7;padding:2px;}#m-02e1152b1ac5-light .icon-shape .label rect,#m-02e1152b1ac5-light .image-shape .label rect{opacity:0.5;background-color:#fafaf7;fill:#fafaf7;}#m-02e1152b1ac5-light .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#m-02e1152b1ac5-light .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#m-02e1152b1ac5-light .node .neo-node{stroke:#c8c5bb;}#m-02e1152b1ac5-light [data-look="neo"].node rect,#m-02e1152b1ac5-light [data-look="neo"].cluster rect,#m-02e1152b1ac5-light [data-look="neo"].node polygon{stroke:url(#m-02e1152b1ac5-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-02e1152b1ac5-light [data-look="neo"].node path{stroke:url(#m-02e1152b1ac5-light-gradient);stroke-width:1px;}#m-02e1152b1ac5-light [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-02e1152b1ac5-light [data-look="neo"].node .neo-line path{stroke:#c8c5bb;filter:none;}#m-02e1152b1ac5-light [data-look="neo"].node circle{stroke:url(#m-02e1152b1ac5-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-02e1152b1ac5-light [data-look="neo"].node circle .state-start{fill:#000000;}#m-02e1152b1ac5-light [data-look="neo"].icon-shape .icon{fill:url(#m-02e1152b1ac5-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-02e1152b1ac5-light [data-look="neo"].icon-shape .icon-neo path{stroke:url(#m-02e1152b1ac5-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-02e1152b1ac5-light :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="m-02e1152b1ac5-light_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-light_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-light_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-light_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-light_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-light_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-light_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-light_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-light_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-light_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-light_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="m-02e1152b1ac5-light_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M207.593,178L221.005,171.021C234.416,164.042,261.239,150.083,278.151,143.104C295.063,136.125,302.063,136.125,305.563,136.125L309.063,136.125" id="m-02e1152b1ac5-light-L_System_M_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_System_M_0" data-points="W3sieCI6MjA3LjU5MzI1Nzg3NDAxNTc2LCJ5IjoxNzh9LHsieCI6Mjg4LjA2MjUsInkiOjEzNi4xMjV9LHsieCI6MzEzLjA2MjUsInkiOjEzNi4xMjV9XQ==" data-look="classic" marker-end="url(#m-02e1152b1ac5-light_flowchart-v2-pointEnd)"/><path d="M207.593,253L221.005,259.979C234.416,266.958,261.239,280.917,282.315,287.896C303.391,294.875,318.719,294.875,326.383,294.875L334.047,294.875" id="m-02e1152b1ac5-light-L_System_O_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_System_O_0" data-points="W3sieCI6MjA3LjU5MzI1Nzg3NDAxNTc2LCJ5IjoyNTN9LHsieCI6Mjg4LjA2MjUsInkiOjI5NC44NzV9LHsieCI6MzM4LjA0Njg3NSwieSI6Mjk0Ljg3NX1d" data-look="classic" marker-end="url(#m-02e1152b1ac5-light_flowchart-v2-pointEnd)"/><path d="M537.651,87.375L547.282,82.479C556.913,77.583,576.175,67.792,589.308,63.122C602.44,58.452,609.443,58.904,612.944,59.129L616.446,59.355" id="m-02e1152b1ac5-light-L_M_A_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_M_A_0" data-points="W3sieCI6NTM3LjY1MSwieSI6ODcuMzc1fSx7IngiOjU5NS40Mzc1LCJ5Ijo1OH0seyJ4Ijo2MjAuNDM3NSwieSI6NTkuNjEyOTAzMjI1ODA2NDV9XQ==" data-look="classic" marker-end="url(#m-02e1152b1ac5-light_flowchart-v2-pointEnd)"/><path d="M504.267,234.875L519.462,220.292C534.657,205.708,565.047,176.542,585.955,159.033C606.862,141.524,618.287,135.674,623.999,132.749L629.712,129.823" id="m-02e1152b1ac5-light-L_O_A_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_O_A_0" data-points="W3sieCI6NTA0LjI2Njk0OTE1MjU0MjQsInkiOjIzNC44NzV9LHsieCI6NTk1LjQzNzUsInkiOjE0Ny4zNzV9LHsieCI6NjMzLjI3MjE0NTY2OTI5MTQsInkiOjEyOH1d" data-look="classic" marker-end="url(#m-02e1152b1ac5-light_flowchart-v2-pointEnd)"/><path d="M880.438,68L884.604,68C888.771,68,897.104,68,904.771,68C912.438,68,919.438,68,922.938,68L926.438,68" id="m-02e1152b1ac5-light-L_A_H_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_A_H_0" data-points="W3sieCI6ODgwLjQzNzUsInkiOjY4fSx7IngiOjkwNS40Mzc1LCJ5Ijo2OH0seyJ4Ijo5MzAuNDM3NSwieSI6Njh9XQ==" data-look="classic" marker-end="url(#m-02e1152b1ac5-light_flowchart-v2-pointEnd)"/><path d="M525.58,184.875L537.223,191.646C548.866,198.417,572.152,211.958,588.033,218.729C603.914,225.5,612.391,225.5,616.629,225.5L620.867,225.5" id="m-02e1152b1ac5-light-L_M_D_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_M_D_0" data-points="W3sieCI6NTI1LjU3OTU0NTQ1NDU0NTUsInkiOjE4NC44NzV9LHsieCI6NTk1LjQzNzUsInkiOjIyNS41fSx7IngiOjYyNC44NjcxODc1LCJ5IjoyMjUuNX1d" data-look="classic" marker-end="url(#m-02e1152b1ac5-light_flowchart-v2-pointEnd)"/><path d="M545.453,336.204L553.784,339.525C562.115,342.845,578.776,349.485,596.022,352.805C613.268,356.125,631.099,356.125,640.014,356.125L648.93,356.125" id="m-02e1152b1ac5-light-L_O_R_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_O_R_0" data-points="W3sieCI6NTQ1LjQ1MzEyNSwieSI6MzM2LjIwNDQyNzYxMjg1MDc0fSx7IngiOjU5NS40Mzc1LCJ5IjozNTYuMTI1fSx7IngiOjY1Mi45Mjk2ODc1LCJ5IjozNTYuMTI1fV0=" data-look="classic" marker-end="url(#m-02e1152b1ac5-light_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_System_M_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_System_O_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_M_A_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_O_A_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_A_H_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_M_D_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_O_R_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="m-02e1152b1ac5-light-flowchart-System-0" data-look="classic" transform="translate(135.53125, 215.5)"><rect class="basic label-container" style="" x="-127.53125" y="-37.5" width="255.0625" height="75"/><g class="label" style="" transform="translate(-97.53125, -22.5)"><rect/><foreignObject width="195.0625" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Система<br />сервисы, БД, кэш, очереди</p></span></div></foreignObject></g></g><g class="node default" id="m-02e1152b1ac5-light-flowchart-M-1" data-look="classic" transform="translate(441.75, 136.125)"><rect class="basic label-container" style="" x="-128.6875" y="-48.75" width="257.375" height="97.5"/><g class="label" style="" transform="translate(-98.6875, -33.75)"><rect/><foreignObject width="197.375" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Monitoring<br />known unknowns:<br />заранее заданные метрики</p></span></div></foreignObject></g></g><g class="node default" id="m-02e1152b1ac5-light-flowchart-O-3" data-look="classic" transform="translate(441.75, 294.875)"><rect class="basic label-container" style="" x="-103.703125" y="-60" width="207.40625" height="120"/><g class="label" style="" transform="translate(-73.703125, -45)"><rect/><foreignObject width="147.40625" height="90"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Observability<br />unknown unknowns:<br />возможность задать<br />новый вопрос</p></span></div></foreignObject></g></g><g class="node default" id="m-02e1152b1ac5-light-flowchart-A-5" data-look="classic" transform="translate(750.4375, 68)"><rect class="basic label-container" style="" x="-130" y="-60" width="260" height="120"/><g class="label" style="" transform="translate(-100, -45)"><rect/><foreignObject width="200" height="90"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>Alerting<br />правила, которые<br />превращают сигнал в инцидент</p></span></div></foreignObject></g></g><g class="node default" id="m-02e1152b1ac5-light-flowchart-H-9" data-look="classic" transform="translate(1016.0625, 68)"><rect class="basic label-container" style="" x="-85.625" y="-26.25" width="171.25" height="52.5"/><g class="label" style="" transform="translate(-55.625, -11.25)"><rect/><foreignObject width="111.25" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Человек on-call</p></span></div></foreignObject></g></g><g class="node default" id="m-02e1152b1ac5-light-flowchart-D-11" data-look="classic" transform="translate(750.4375, 225.5)"><rect class="basic label-container" style="" x="-125.5703125" y="-26.25" width="251.140625" height="52.5"/><g class="label" style="" transform="translate(-95.5703125, -11.25)"><rect/><foreignObject width="191.140625" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Дашборды и SLO-репорты</p></span></div></foreignObject></g></g><g class="node default" id="m-02e1152b1ac5-light-flowchart-R-13" data-look="classic" transform="translate(750.4375, 356.125)"><rect class="basic label-container" style="" x="-97.5078125" y="-26.25" width="195.015625" height="52.5"/><g class="label" style="" transform="translate(-67.5078125, -11.25)"><rect/><foreignObject width="135.015625" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Root cause analysis</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="m-02e1152b1ac5-light-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="m-02e1152b1ac5-light-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><linearGradient id="m-02e1152b1ac5-light-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#c8c5bb" stop-opacity="1"/><stop offset="100%" stop-color="#c8c5bb" stop-opacity="1"/></linearGradient></svg>
</div>
<div class="mermaid-svg mermaid-svg--dark">
<svg id="m-02e1152b1ac5-dark" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 1109.69px; background-color: transparent;" viewBox="0 0 1109.6875 390.375" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#m-02e1152b1ac5-dark{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;fill:#e8e6df;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#m-02e1152b1ac5-dark .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#m-02e1152b1ac5-dark .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#m-02e1152b1ac5-dark .error-icon{fill:#7f1d1d;}#m-02e1152b1ac5-dark .error-text{fill:#fecaca;stroke:#fecaca;}#m-02e1152b1ac5-dark .edge-thickness-normal{stroke-width:1px;}#m-02e1152b1ac5-dark .edge-thickness-thick{stroke-width:3.5px;}#m-02e1152b1ac5-dark .edge-pattern-solid{stroke-dasharray:0;}#m-02e1152b1ac5-dark .edge-thickness-invisible{stroke-width:0;fill:none;}#m-02e1152b1ac5-dark .edge-pattern-dashed{stroke-dasharray:3;}#m-02e1152b1ac5-dark .edge-pattern-dotted{stroke-dasharray:2;}#m-02e1152b1ac5-dark .marker{fill:#a8a89e;stroke:#a8a89e;}#m-02e1152b1ac5-dark .marker.cross{stroke:#a8a89e;}#m-02e1152b1ac5-dark svg{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;}#m-02e1152b1ac5-dark p{margin:0;}#m-02e1152b1ac5-dark .label{font-family:Inter,system-ui,-apple-system,sans-serif;color:#e8e6df;}#m-02e1152b1ac5-dark .cluster-label text{fill:#e8e6df;}#m-02e1152b1ac5-dark .cluster-label span{color:#e8e6df;}#m-02e1152b1ac5-dark .cluster-label span p{background-color:transparent;}#m-02e1152b1ac5-dark .label text,#m-02e1152b1ac5-dark span{fill:#e8e6df;color:#e8e6df;}#m-02e1152b1ac5-dark .node rect,#m-02e1152b1ac5-dark .node circle,#m-02e1152b1ac5-dark .node ellipse,#m-02e1152b1ac5-dark .node polygon,#m-02e1152b1ac5-dark .node path{fill:#23252a;stroke:#3f3f46;stroke-width:1px;}#m-02e1152b1ac5-dark .rough-node .label text,#m-02e1152b1ac5-dark .node .label text,#m-02e1152b1ac5-dark .image-shape .label,#m-02e1152b1ac5-dark .icon-shape .label{text-anchor:middle;}#m-02e1152b1ac5-dark .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#m-02e1152b1ac5-dark .rough-node .label,#m-02e1152b1ac5-dark .node .label,#m-02e1152b1ac5-dark .image-shape .label,#m-02e1152b1ac5-dark .icon-shape .label{text-align:center;}#m-02e1152b1ac5-dark .node.clickable{cursor:pointer;}#m-02e1152b1ac5-dark .root .anchor path{fill:#a8a89e!important;stroke-width:0;stroke:#a8a89e;}#m-02e1152b1ac5-dark .arrowheadPath{fill:rgba(255, 255, 255, 0);}#m-02e1152b1ac5-dark .edgePath .path{stroke:#a8a89e;stroke-width:1px;}#m-02e1152b1ac5-dark .flowchart-link{stroke:#a8a89e;fill:none;}#m-02e1152b1ac5-dark .edgeLabel{background-color:#1a1b1e;text-align:center;}#m-02e1152b1ac5-dark .edgeLabel p{background-color:#1a1b1e;}#m-02e1152b1ac5-dark .edgeLabel rect{opacity:0.5;background-color:#1a1b1e;fill:#1a1b1e;}#m-02e1152b1ac5-dark .labelBkg{background-color:rgba(26, 27, 30, 0.5);}#m-02e1152b1ac5-dark .cluster rect{fill:#2a2b2f;stroke:#3f3f46;stroke-width:1px;}#m-02e1152b1ac5-dark .cluster text{fill:#e8e6df;}#m-02e1152b1ac5-dark .cluster span{color:#e8e6df;}#m-02e1152b1ac5-dark div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:12px;background:#7c2d12;border:1px solid #fb923c;border-radius:2px;pointer-events:none;z-index:100;}#m-02e1152b1ac5-dark .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#e8e6df;}#m-02e1152b1ac5-dark rect.text{fill:none;stroke-width:0;}#m-02e1152b1ac5-dark .icon-shape,#m-02e1152b1ac5-dark .image-shape{background-color:#1a1b1e;text-align:center;}#m-02e1152b1ac5-dark .icon-shape p,#m-02e1152b1ac5-dark .image-shape p{background-color:#1a1b1e;padding:2px;}#m-02e1152b1ac5-dark .icon-shape .label rect,#m-02e1152b1ac5-dark .image-shape .label rect{opacity:0.5;background-color:#1a1b1e;fill:#1a1b1e;}#m-02e1152b1ac5-dark .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#m-02e1152b1ac5-dark .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#m-02e1152b1ac5-dark .node .neo-node{stroke:#3f3f46;}#m-02e1152b1ac5-dark [data-look="neo"].node rect,#m-02e1152b1ac5-dark [data-look="neo"].cluster rect,#m-02e1152b1ac5-dark [data-look="neo"].node polygon{stroke:url(#m-02e1152b1ac5-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-02e1152b1ac5-dark [data-look="neo"].node path{stroke:url(#m-02e1152b1ac5-dark-gradient);stroke-width:1px;}#m-02e1152b1ac5-dark [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-02e1152b1ac5-dark [data-look="neo"].node .neo-line path{stroke:#3f3f46;filter:none;}#m-02e1152b1ac5-dark [data-look="neo"].node circle{stroke:url(#m-02e1152b1ac5-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-02e1152b1ac5-dark [data-look="neo"].node circle .state-start{fill:#000000;}#m-02e1152b1ac5-dark [data-look="neo"].icon-shape .icon{fill:url(#m-02e1152b1ac5-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-02e1152b1ac5-dark [data-look="neo"].icon-shape .icon-neo path{stroke:url(#m-02e1152b1ac5-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-02e1152b1ac5-dark :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="m-02e1152b1ac5-dark_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-dark_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-dark_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-dark_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-dark_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-dark_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-dark_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-dark_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-dark_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-dark_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-dark_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="m-02e1152b1ac5-dark_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M207.593,178L221.005,171.021C234.416,164.042,261.239,150.083,278.151,143.104C295.063,136.125,302.063,136.125,305.563,136.125L309.063,136.125" id="m-02e1152b1ac5-dark-L_System_M_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_System_M_0" data-points="W3sieCI6MjA3LjU5MzI1Nzg3NDAxNTc2LCJ5IjoxNzh9LHsieCI6Mjg4LjA2MjUsInkiOjEzNi4xMjV9LHsieCI6MzEzLjA2MjUsInkiOjEzNi4xMjV9XQ==" data-look="classic" marker-end="url(#m-02e1152b1ac5-dark_flowchart-v2-pointEnd)"/><path d="M207.593,253L221.005,259.979C234.416,266.958,261.239,280.917,282.315,287.896C303.391,294.875,318.719,294.875,326.383,294.875L334.047,294.875" id="m-02e1152b1ac5-dark-L_System_O_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_System_O_0" data-points="W3sieCI6MjA3LjU5MzI1Nzg3NDAxNTc2LCJ5IjoyNTN9LHsieCI6Mjg4LjA2MjUsInkiOjI5NC44NzV9LHsieCI6MzM4LjA0Njg3NSwieSI6Mjk0Ljg3NX1d" data-look="classic" marker-end="url(#m-02e1152b1ac5-dark_flowchart-v2-pointEnd)"/><path d="M537.651,87.375L547.282,82.479C556.913,77.583,576.175,67.792,589.308,63.122C602.44,58.452,609.443,58.904,612.944,59.129L616.446,59.355" id="m-02e1152b1ac5-dark-L_M_A_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_M_A_0" data-points="W3sieCI6NTM3LjY1MSwieSI6ODcuMzc1fSx7IngiOjU5NS40Mzc1LCJ5Ijo1OH0seyJ4Ijo2MjAuNDM3NSwieSI6NTkuNjEyOTAzMjI1ODA2NDV9XQ==" data-look="classic" marker-end="url(#m-02e1152b1ac5-dark_flowchart-v2-pointEnd)"/><path d="M504.267,234.875L519.462,220.292C534.657,205.708,565.047,176.542,585.955,159.033C606.862,141.524,618.287,135.674,623.999,132.749L629.712,129.823" id="m-02e1152b1ac5-dark-L_O_A_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_O_A_0" data-points="W3sieCI6NTA0LjI2Njk0OTE1MjU0MjQsInkiOjIzNC44NzV9LHsieCI6NTk1LjQzNzUsInkiOjE0Ny4zNzV9LHsieCI6NjMzLjI3MjE0NTY2OTI5MTQsInkiOjEyOH1d" data-look="classic" marker-end="url(#m-02e1152b1ac5-dark_flowchart-v2-pointEnd)"/><path d="M880.438,68L884.604,68C888.771,68,897.104,68,904.771,68C912.438,68,919.438,68,922.938,68L926.438,68" id="m-02e1152b1ac5-dark-L_A_H_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_A_H_0" data-points="W3sieCI6ODgwLjQzNzUsInkiOjY4fSx7IngiOjkwNS40Mzc1LCJ5Ijo2OH0seyJ4Ijo5MzAuNDM3NSwieSI6Njh9XQ==" data-look="classic" marker-end="url(#m-02e1152b1ac5-dark_flowchart-v2-pointEnd)"/><path d="M525.58,184.875L537.223,191.646C548.866,198.417,572.152,211.958,588.033,218.729C603.914,225.5,612.391,225.5,616.629,225.5L620.867,225.5" id="m-02e1152b1ac5-dark-L_M_D_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_M_D_0" data-points="W3sieCI6NTI1LjU3OTU0NTQ1NDU0NTUsInkiOjE4NC44NzV9LHsieCI6NTk1LjQzNzUsInkiOjIyNS41fSx7IngiOjYyNC44NjcxODc1LCJ5IjoyMjUuNX1d" data-look="classic" marker-end="url(#m-02e1152b1ac5-dark_flowchart-v2-pointEnd)"/><path d="M545.453,336.204L553.784,339.525C562.115,342.845,578.776,349.485,596.022,352.805C613.268,356.125,631.099,356.125,640.014,356.125L648.93,356.125" id="m-02e1152b1ac5-dark-L_O_R_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_O_R_0" data-points="W3sieCI6NTQ1LjQ1MzEyNSwieSI6MzM2LjIwNDQyNzYxMjg1MDc0fSx7IngiOjU5NS40Mzc1LCJ5IjozNTYuMTI1fSx7IngiOjY1Mi45Mjk2ODc1LCJ5IjozNTYuMTI1fV0=" data-look="classic" marker-end="url(#m-02e1152b1ac5-dark_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_System_M_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_System_O_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_M_A_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_O_A_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_A_H_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_M_D_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_O_R_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="m-02e1152b1ac5-dark-flowchart-System-0" data-look="classic" transform="translate(135.53125, 215.5)"><rect class="basic label-container" style="" x="-127.53125" y="-37.5" width="255.0625" height="75"/><g class="label" style="" transform="translate(-97.53125, -22.5)"><rect/><foreignObject width="195.0625" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Система<br />сервисы, БД, кэш, очереди</p></span></div></foreignObject></g></g><g class="node default" id="m-02e1152b1ac5-dark-flowchart-M-1" data-look="classic" transform="translate(441.75, 136.125)"><rect class="basic label-container" style="" x="-128.6875" y="-48.75" width="257.375" height="97.5"/><g class="label" style="" transform="translate(-98.6875, -33.75)"><rect/><foreignObject width="197.375" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Monitoring<br />known unknowns:<br />заранее заданные метрики</p></span></div></foreignObject></g></g><g class="node default" id="m-02e1152b1ac5-dark-flowchart-O-3" data-look="classic" transform="translate(441.75, 294.875)"><rect class="basic label-container" style="" x="-103.703125" y="-60" width="207.40625" height="120"/><g class="label" style="" transform="translate(-73.703125, -45)"><rect/><foreignObject width="147.40625" height="90"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Observability<br />unknown unknowns:<br />возможность задать<br />новый вопрос</p></span></div></foreignObject></g></g><g class="node default" id="m-02e1152b1ac5-dark-flowchart-A-5" data-look="classic" transform="translate(750.4375, 68)"><rect class="basic label-container" style="" x="-130" y="-60" width="260" height="120"/><g class="label" style="" transform="translate(-100, -45)"><rect/><foreignObject width="200" height="90"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>Alerting<br />правила, которые<br />превращают сигнал в инцидент</p></span></div></foreignObject></g></g><g class="node default" id="m-02e1152b1ac5-dark-flowchart-H-9" data-look="classic" transform="translate(1016.0625, 68)"><rect class="basic label-container" style="" x="-85.625" y="-26.25" width="171.25" height="52.5"/><g class="label" style="" transform="translate(-55.625, -11.25)"><rect/><foreignObject width="111.25" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Человек on-call</p></span></div></foreignObject></g></g><g class="node default" id="m-02e1152b1ac5-dark-flowchart-D-11" data-look="classic" transform="translate(750.4375, 225.5)"><rect class="basic label-container" style="" x="-125.5703125" y="-26.25" width="251.140625" height="52.5"/><g class="label" style="" transform="translate(-95.5703125, -11.25)"><rect/><foreignObject width="191.140625" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Дашборды и SLO-репорты</p></span></div></foreignObject></g></g><g class="node default" id="m-02e1152b1ac5-dark-flowchart-R-13" data-look="classic" transform="translate(750.4375, 356.125)"><rect class="basic label-container" style="" x="-97.5078125" y="-26.25" width="195.015625" height="52.5"/><g class="label" style="" transform="translate(-67.5078125, -11.25)"><rect/><foreignObject width="135.015625" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Root cause analysis</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="m-02e1152b1ac5-dark-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="m-02e1152b1ac5-dark-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><linearGradient id="m-02e1152b1ac5-dark-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#3f3f46" stop-opacity="1"/><stop offset="100%" stop-color="#3f3f46" stop-opacity="1"/></linearGradient></svg>
</div>
</figure><p>В этой триаде SLI — это специально выделенные метрики из мониторинга, которые отражают пользовательский опыт. SLO — правило поверх SLI, которое мы хотим выполнять. Алерты по burn-rate — правила поверх SLO. Observability — страховка на случай, когда SLO сгорает, и нужно понять, <strong>почему именно сейчас и в этом запросе</strong>. Иначе говоря: мониторинг, SLI и SLO живут в плоскости «всё ли в порядке по тем критериям, которые мы назначили». Observability — в плоскости «что именно сейчас не так и почему», когда привычные метрики не дают ответа.</p>
<p>Теперь, с этим словарём — переходим к самому SLI.</p>
<h3 id="что-такое-sli">Что такое SLI</h3>
<p><strong>SLI (Service Level Indicator)</strong> — измеримая характеристика, которая отражает качество одного аспекта обслуживания пользователя. Ключевое слово — <strong>отражает</strong>. SLI меряет не «что система делает», а «насколько хорошо это видит пользователь».</p>
<p>Каноническая формула SLI — доля «хороших» событий от всех релевантных:</p>
$$ \text{SLI} = \dfrac{\text{количество хороших событий}}{\text{количество всех релевантных событий}} \times 100\% $$<p>Что такое «хорошее событие» и какие события «релевантны» — определяется <strong>явно</strong>, иначе SLI получится бесполезным. Самая частая ошибка здесь — посчитать «все HTTP 2xx» как «хорошие». Так делать нельзя по двум причинам:</p>
<ol>
<li><strong>Не все 2xx одинаковы.</strong> Запрос, ответивший <code>200 OK</code> за 5 секунд, формально успешен, но для пользователя это провал. SLI должен учитывать порог по латентности, иначе он маскирует деградацию.</li>
<li><strong>Не все запросы одинаковы.</strong> Health-чек с другого сервиса тоже летит как HTTP-запрос, но на пользовательский опыт не влияет. Если он попал в знаменатель — SLI размылся.</li>
</ol>
<h3 id="формат-хорошего-sli">Формат хорошего SLI</h3>
<p>У хорошего SLI всегда три явные части:</p>
<ul>
<li><strong>Числитель.</strong> Что считаем «хорошим» — порог по времени, корректности, объёму. Должно быть ясно, что туда входит, а что нет.</li>
<li><strong>Знаменатель.</strong> Какие события считаем релевантными — фильтр по эндпоинту, источнику трафика, типу запроса. Должно быть ясно, какие исключаем.</li>
<li><strong>Окно агрегации.</strong> За какой период считаем — 5 минут для алертов, 30 дней для отчётности. Без окна SLI — не число, а описание формы.</li>
</ul>
<h3 id="конкретные-sli-для-нашего-кейса">Конкретные SLI для нашего кейса</h3>
<p>Возьмём ключевые шаги из таблицы НФТ и сформулируем для них SLI. Останавливаюсь на четырёх — этого достаточно, чтобы показать механику; в реальном проде их обычно 4–8 на сервис.</p>
<p><strong>SLI-1 — Latency-SLI на шаге 4 «получение выдачи».</strong></p>
<blockquote><p>Доля поисковых запросов, на которые система ответила за время <code>&lt; 500 ms</code>, от всех релевантных поисковых запросов с пользовательского трафика, за окно 30 дней.</p>
</blockquote><ul>
<li><strong>Числитель:</strong> запросы с <code>status in {200, 204}</code> AND <code>request_duration &lt; 500 ms</code>.</li>
<li><strong>Знаменатель:</strong> запросы с <code>status in {200, 204, 5xx}</code> плюс таймауты, исключая 4xx-валидационные ответы (всё, что не health-check, не synthetic-проба, не вызов внутреннего сервиса).</li>
<li><strong>Окно:</strong> 30 дней rolling.</li>
</ul>
<p>Заметь две вещи. Во-первых, <strong>5xx в знаменателе</strong>: не учитывать их — значит нарисовать оптимистичную картинку, в которой провал «технически не считается». Во-вторых, <strong>4xx-ответы пользовательского трафика в знаменатель не идут</strong> — по канонической Google SRE-практике (глава «Service Level Objectives» в SRE Workbook, O&rsquo;Reilly, 2018) это корректное отвержение невалидного запроса (например, поисковая строка пустая или превышает лимит длины), система отработала ожидаемо. Включать их в знаменатель — раздуть его и сделать SLI оптимистичнее, чем он есть на самом деле.</p>
<p><strong>SLI-2 — Availability-SLI на шаге 4.</strong></p>
<blockquote><p>Доля поисковых запросов, завершившихся успешно (не 5xx, не таймаут), от всех релевантных запросов, за окно 30 дней.</p>
</blockquote><p>Это «классическая» availability. Но смотрим только на пользовательский трафик в шаг 4, не «по системе целиком». Знаменатель тот же, что у SLI-1, — 4xx-валидационные ответы исключены.</p>
<p><strong>SLI-3 — Correctness-SLI на шаге 4.</strong></p>
<blockquote><p>Доля поисковых запросов, вернувших непустую и валидную выдачу, от всех запросов, для которых должна была быть хотя бы одна позиция (не 0-result-by-design).</p>
</blockquote><p>Этот SLI сложнее, потому что нужно знать «должна была быть выдача или нет». Меряется офлайн-сэмплингом: берём X% запросов, прогоняем эталонный поиск, сравниваем долю «должно быть, но не было».</p>
<p><strong>SLI-4 — Freshness-SLI на шаге 6 «клик в карточку».</strong></p>
<blockquote><p>Доля переходов в карточку, на которых цена и наличие отображены не старше 60 секунд от истинного состояния товара.</p>
</blockquote><p>Этот SLI напрямую защищает от ситуации «увидел одну цену в выдаче — на чекауте другая». Без него ты рискуешь не техническим инцидентом, а <strong>репутационным</strong>: пользователь зол, возвраты растут, рейтинг продавцов падает.</p>
<p>Аналогичные SLI строятся для autocomplete, фильтра, отправки запроса по той же механике — повторять не буду. Достаточно принципа: один шаг — один или несколько SLI, каждый с явным числителем, знаменателем и окном.</p>
<h3 id="что-мы-не-берём-как-sli">Что мы НЕ берём как SLI</h3>
<p>Контрпримеры, чтобы калибровать чутьё:</p>
<ul>
<li><strong>CPU/Memory utilization.</strong> Это <strong>служебный сигнал</strong>, а не SLI. Пользователь не страдает от того, что у тебя CPU 80% — он страдает только если это превратилось в latency или 5xx. Утилизация — причина, SLI — следствие.</li>
<li><strong>Количество подов в реплике.</strong> Тоже служебный. Метрика для capacity planning, не для SLO.</li>
<li><strong>Среднее время ответа.</strong> Опасный «псевдо-SLI». Скрывает хвосты — а хвосты это и есть пользовательская боль. Только перцентили: P95 как минимум, P99 для критичных шагов.</li>
</ul>
<p>Дальше — превращаем SLI в обещание самим себе. То есть в SLO.</p>
<h2 id="шаг-4-slo-как-контракт-и-error-budget-математически">Шаг 4: SLO как контракт и error budget математически</h2>
<p><strong>SLO (Service Level Objective)</strong> — целевое значение SLI на оговорённом окне. Если SLI отвечает на вопрос «как было», то SLO — «как мы обещаем, что должно быть».</p>
<p>Формула:</p>
$$ \text{SLO}: \text{SLI} \geq T \text{ (на окне } W) $$<p>Где <code>T</code> — таргет (например, <code>99.9</code>), <code>W</code> — окно агрегации (например, 30 дней rolling).</p>
<h3 id="slo-для-нашего-sli-1">SLO для нашего SLI-1</h3>
<p>Берём SLI-1 (latency-SLI поиска: доля запросов <code>&lt; 500 ms</code>):</p>
<blockquote><p>SLO: 99.9% поисковых запросов отвечают быстрее <code>500 ms</code> на rolling-окне 30 дней.</p>
</blockquote><p>Это полноценный контракт. И он автоматически рождает <strong>error budget</strong>.</p>
<h3 id="error-budget-математически">Error budget математически</h3>
<p>Error budget — это <strong>разрешённая доля «плохих» событий</strong> за период:</p>
$$ \text{Error Budget} = 1 - \text{SLO} $$<p>Для SLO <code>99.9%</code> это <code>0.1%</code>, или 1 «плохой» запрос из 1000.</p>
<p>Дальше переводим в абсолютные значения. Берём типовой день нашего маркетплейса:</p>
<ul>
<li>Пиковый RPS: <code>30 000 запросов/сек</code>.</li>
<li>Средний по дню (с учётом ночи): <code>~10 000 запросов/сек</code>.</li>
<li>Запросов в сутки: <code>10 000 × 86 400 ≈ 864 000 000</code>.</li>
<li>Запросов за 30-дневное окно: <code>~26 миллиардов</code>.</li>
<li>Допустимая доля «плохих» при SLO <code>99.9%</code>: <code>0.1%</code>.</li>
<li><strong>Бюджет ошибок за 30 дней: ~26 миллионов запросов.</strong></li>
</ul>
<p>Если перевести в эквивалент простоя — двумя срезами, на пике и при средней нагрузке за сутки:</p>
<table>
  <thead>
      <tr>
          <th>SLO</th>
          <th>Бюджет ошибок</th>
          <th>На пике (30k RPS)</th>
          <th>При средней нагрузке (~10k RPS)</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>99.0%</td>
          <td>~260M запросов</td>
          <td>~2 ч 24 мин</td>
          <td>~7 ч 13 мин</td>
      </tr>
      <tr>
          <td>99.9%</td>
          <td>~26M запросов</td>
          <td>~14 мин 27 с</td>
          <td>~43 мин 20 с</td>
      </tr>
      <tr>
          <td>99.99%</td>
          <td>~2.6M запросов</td>
          <td>~1 мин 27 с</td>
          <td>~4 мин 20 с</td>
      </tr>
      <tr>
          <td>99.999%</td>
          <td>~260K запросов</td>
          <td>~8.7 с</td>
          <td>~26 с</td>
      </tr>
  </tbody>
</table>
<p>Две колонки — потому что бюджет ошибок «горит» неравномерно. На пике RPS ты расходуешь запросы в три раза быстрее, чем в среднем по суткам, — поэтому инцидент в Чёрную пятницу обходится сильно дороже, чем тот же инцидент во вторник в 4 утра. Колонка «На пике» — про худший случай, на который надо проектировать SLO; колонка «При средней нагрузке» — про календарный «эквивалент полного простоя», который чаще видят в отчётах.</p>
<p>Это не просто разные числа — это разные <strong>физические возможности</strong>. На пике 8.7 секунд в месяц означают, что человек не успеет даже заметить пейдж: реакция должна быть автоматической. 7 часов в месяц при средней нагрузке — означают, что можно позволить себе ручной разбор каждого инцидента.</p>
<h3 id="что-error-budget-значит-на-практике">Что error budget значит на практике</h3>
<p>Бюджет — не «допустимый ущерб», а <strong>бюджет на риск</strong>. На него тратятся:</p>
<ul>
<li><strong>Деплои.</strong> Каждый релиз — ставка из бюджета. Откат + время на восстановление = израсходованные ошибки.</li>
<li><strong>Эксперименты.</strong> A/B-тесты, постепенный rollout, фиче-флаги — потенциальные источники регрессии.</li>
<li><strong>Учения.</strong> Game days, chaos engineering, плановые отказы — расходуют бюджет, но взамен дают уверенность в стабильности на реальных инцидентах.</li>
</ul>
<p>Если бюджет полностью сгорел до конца окна — это сигнал к <strong>freeze: остановить рискованные деплои и вкладываться в reliability</strong>, пока окно не сдвинется. Если бюджет жирный — это <strong>разрешение рисковать</strong>: ускорять выкатки, экспериментировать, рефакторить.</p>
<p>К теме «бюджет как валюта в спорах» вернусь в разделе про error budget как арбитр. Сейчас важно зафиксировать одно: <strong>SLO без error budget — это пожелание, а не контракт.</strong> Бюджет — то, что превращает SLO из табло в инструмент принятия решений.</p>
<p>Дальше — главный технический разбор статьи. Берём один и тот же поиск маркетплейса и прокручиваем сквозь три уровня SLO: 99.0%, 99.9%, 99.99%. Покажу, что меняется в архитектуре, что — в стоимости, что — в эксплуатационной нагрузке.</p>
<h2 id="один-кейс--три-slo--три-архитектуры">Один кейс — три SLO — три архитектуры</h2>
<p>Дальше беру тот же поиск маркетплейса с теми же параметрами и проектирую <strong>три разные системы</strong>. Меняется структура read path, выбор технологий, capacity, RTO/RPO, эксплуатационная модель. Остаётся постановка задачи, объём каталога (50M), пиковый RPS (30k), 5 регионов, 70% mobile.</p>
<p>Структура каждого подраздела одинаковая: бюджет → схема read path → числа (capacity, RTO/RPO, кэш, индекс) → что добавилось по сравнению с предыдущим уровнем и зачем → чего намеренно НЕ делаем.</p>
<h3 id="slo-990-дешёвая-надёжность-для-не-критичных-сценариев">SLO 99.0%: «дешёвая надёжность» для не-критичных сценариев</h3>
<p><strong>Бюджет:</strong> ~260M «плохих» запросов за 30 дней, или <strong>~2 ч 24 мин</strong> полного даунтайма на пике / <strong>~7 ч 13 мин</strong> при средней нагрузке. Почти полный рабочий день на инциденты в месяц — много, но выживаемо при ручной операционной модели.</p>
<p><strong>Когда уместно:</strong> внутренние инструменты, ранний MVP стартапа, неосновные feature-paths в большом продукте (например, search в каталоге сторонних услуг, не кормящий основную конверсию).</p>
<p><strong>Read path:</strong></p>
<figure class="mermaid mermaid--prerendered" aria-label="Mermaid diagram">
<div class="mermaid-svg mermaid-svg--light">
<svg id="m-eda2ce005e57-light" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 1028.84px; background-color: transparent;" viewBox="0 0 1028.84375 138.9862823486328" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#m-eda2ce005e57-light{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;fill:#1c1c1f;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#m-eda2ce005e57-light .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#m-eda2ce005e57-light .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#m-eda2ce005e57-light .error-icon{fill:#fee2e2;}#m-eda2ce005e57-light .error-text{fill:#7f1d1d;stroke:#7f1d1d;}#m-eda2ce005e57-light .edge-thickness-normal{stroke-width:1px;}#m-eda2ce005e57-light .edge-thickness-thick{stroke-width:3.5px;}#m-eda2ce005e57-light .edge-pattern-solid{stroke-dasharray:0;}#m-eda2ce005e57-light .edge-thickness-invisible{stroke-width:0;fill:none;}#m-eda2ce005e57-light .edge-pattern-dashed{stroke-dasharray:3;}#m-eda2ce005e57-light .edge-pattern-dotted{stroke-dasharray:2;}#m-eda2ce005e57-light .marker{fill:#5b5b62;stroke:#5b5b62;}#m-eda2ce005e57-light .marker.cross{stroke:#5b5b62;}#m-eda2ce005e57-light svg{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;}#m-eda2ce005e57-light p{margin:0;}#m-eda2ce005e57-light .label{font-family:Inter,system-ui,-apple-system,sans-serif;color:#1c1c1f;}#m-eda2ce005e57-light .cluster-label text{fill:#1c1c1f;}#m-eda2ce005e57-light .cluster-label span{color:#1c1c1f;}#m-eda2ce005e57-light .cluster-label span p{background-color:transparent;}#m-eda2ce005e57-light .label text,#m-eda2ce005e57-light span{fill:#1c1c1f;color:#1c1c1f;}#m-eda2ce005e57-light .node rect,#m-eda2ce005e57-light .node circle,#m-eda2ce005e57-light .node ellipse,#m-eda2ce005e57-light .node polygon,#m-eda2ce005e57-light .node path{fill:#ffffff;stroke:#c8c5bb;stroke-width:1px;}#m-eda2ce005e57-light .rough-node .label text,#m-eda2ce005e57-light .node .label text,#m-eda2ce005e57-light .image-shape .label,#m-eda2ce005e57-light .icon-shape .label{text-anchor:middle;}#m-eda2ce005e57-light .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#m-eda2ce005e57-light .rough-node .label,#m-eda2ce005e57-light .node .label,#m-eda2ce005e57-light .image-shape .label,#m-eda2ce005e57-light .icon-shape .label{text-align:center;}#m-eda2ce005e57-light .node.clickable{cursor:pointer;}#m-eda2ce005e57-light .root .anchor path{fill:#5b5b62!important;stroke-width:0;stroke:#5b5b62;}#m-eda2ce005e57-light .arrowheadPath{fill:rgba(255, 255, 255, 0);}#m-eda2ce005e57-light .edgePath .path{stroke:#5b5b62;stroke-width:1px;}#m-eda2ce005e57-light .flowchart-link{stroke:#5b5b62;fill:none;}#m-eda2ce005e57-light .edgeLabel{background-color:#fafaf7;text-align:center;}#m-eda2ce005e57-light .edgeLabel p{background-color:#fafaf7;}#m-eda2ce005e57-light .edgeLabel rect{opacity:0.5;background-color:#fafaf7;fill:#fafaf7;}#m-eda2ce005e57-light .labelBkg{background-color:rgba(250, 250, 247, 0.5);}#m-eda2ce005e57-light .cluster rect{fill:#f3f1ed;stroke:#c8c5bb;stroke-width:1px;}#m-eda2ce005e57-light .cluster text{fill:#1c1c1f;}#m-eda2ce005e57-light .cluster span{color:#1c1c1f;}#m-eda2ce005e57-light div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:12px;background:#fed7aa;border:1px solid #c2410c;border-radius:2px;pointer-events:none;z-index:100;}#m-eda2ce005e57-light .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#1c1c1f;}#m-eda2ce005e57-light rect.text{fill:none;stroke-width:0;}#m-eda2ce005e57-light .icon-shape,#m-eda2ce005e57-light .image-shape{background-color:#fafaf7;text-align:center;}#m-eda2ce005e57-light .icon-shape p,#m-eda2ce005e57-light .image-shape p{background-color:#fafaf7;padding:2px;}#m-eda2ce005e57-light .icon-shape .label rect,#m-eda2ce005e57-light .image-shape .label rect{opacity:0.5;background-color:#fafaf7;fill:#fafaf7;}#m-eda2ce005e57-light .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#m-eda2ce005e57-light .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#m-eda2ce005e57-light .node .neo-node{stroke:#c8c5bb;}#m-eda2ce005e57-light [data-look="neo"].node rect,#m-eda2ce005e57-light [data-look="neo"].cluster rect,#m-eda2ce005e57-light [data-look="neo"].node polygon{stroke:url(#m-eda2ce005e57-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-eda2ce005e57-light [data-look="neo"].node path{stroke:url(#m-eda2ce005e57-light-gradient);stroke-width:1px;}#m-eda2ce005e57-light [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-eda2ce005e57-light [data-look="neo"].node .neo-line path{stroke:#c8c5bb;filter:none;}#m-eda2ce005e57-light [data-look="neo"].node circle{stroke:url(#m-eda2ce005e57-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-eda2ce005e57-light [data-look="neo"].node circle .state-start{fill:#000000;}#m-eda2ce005e57-light [data-look="neo"].icon-shape .icon{fill:url(#m-eda2ce005e57-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-eda2ce005e57-light [data-look="neo"].icon-shape .icon-neo path{stroke:url(#m-eda2ce005e57-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-eda2ce005e57-light :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="m-eda2ce005e57-light_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-light_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-light_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-light_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-light_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-light_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-light_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-light_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-light_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-light_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-light_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="m-eda2ce005e57-light_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M163.348,55.5L168.157,53.833C172.966,52.167,182.585,48.833,190.894,47.167C199.203,45.5,206.203,45.5,209.703,45.5L213.203,45.5" id="m-eda2ce005e57-light-L_U_LB_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_U_LB_0" data-points="W3sieCI6MTYzLjM0NzUyMTU1MTcyNDEzLCJ5Ijo1NS41fSx7IngiOjE5Mi4yMDMxMjUsInkiOjQ1LjV9LHsieCI6MjE3LjIwMzEyNSwieSI6NDUuNX1d" data-look="classic" marker-end="url(#m-eda2ce005e57-light_flowchart-v2-pointEnd)"/><path d="M374.516,45.5L378.682,45.5C382.849,45.5,391.182,45.5,398.884,46.69C406.585,47.879,413.655,50.259,417.19,51.448L420.725,52.638" id="m-eda2ce005e57-light-L_LB_A_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_LB_A_0" data-points="W3sieCI6Mzc0LjUxNTYyNSwieSI6NDUuNX0seyJ4IjozOTkuNTE1NjI1LCJ5Ijo0NS41fSx7IngiOjQyNC41MTU2MjUsInkiOjUzLjkxMzcyMzA3MjQ1OTU2fV0=" data-look="classic" marker-end="url(#m-eda2ce005e57-light_flowchart-v2-pointEnd)"/><path d="M589.938,53.914L594.104,52.511C598.271,51.109,606.604,48.305,614.271,46.902C621.938,45.5,628.938,45.5,632.438,45.5L635.938,45.5" id="m-eda2ce005e57-light-L_A_C_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_A_C_0" data-points="W3sieCI6NTg5LjkzNzUsInkiOjUzLjkxMzcyMzA3MjQ1OTU2fSx7IngiOjYxNC45Mzc1LCJ5Ijo0NS41fSx7IngiOjYzOS45Mzc1LCJ5Ijo0NS41fV0=" data-look="classic" marker-end="url(#m-eda2ce005e57-light_flowchart-v2-pointEnd)"/><path d="M807.797,45.5L814.579,45.5C821.362,45.5,834.927,45.5,847.861,47.593C860.795,49.687,873.098,53.873,879.249,55.967L885.401,58.06" id="m-eda2ce005e57-light-L_C_P_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_C_P_0" data-points="W3sieCI6ODA3Ljc5Njg3NSwieSI6NDUuNX0seyJ4Ijo4NDguNDkyMTg3NSwieSI6NDUuNX0seyJ4Ijo4ODkuMTg3NSwieSI6NTkuMzQ4NjQzMTk3NjUzMTA0fV0=" data-look="classic" marker-end="url(#m-eda2ce005e57-light_flowchart-v2-pointEnd)"/><path d="M889.188,104.151L882.405,106.459C875.622,108.768,862.057,113.384,834.504,115.692C806.951,118,765.409,118,726.483,118C687.557,118,651.247,118,629.558,116.81C607.868,115.621,600.798,113.241,597.263,112.052L593.729,110.862" id="m-eda2ce005e57-light-L_P_A_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_P_A_0" data-points="W3sieCI6ODg5LjE4NzUsInkiOjEwNC4xNTEzNTY4MDIzNDY5fSx7IngiOjg0OC40OTIxODc1LCJ5IjoxMTh9LHsieCI6NzIzLjg2NzE4NzUsInkiOjExOH0seyJ4Ijo2MTQuOTM3NSwieSI6MTE4fSx7IngiOjU4OS45Mzc1LCJ5IjoxMDkuNTg2Mjc2OTI3NTQwNDR9XQ==" data-look="classic" marker-end="url(#m-eda2ce005e57-light_flowchart-v2-pointEnd)"/><path d="M424.516,109.586L420.349,110.989C416.182,112.391,407.849,115.195,386.406,116.598C364.964,118,330.411,118,295.859,118C261.307,118,226.755,118,205.3,116.552C183.844,115.103,175.486,112.207,171.306,110.758L167.127,109.31" id="m-eda2ce005e57-light-L_A_U_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_A_U_0" data-points="W3sieCI6NDI0LjUxNTYyNSwieSI6MTA5LjU4NjI3NjkyNzU0MDQ0fSx7IngiOjM5OS41MTU2MjUsInkiOjExOH0seyJ4IjoyOTUuODU5Mzc1LCJ5IjoxMTh9LHsieCI6MTkyLjIwMzEyNSwieSI6MTE4fSx7IngiOjE2My4zNDc1MjE1NTE3MjQxMywieSI6MTA4fV0=" data-look="classic" marker-end="url(#m-eda2ce005e57-light_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_U_LB_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_LB_A_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_A_C_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(848.4921875, 45.5)"><g class="label" data-id="L_C_P_0" transform="translate(-15.6953125, -11.25)"><foreignObject width="31.390625" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>miss</p></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_P_A_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_A_U_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="m-eda2ce005e57-light-flowchart-U-0" data-look="classic" transform="translate(87.6015625, 81.75)"><rect class="basic label-container" style="" x="-79.6015625" y="-26.25" width="159.203125" height="52.5"/><g class="label" style="" transform="translate(-49.6015625, -11.25)"><rect/><foreignObject width="99.203125" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Пользователь</p></span></div></foreignObject></g></g><g class="node default" id="m-eda2ce005e57-light-flowchart-LB-1" data-look="classic" transform="translate(295.859375, 45.5)"><rect class="basic label-container" style="" x="-78.65625" y="-37.5" width="157.3125" height="75"/><g class="label" style="" transform="translate(-48.65625, -22.5)"><rect/><foreignObject width="97.3125" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Load Balancer<br />1 регион</p></span></div></foreignObject></g></g><g class="node default" id="m-eda2ce005e57-light-flowchart-A-3" data-look="classic" transform="translate(507.2265625, 81.75)"><rect class="basic label-container" style="" x="-82.7109375" y="-37.5" width="165.421875" height="75"/><g class="label" style="" transform="translate(-52.7109375, -22.5)"><rect/><foreignObject width="105.421875" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>App-сервер<br />3–5 инстансов</p></span></div></foreignObject></g></g><g class="node default" id="m-eda2ce005e57-light-flowchart-C-5" data-look="classic" transform="translate(723.8671875, 45.5)"><rect class="basic label-container" style="" x="-83.9296875" y="-37.5" width="167.859375" height="75"/><g class="label" style="" transform="translate(-53.9296875, -22.5)"><rect/><foreignObject width="107.859375" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>In-memory LRU<br />per-instance</p></span></div></foreignObject></g></g><g class="node default" id="m-eda2ce005e57-light-flowchart-P-7" data-look="classic" transform="translate(955.015625, 81.75)"><path d="M0,12.8241811761841 a65.828125,12.8241811761841 0,0,0 131.65625,0 a65.828125,12.8241811761841 0,0,0 -131.65625,0 l0,72.8241811761841 a65.828125,12.8241811761841 0,0,0 131.65625,0 l0,-72.8241811761841" class="basic label-container outer-path" style="" transform="translate(-65.828125, -49.23627176427615)"/><g class="label" style="" transform="translate(-58.328125, -12.5)"><rect/><foreignObject width="116.65625" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Postgres primary<br />+ 1 read replica</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="m-eda2ce005e57-light-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="m-eda2ce005e57-light-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><linearGradient id="m-eda2ce005e57-light-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#c8c5bb" stop-opacity="1"/><stop offset="100%" stop-color="#c8c5bb" stop-opacity="1"/></linearGradient></svg>
</div>
<div class="mermaid-svg mermaid-svg--dark">
<svg id="m-eda2ce005e57-dark" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 1028.84px; background-color: transparent;" viewBox="0 0 1028.84375 138.9862823486328" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#m-eda2ce005e57-dark{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;fill:#e8e6df;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#m-eda2ce005e57-dark .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#m-eda2ce005e57-dark .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#m-eda2ce005e57-dark .error-icon{fill:#7f1d1d;}#m-eda2ce005e57-dark .error-text{fill:#fecaca;stroke:#fecaca;}#m-eda2ce005e57-dark .edge-thickness-normal{stroke-width:1px;}#m-eda2ce005e57-dark .edge-thickness-thick{stroke-width:3.5px;}#m-eda2ce005e57-dark .edge-pattern-solid{stroke-dasharray:0;}#m-eda2ce005e57-dark .edge-thickness-invisible{stroke-width:0;fill:none;}#m-eda2ce005e57-dark .edge-pattern-dashed{stroke-dasharray:3;}#m-eda2ce005e57-dark .edge-pattern-dotted{stroke-dasharray:2;}#m-eda2ce005e57-dark .marker{fill:#a8a89e;stroke:#a8a89e;}#m-eda2ce005e57-dark .marker.cross{stroke:#a8a89e;}#m-eda2ce005e57-dark svg{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;}#m-eda2ce005e57-dark p{margin:0;}#m-eda2ce005e57-dark .label{font-family:Inter,system-ui,-apple-system,sans-serif;color:#e8e6df;}#m-eda2ce005e57-dark .cluster-label text{fill:#e8e6df;}#m-eda2ce005e57-dark .cluster-label span{color:#e8e6df;}#m-eda2ce005e57-dark .cluster-label span p{background-color:transparent;}#m-eda2ce005e57-dark .label text,#m-eda2ce005e57-dark span{fill:#e8e6df;color:#e8e6df;}#m-eda2ce005e57-dark .node rect,#m-eda2ce005e57-dark .node circle,#m-eda2ce005e57-dark .node ellipse,#m-eda2ce005e57-dark .node polygon,#m-eda2ce005e57-dark .node path{fill:#23252a;stroke:#3f3f46;stroke-width:1px;}#m-eda2ce005e57-dark .rough-node .label text,#m-eda2ce005e57-dark .node .label text,#m-eda2ce005e57-dark .image-shape .label,#m-eda2ce005e57-dark .icon-shape .label{text-anchor:middle;}#m-eda2ce005e57-dark .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#m-eda2ce005e57-dark .rough-node .label,#m-eda2ce005e57-dark .node .label,#m-eda2ce005e57-dark .image-shape .label,#m-eda2ce005e57-dark .icon-shape .label{text-align:center;}#m-eda2ce005e57-dark .node.clickable{cursor:pointer;}#m-eda2ce005e57-dark .root .anchor path{fill:#a8a89e!important;stroke-width:0;stroke:#a8a89e;}#m-eda2ce005e57-dark .arrowheadPath{fill:rgba(255, 255, 255, 0);}#m-eda2ce005e57-dark .edgePath .path{stroke:#a8a89e;stroke-width:1px;}#m-eda2ce005e57-dark .flowchart-link{stroke:#a8a89e;fill:none;}#m-eda2ce005e57-dark .edgeLabel{background-color:#1a1b1e;text-align:center;}#m-eda2ce005e57-dark .edgeLabel p{background-color:#1a1b1e;}#m-eda2ce005e57-dark .edgeLabel rect{opacity:0.5;background-color:#1a1b1e;fill:#1a1b1e;}#m-eda2ce005e57-dark .labelBkg{background-color:rgba(26, 27, 30, 0.5);}#m-eda2ce005e57-dark .cluster rect{fill:#2a2b2f;stroke:#3f3f46;stroke-width:1px;}#m-eda2ce005e57-dark .cluster text{fill:#e8e6df;}#m-eda2ce005e57-dark .cluster span{color:#e8e6df;}#m-eda2ce005e57-dark div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:12px;background:#7c2d12;border:1px solid #fb923c;border-radius:2px;pointer-events:none;z-index:100;}#m-eda2ce005e57-dark .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#e8e6df;}#m-eda2ce005e57-dark rect.text{fill:none;stroke-width:0;}#m-eda2ce005e57-dark .icon-shape,#m-eda2ce005e57-dark .image-shape{background-color:#1a1b1e;text-align:center;}#m-eda2ce005e57-dark .icon-shape p,#m-eda2ce005e57-dark .image-shape p{background-color:#1a1b1e;padding:2px;}#m-eda2ce005e57-dark .icon-shape .label rect,#m-eda2ce005e57-dark .image-shape .label rect{opacity:0.5;background-color:#1a1b1e;fill:#1a1b1e;}#m-eda2ce005e57-dark .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#m-eda2ce005e57-dark .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#m-eda2ce005e57-dark .node .neo-node{stroke:#3f3f46;}#m-eda2ce005e57-dark [data-look="neo"].node rect,#m-eda2ce005e57-dark [data-look="neo"].cluster rect,#m-eda2ce005e57-dark [data-look="neo"].node polygon{stroke:url(#m-eda2ce005e57-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-eda2ce005e57-dark [data-look="neo"].node path{stroke:url(#m-eda2ce005e57-dark-gradient);stroke-width:1px;}#m-eda2ce005e57-dark [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-eda2ce005e57-dark [data-look="neo"].node .neo-line path{stroke:#3f3f46;filter:none;}#m-eda2ce005e57-dark [data-look="neo"].node circle{stroke:url(#m-eda2ce005e57-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-eda2ce005e57-dark [data-look="neo"].node circle .state-start{fill:#000000;}#m-eda2ce005e57-dark [data-look="neo"].icon-shape .icon{fill:url(#m-eda2ce005e57-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-eda2ce005e57-dark [data-look="neo"].icon-shape .icon-neo path{stroke:url(#m-eda2ce005e57-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-eda2ce005e57-dark :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="m-eda2ce005e57-dark_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-dark_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-dark_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-dark_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-dark_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-dark_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-dark_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-dark_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-dark_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-dark_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-dark_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="m-eda2ce005e57-dark_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M163.348,55.5L168.157,53.833C172.966,52.167,182.585,48.833,190.894,47.167C199.203,45.5,206.203,45.5,209.703,45.5L213.203,45.5" id="m-eda2ce005e57-dark-L_U_LB_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_U_LB_0" data-points="W3sieCI6MTYzLjM0NzUyMTU1MTcyNDEzLCJ5Ijo1NS41fSx7IngiOjE5Mi4yMDMxMjUsInkiOjQ1LjV9LHsieCI6MjE3LjIwMzEyNSwieSI6NDUuNX1d" data-look="classic" marker-end="url(#m-eda2ce005e57-dark_flowchart-v2-pointEnd)"/><path d="M374.516,45.5L378.682,45.5C382.849,45.5,391.182,45.5,398.884,46.69C406.585,47.879,413.655,50.259,417.19,51.448L420.725,52.638" id="m-eda2ce005e57-dark-L_LB_A_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_LB_A_0" data-points="W3sieCI6Mzc0LjUxNTYyNSwieSI6NDUuNX0seyJ4IjozOTkuNTE1NjI1LCJ5Ijo0NS41fSx7IngiOjQyNC41MTU2MjUsInkiOjUzLjkxMzcyMzA3MjQ1OTU2fV0=" data-look="classic" marker-end="url(#m-eda2ce005e57-dark_flowchart-v2-pointEnd)"/><path d="M589.938,53.914L594.104,52.511C598.271,51.109,606.604,48.305,614.271,46.902C621.938,45.5,628.938,45.5,632.438,45.5L635.938,45.5" id="m-eda2ce005e57-dark-L_A_C_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_A_C_0" data-points="W3sieCI6NTg5LjkzNzUsInkiOjUzLjkxMzcyMzA3MjQ1OTU2fSx7IngiOjYxNC45Mzc1LCJ5Ijo0NS41fSx7IngiOjYzOS45Mzc1LCJ5Ijo0NS41fV0=" data-look="classic" marker-end="url(#m-eda2ce005e57-dark_flowchart-v2-pointEnd)"/><path d="M807.797,45.5L814.579,45.5C821.362,45.5,834.927,45.5,847.861,47.593C860.795,49.687,873.098,53.873,879.249,55.967L885.401,58.06" id="m-eda2ce005e57-dark-L_C_P_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_C_P_0" data-points="W3sieCI6ODA3Ljc5Njg3NSwieSI6NDUuNX0seyJ4Ijo4NDguNDkyMTg3NSwieSI6NDUuNX0seyJ4Ijo4ODkuMTg3NSwieSI6NTkuMzQ4NjQzMTk3NjUzMTA0fV0=" data-look="classic" marker-end="url(#m-eda2ce005e57-dark_flowchart-v2-pointEnd)"/><path d="M889.188,104.151L882.405,106.459C875.622,108.768,862.057,113.384,834.504,115.692C806.951,118,765.409,118,726.483,118C687.557,118,651.247,118,629.558,116.81C607.868,115.621,600.798,113.241,597.263,112.052L593.729,110.862" id="m-eda2ce005e57-dark-L_P_A_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_P_A_0" data-points="W3sieCI6ODg5LjE4NzUsInkiOjEwNC4xNTEzNTY4MDIzNDY5fSx7IngiOjg0OC40OTIxODc1LCJ5IjoxMTh9LHsieCI6NzIzLjg2NzE4NzUsInkiOjExOH0seyJ4Ijo2MTQuOTM3NSwieSI6MTE4fSx7IngiOjU4OS45Mzc1LCJ5IjoxMDkuNTg2Mjc2OTI3NTQwNDR9XQ==" data-look="classic" marker-end="url(#m-eda2ce005e57-dark_flowchart-v2-pointEnd)"/><path d="M424.516,109.586L420.349,110.989C416.182,112.391,407.849,115.195,386.406,116.598C364.964,118,330.411,118,295.859,118C261.307,118,226.755,118,205.3,116.552C183.844,115.103,175.486,112.207,171.306,110.758L167.127,109.31" id="m-eda2ce005e57-dark-L_A_U_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_A_U_0" data-points="W3sieCI6NDI0LjUxNTYyNSwieSI6MTA5LjU4NjI3NjkyNzU0MDQ0fSx7IngiOjM5OS41MTU2MjUsInkiOjExOH0seyJ4IjoyOTUuODU5Mzc1LCJ5IjoxMTh9LHsieCI6MTkyLjIwMzEyNSwieSI6MTE4fSx7IngiOjE2My4zNDc1MjE1NTE3MjQxMywieSI6MTA4fV0=" data-look="classic" marker-end="url(#m-eda2ce005e57-dark_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_U_LB_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_LB_A_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_A_C_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(848.4921875, 45.5)"><g class="label" data-id="L_C_P_0" transform="translate(-15.6953125, -11.25)"><foreignObject width="31.390625" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>miss</p></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_P_A_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_A_U_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="m-eda2ce005e57-dark-flowchart-U-0" data-look="classic" transform="translate(87.6015625, 81.75)"><rect class="basic label-container" style="" x="-79.6015625" y="-26.25" width="159.203125" height="52.5"/><g class="label" style="" transform="translate(-49.6015625, -11.25)"><rect/><foreignObject width="99.203125" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Пользователь</p></span></div></foreignObject></g></g><g class="node default" id="m-eda2ce005e57-dark-flowchart-LB-1" data-look="classic" transform="translate(295.859375, 45.5)"><rect class="basic label-container" style="" x="-78.65625" y="-37.5" width="157.3125" height="75"/><g class="label" style="" transform="translate(-48.65625, -22.5)"><rect/><foreignObject width="97.3125" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Load Balancer<br />1 регион</p></span></div></foreignObject></g></g><g class="node default" id="m-eda2ce005e57-dark-flowchart-A-3" data-look="classic" transform="translate(507.2265625, 81.75)"><rect class="basic label-container" style="" x="-82.7109375" y="-37.5" width="165.421875" height="75"/><g class="label" style="" transform="translate(-52.7109375, -22.5)"><rect/><foreignObject width="105.421875" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>App-сервер<br />3–5 инстансов</p></span></div></foreignObject></g></g><g class="node default" id="m-eda2ce005e57-dark-flowchart-C-5" data-look="classic" transform="translate(723.8671875, 45.5)"><rect class="basic label-container" style="" x="-83.9296875" y="-37.5" width="167.859375" height="75"/><g class="label" style="" transform="translate(-53.9296875, -22.5)"><rect/><foreignObject width="107.859375" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>In-memory LRU<br />per-instance</p></span></div></foreignObject></g></g><g class="node default" id="m-eda2ce005e57-dark-flowchart-P-7" data-look="classic" transform="translate(955.015625, 81.75)"><path d="M0,12.8241811761841 a65.828125,12.8241811761841 0,0,0 131.65625,0 a65.828125,12.8241811761841 0,0,0 -131.65625,0 l0,72.8241811761841 a65.828125,12.8241811761841 0,0,0 131.65625,0 l0,-72.8241811761841" class="basic label-container outer-path" style="" transform="translate(-65.828125, -49.23627176427615)"/><g class="label" style="" transform="translate(-58.328125, -12.5)"><rect/><foreignObject width="116.65625" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Postgres primary<br />+ 1 read replica</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="m-eda2ce005e57-dark-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="m-eda2ce005e57-dark-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><linearGradient id="m-eda2ce005e57-dark-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#3f3f46" stop-opacity="1"/><stop offset="100%" stop-color="#3f3f46" stop-opacity="1"/></linearGradient></svg>
</div>
</figure><p><strong>Числовые прикидки:</strong></p>
<ul>
<li><strong>Capacity.</strong> 30k RPS пика → при <code>99.0%</code> можно потерять ~300 запросов/сек без нарушения SLO. Один хорошо настроенный Postgres primary с trigram-индексом на <code>title/description</code> тянет 1–3k RPS read на сложных запросах с фильтрами и фасетами, до 5–8k RPS — на простых коротких запросах с маленькой выборкой (P99 &lt; 200 ms, при правильном connection pooling). Read replica удваивает чтение, итого <code>~2–15k RPS</code> в зависимости от профиля. На пике 30k ты либо урежешь long-tail запросы кэшем приложения, либо примешь деградацию — бюджет позволяет.</li>
<li><strong>Кэш.</strong> In-memory LRU на каждом app-инстансе, размер <code>~256 MB</code>. Hit rate 30–40% на популярных запросах. Без Redis — отдельный сервис добавил бы операционную сложность, нерелевантную для этого SLO.</li>
<li><strong>Полнотекстовый индекс.</strong> <code>pg_trgm</code> + <code>tsvector</code> поверх 50M товаров занимают <code>3–5×</code> от размера индексируемых текстовых полей (title, description, attributes-text). Для нашего каталога с расширенными текстовыми атрибутами это порядка <code>1.5–2.5 TB</code> индексов. Реалистично на одной мощной машине (NVMe, 256 GB RAM).</li>
<li><strong>RTO.</strong> До 30–60 минут на ручной failover на реплику. Автоматизации нет — стоит отдельный сервис.</li>
<li><strong>RPO.</strong> До 5 минут (типовая асинхронная репликация Postgres).</li>
<li><strong>Алерты.</strong> На симптомы: 5xx-rate, P99 latency, replication lag. Реакция оператором, не автоматическая remediation.</li>
</ul>
<p><strong>Почему этого достаточно — счёт по бюджету.</strong> Бюджет 99.0% — это <code>~7 часов даунтайма в месяц</code> при средней нагрузке. Типовой худший случай выхода из строя primary с восстановлением из <code>pg_basebackup</code> + PITR — <code>30–90 минут</code> от пейджа до возобновления read path (включая ручное переключение приложений на реплику и прогрев кэша). Даже два таких инцидента в месяц съедают <code>~3 часа</code> — это меньше половины бюджета. Платить за синхронную репликацию, автоматический failover-tooling (Patroni / RepMgr / Stolon) и дежурную команду, способную их обслуживать, на этом уровне SLO нечем: бюджет покрывает ручной MTTR с большим запасом. На 99.9% этого запаса уже нет — отсюда и Active-passive failover на следующем уровне.</p>
<p><strong>Что намеренно НЕ делаем:</strong></p>
<ul>
<li>Не поднимаем Elasticsearch — он добавит +1 систему-источник истины, требующую отдельного индексирования, мониторинга и SLO. На 99.0% это лишний оверхед.</li>
<li>Не делаем шардинг — одна машина с 256 GB RAM в 2025 году утаскивает 50M документов с trigram-индексом без проблем.</li>
<li>Не делаем multi-region даже active-passive. Бюджет 7 часов покрывает любой региональный инцидент с ручным восстановлением.</li>
</ul>
<p><strong>Стоимость:</strong> обозначу как <strong>1× baseline</strong> для последующего сравнения.</p>
<h3 id="slo-999-рабочий-production-уровень">SLO 99.9%: рабочий production-уровень</h3>
<p><strong>Бюджет:</strong> ~26M «плохих» запросов за 30 дней, или <strong>~14 мин 27 с</strong> полного даунтайма на пике / <strong>~43 мин 20 с</strong> при средней нагрузке. На инцидент при средней нагрузке остаётся минут 20–30 — хватает на автоматический failover, но не на ручной разбор каждого 5xx.</p>
<p><strong>Когда уместно:</strong> основные пользовательские пути в среднем e-commerce, обычный production. Большинство сервисов в индустрии живут в этом диапазоне.</p>
<p><strong>Read path:</strong></p>
<figure class="mermaid mermaid--prerendered" aria-label="Mermaid diagram">
<div class="mermaid-svg mermaid-svg--light">
<svg id="m-58b7ff999bbf-light" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 1236.55px; background-color: transparent;" viewBox="0 0 1236.546875 312.40679931640625" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#m-58b7ff999bbf-light{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;fill:#1c1c1f;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#m-58b7ff999bbf-light .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#m-58b7ff999bbf-light .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#m-58b7ff999bbf-light .error-icon{fill:#fee2e2;}#m-58b7ff999bbf-light .error-text{fill:#7f1d1d;stroke:#7f1d1d;}#m-58b7ff999bbf-light .edge-thickness-normal{stroke-width:1px;}#m-58b7ff999bbf-light .edge-thickness-thick{stroke-width:3.5px;}#m-58b7ff999bbf-light .edge-pattern-solid{stroke-dasharray:0;}#m-58b7ff999bbf-light .edge-thickness-invisible{stroke-width:0;fill:none;}#m-58b7ff999bbf-light .edge-pattern-dashed{stroke-dasharray:3;}#m-58b7ff999bbf-light .edge-pattern-dotted{stroke-dasharray:2;}#m-58b7ff999bbf-light .marker{fill:#5b5b62;stroke:#5b5b62;}#m-58b7ff999bbf-light .marker.cross{stroke:#5b5b62;}#m-58b7ff999bbf-light svg{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;}#m-58b7ff999bbf-light p{margin:0;}#m-58b7ff999bbf-light .label{font-family:Inter,system-ui,-apple-system,sans-serif;color:#1c1c1f;}#m-58b7ff999bbf-light .cluster-label text{fill:#1c1c1f;}#m-58b7ff999bbf-light .cluster-label span{color:#1c1c1f;}#m-58b7ff999bbf-light .cluster-label span p{background-color:transparent;}#m-58b7ff999bbf-light .label text,#m-58b7ff999bbf-light span{fill:#1c1c1f;color:#1c1c1f;}#m-58b7ff999bbf-light .node rect,#m-58b7ff999bbf-light .node circle,#m-58b7ff999bbf-light .node ellipse,#m-58b7ff999bbf-light .node polygon,#m-58b7ff999bbf-light .node path{fill:#ffffff;stroke:#c8c5bb;stroke-width:1px;}#m-58b7ff999bbf-light .rough-node .label text,#m-58b7ff999bbf-light .node .label text,#m-58b7ff999bbf-light .image-shape .label,#m-58b7ff999bbf-light .icon-shape .label{text-anchor:middle;}#m-58b7ff999bbf-light .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#m-58b7ff999bbf-light .rough-node .label,#m-58b7ff999bbf-light .node .label,#m-58b7ff999bbf-light .image-shape .label,#m-58b7ff999bbf-light .icon-shape .label{text-align:center;}#m-58b7ff999bbf-light .node.clickable{cursor:pointer;}#m-58b7ff999bbf-light .root .anchor path{fill:#5b5b62!important;stroke-width:0;stroke:#5b5b62;}#m-58b7ff999bbf-light .arrowheadPath{fill:rgba(255, 255, 255, 0);}#m-58b7ff999bbf-light .edgePath .path{stroke:#5b5b62;stroke-width:1px;}#m-58b7ff999bbf-light .flowchart-link{stroke:#5b5b62;fill:none;}#m-58b7ff999bbf-light .edgeLabel{background-color:#fafaf7;text-align:center;}#m-58b7ff999bbf-light .edgeLabel p{background-color:#fafaf7;}#m-58b7ff999bbf-light .edgeLabel rect{opacity:0.5;background-color:#fafaf7;fill:#fafaf7;}#m-58b7ff999bbf-light .labelBkg{background-color:rgba(250, 250, 247, 0.5);}#m-58b7ff999bbf-light .cluster rect{fill:#f3f1ed;stroke:#c8c5bb;stroke-width:1px;}#m-58b7ff999bbf-light .cluster text{fill:#1c1c1f;}#m-58b7ff999bbf-light .cluster span{color:#1c1c1f;}#m-58b7ff999bbf-light div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:12px;background:#fed7aa;border:1px solid #c2410c;border-radius:2px;pointer-events:none;z-index:100;}#m-58b7ff999bbf-light .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#1c1c1f;}#m-58b7ff999bbf-light rect.text{fill:none;stroke-width:0;}#m-58b7ff999bbf-light .icon-shape,#m-58b7ff999bbf-light .image-shape{background-color:#fafaf7;text-align:center;}#m-58b7ff999bbf-light .icon-shape p,#m-58b7ff999bbf-light .image-shape p{background-color:#fafaf7;padding:2px;}#m-58b7ff999bbf-light .icon-shape .label rect,#m-58b7ff999bbf-light .image-shape .label rect{opacity:0.5;background-color:#fafaf7;fill:#fafaf7;}#m-58b7ff999bbf-light .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#m-58b7ff999bbf-light .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#m-58b7ff999bbf-light .node .neo-node{stroke:#c8c5bb;}#m-58b7ff999bbf-light [data-look="neo"].node rect,#m-58b7ff999bbf-light [data-look="neo"].cluster rect,#m-58b7ff999bbf-light [data-look="neo"].node polygon{stroke:url(#m-58b7ff999bbf-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-58b7ff999bbf-light [data-look="neo"].node path{stroke:url(#m-58b7ff999bbf-light-gradient);stroke-width:1px;}#m-58b7ff999bbf-light [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-58b7ff999bbf-light [data-look="neo"].node .neo-line path{stroke:#c8c5bb;filter:none;}#m-58b7ff999bbf-light [data-look="neo"].node circle{stroke:url(#m-58b7ff999bbf-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-58b7ff999bbf-light [data-look="neo"].node circle .state-start{fill:#000000;}#m-58b7ff999bbf-light [data-look="neo"].icon-shape .icon{fill:url(#m-58b7ff999bbf-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-58b7ff999bbf-light [data-look="neo"].icon-shape .icon-neo path{stroke:url(#m-58b7ff999bbf-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-58b7ff999bbf-light :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="m-58b7ff999bbf-light_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-light_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-light_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-light_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-light_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-light_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-light_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-light_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-light_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-light_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-light_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="m-58b7ff999bbf-light_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M119.801,158.43L131.868,148.593C143.935,138.756,168.069,119.081,186.669,109.244C205.268,99.407,218.333,99.407,224.866,99.407L231.398,99.407" id="m-58b7ff999bbf-light-L_U_CDN_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_U_CDN_0" data-points="W3sieCI6MTE5LjgwMTQ1MjU4NjIxOTkxLCJ5IjoxNTguNDMwMDg4MDQzMjEyOX0seyJ4IjoxOTIuMjAzMTI1LCJ5Ijo5OS40MDY3ODQwNTc2MTcxOX0seyJ4IjoyMzUuMzk4NDM3NSwieSI6OTkuNDA2Nzg0MDU3NjE3MTl9XQ==" data-look="classic" marker-end="url(#m-58b7ff999bbf-light_flowchart-v2-pointEnd)"/><path d="M126.287,210.93L137.273,218.385C148.259,225.839,170.231,240.748,184.717,248.202C199.203,255.657,206.203,255.657,209.703,255.657L213.203,255.657" id="m-58b7ff999bbf-light-L_U_GLB_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_U_GLB_0" data-points="W3sieCI6MTI2LjI4NzM3MzA1MjA2ODUsInkiOjIxMC45MzAwODgwNDMyMTI5fSx7IngiOjE5Mi4yMDMxMjUsInkiOjI1NS42NTY3ODQwNTc2MTcyfSx7IngiOjIxNy4yMDMxMjUsInkiOjI1NS42NTY3ODQwNTc2MTcyfV0=" data-look="classic" marker-end="url(#m-58b7ff999bbf-light_flowchart-v2-pointEnd)"/><path d="M422.656,255.657L426.823,255.657C430.99,255.657,439.323,255.657,446.99,255.657C454.656,255.657,461.656,255.657,465.156,255.657L468.656,255.657" id="m-58b7ff999bbf-light-L_GLB_R_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_GLB_R_0" data-points="W3sieCI6NDIyLjY1NjI1LCJ5IjoyNTUuNjU2Nzg0MDU3NjE3Mn0seyJ4Ijo0NDcuNjU2MjUsInkiOjI1NS42NTY3ODQwNTc2MTcyfSx7IngiOjQ3Mi42NTYyNSwieSI6MjU1LjY1Njc4NDA1NzYxNzJ9XQ==" data-look="classic" marker-end="url(#m-58b7ff999bbf-light_flowchart-v2-pointEnd)"/><path d="M626.813,260.518L633.618,260.947C640.424,261.376,654.036,262.235,666.997,261.32C679.958,260.406,692.267,257.718,698.422,256.375L704.576,255.031" id="m-58b7ff999bbf-light-L_R_SS_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_R_SS_0" data-points="W3sieCI6NjI2LjgxMjUsInkiOjI2MC41MTc4Mjk2ODgyNzMyfSx7IngiOjY2Ny42NDg0Mzc1LCJ5IjoyNjMuMDkzMjA4MzEyOTg4M30seyJ4Ijo3MDguNDg0Mzc1LCJ5IjoyNTQuMTc3NTUxNDE2NTMwNjZ9XQ==" data-look="classic" marker-end="url(#m-58b7ff999bbf-light_flowchart-v2-pointEnd)"/><path d="M883.965,194.343L898.2,187.049C912.435,179.755,940.905,165.167,963.995,151.054C987.084,136.941,1004.793,123.304,1013.648,116.485L1022.503,109.666" id="m-58b7ff999bbf-light-L_SS_ES_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_SS_ES_0" data-points="W3sieCI6ODgzLjk2NTAyMDAxMTg5MTMsInkiOjE5NC4zNDMyMDgzMTI5ODgyOH0seyJ4Ijo5NjkuMzc1LCJ5IjoxNTAuNTc4MzkyMDI4ODA4Nn0seyJ4IjoxMDI1LjY3MTg3NSwieSI6MTA3LjIyNTkxOTQ4NzY0MDl9XQ==" data-look="classic" marker-end="url(#m-58b7ff999bbf-light_flowchart-v2-pointEnd)"/><path d="M913.078,237.125L922.461,237.609C931.844,238.094,950.609,239.063,971.448,239.547C992.286,240.032,1015.198,240.032,1026.654,240.032L1038.109,240.032" id="m-58b7ff999bbf-light-L_SS_RR_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_SS_RR_0" data-points="W3sieCI6OTEzLjA3ODEyNSwieSI6MjM3LjEyNTA0MTM1NzMzMTY3fSx7IngiOjk2OS4zNzUsInkiOjI0MC4wMzE3ODQwNTc2MTcyfSx7IngiOjEwNDIuMTA5Mzc1LCJ5IjoyNDAuMDMxNzg0MDU3NjE3Mn1d" data-look="classic" marker-end="url(#m-58b7ff999bbf-light_flowchart-v2-pointEnd)"/><path d="M607.898,72.453L617.857,72.453C627.815,72.453,647.732,72.453,672.1,72.453C696.469,72.453,725.289,72.453,739.699,72.453L754.109,72.453" id="m-58b7ff999bbf-light-L_PG_Q_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_PG_Q_0" data-points="W3sieCI6NjA3Ljg5ODQzNzUsInkiOjcyLjQ1MzM5MjAyODgwODZ9LHsieCI6NjY3LjY0ODQzNzUsInkiOjcyLjQ1MzM5MjAyODgwODZ9LHsieCI6NzU4LjEwOTM3NSwieSI6NzIuNDUzMzkyMDI4ODA4Nn1d" data-look="classic" marker-end="url(#m-58b7ff999bbf-light_flowchart-v2-pointEnd)"/><path d="M863.453,72.453L881.107,72.453C898.76,72.453,934.068,72.453,960.438,72.453C986.807,72.453,1004.24,72.453,1012.956,72.453L1021.672,72.453" id="m-58b7ff999bbf-light-L_Q_ES_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Q_ES_0" data-points="W3sieCI6ODYzLjQ1MzEyNSwieSI6NzIuNDUzMzkyMDI4ODA4Nn0seyJ4Ijo5NjkuMzc1LCJ5Ijo3Mi40NTMzOTIwMjg4MDg2fSx7IngiOjEwMjUuNjcxODc1LCJ5Ijo3Mi40NTMzOTIwMjg4MDg2fV0=" data-look="classic" marker-end="url(#m-58b7ff999bbf-light_flowchart-v2-pointEnd)"/><path d="M626.813,240.09L633.618,238.716C640.424,237.341,654.036,234.592,666.982,233.218C679.927,231.843,692.206,231.843,698.345,231.843L704.484,231.843" id="m-58b7ff999bbf-light-L_R_SS_2" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_R_SS_2" data-points="W3sieCI6NjI2LjgxMjUsInkiOjI0MC4wOTAzMTM2MjEyMjIyNn0seyJ4Ijo2NjcuNjQ4NDM3NSwieSI6MjMxLjg0MzIwODMxMjk4ODI4fSx7IngiOjcwOC40ODQzNzUsInkiOjIzMS44NDMyMDgzMTI5ODgyOH1d" data-look="classic" marker-end="url(#m-58b7ff999bbf-light_flowchart-v2-pointEnd)"/><path d="M721.228,194.343L712.298,190.604C703.368,186.864,685.508,179.386,656.926,175.646C628.344,171.907,589.039,171.907,552.374,171.907C515.708,171.907,481.682,171.907,443.382,171.907C405.081,171.907,362.505,171.907,319.93,171.907C277.354,171.907,234.779,171.907,209.986,172.335C185.193,172.763,178.183,173.619,174.679,174.047L171.174,174.475" id="m-58b7ff999bbf-light-L_SS_U_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_SS_U_0" data-points="W3sieCI6NzIxLjIyODM1MjMxODI3MDEsInkiOjE5NC4zNDMyMDgzMTI5ODgyOH0seyJ4Ijo2NjcuNjQ4NDM3NSwieSI6MTcxLjkwNjc4NDA1NzYxNzJ9LHsieCI6NTQ5LjczNDM3NSwieSI6MTcxLjkwNjc4NDA1NzYxNzJ9LHsieCI6NDQ3LjY1NjI1LCJ5IjoxNzEuOTA2Nzg0MDU3NjE3Mn0seyJ4IjozMTkuOTI5Njg3NSwieSI6MTcxLjkwNjc4NDA1NzYxNzJ9LHsieCI6MTkyLjIwMzEyNSwieSI6MTcxLjkwNjc4NDA1NzYxNzJ9LHsieCI6MTY3LjIwMzEyNSwieSI6MTc0Ljk1OTYzMTM3NjYwMzR9XQ==" data-look="classic" marker-end="url(#m-58b7ff999bbf-light_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_U_CDN_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_U_GLB_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_GLB_R_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(668.07871, 262.99927)"><g class="label" data-id="L_R_SS_0" transform="translate(-15.6953125, -11.25)"><foreignObject width="31.390625" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>miss</p></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_SS_ES_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_SS_RR_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(667.6484375, 72.4533920288086)"><g class="label" data-id="L_PG_Q_0" transform="translate(-15.8359375, -11.25)"><foreignObject width="31.671875" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>CDC</p></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(969.375, 72.4533920288086)"><g class="label" data-id="L_Q_ES_0" transform="translate(-31.296875, -11.25)"><foreignObject width="62.59375" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>consume</p></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_R_SS_2" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_SS_U_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="m-58b7ff999bbf-light-flowchart-U-0" data-look="classic" transform="translate(87.6015625, 184.6800880432129)"><rect class="basic label-container" style="" x="-79.6015625" y="-26.25" width="159.203125" height="52.5"/><g class="label" style="" transform="translate(-49.6015625, -11.25)"><rect/><foreignObject width="99.203125" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Пользователь</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-light-flowchart-CDN-1" data-look="classic" transform="translate(319.9296875, 99.40678405761719)"><rect class="basic label-container" style="" x="-84.53125" y="-37.5" width="169.0625" height="75"/><g class="label" style="" transform="translate(-54.53125, -22.5)"><rect/><foreignObject width="109.0625" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>CDN<br />статика, медиа</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-light-flowchart-GLB-3" data-look="classic" transform="translate(319.9296875, 255.6567840576172)"><rect class="basic label-container" style="" x="-102.7265625" y="-48.75" width="205.453125" height="97.5"/><g class="label" style="" transform="translate(-72.7265625, -33.75)"><rect/><foreignObject width="145.453125" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Global LB<br />гео-роутинг<br />в 1 активный регион</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-light-flowchart-R-5" data-look="classic" transform="translate(549.734375, 255.6567840576172)"><rect class="basic label-container" style="" x="-77.078125" y="-48.75" width="154.15625" height="97.5"/><g class="label" style="" transform="translate(-47.078125, -33.75)"><rect/><foreignObject width="94.15625" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Redis Cluster<br />top queries +<br />autocomplete</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-light-flowchart-SS-7" data-look="classic" transform="translate(810.78125, 231.84320831298828)"><rect class="basic label-container" style="" x="-102.296875" y="-37.5" width="204.59375" height="75"/><g class="label" style="" transform="translate(-72.296875, -22.5)"><rect/><foreignObject width="144.59375" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Search Service<br />app-tier, 12–20 инст.</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-light-flowchart-ES-9" data-look="classic" transform="translate(1127.109375, 72.4533920288086)"><path d="M0,15.468928707586732 a101.4375,15.468928707586732 0,0,0 202.875,0 a101.4375,15.468928707586732 0,0,0 -202.875,0 l0,97.96892870758673 a101.4375,15.468928707586732 0,0,0 202.875,0 l0,-97.96892870758673" class="basic label-container outer-path" style="" transform="translate(-101.4375, -64.4533930613801)"/><g class="label" style="" transform="translate(-93.9375, -23.75)"><rect/><foreignObject width="187.875" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Elasticsearch<br />8–12 нод, 6 primary shards<br />× 2 replicas</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-light-flowchart-RR-11" data-look="classic" transform="translate(1127.109375, 240.0317840576172)"><rect class="basic label-container" style="" x="-85" y="-37.5" width="170" height="75"/><g class="label" style="" transform="translate(-55, -22.5)"><rect/><foreignObject width="110" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Ranking Service<br />отдельный SLO</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-light-flowchart-PG-12" data-look="classic" transform="translate(549.734375, 72.4533920288086)"><path d="M0,12.050825509873746 a58.1640625,12.050825509873746 0,0,0 116.328125,0 a58.1640625,12.050825509873746 0,0,0 -116.328125,0 l0,72.05082550987375 a58.1640625,12.050825509873746 0,0,0 116.328125,0 l0,-72.05082550987375" class="basic label-container outer-path" style="" transform="translate(-58.1640625, -48.07623826481062)"/><g class="label" style="" transform="translate(-50.6640625, -12.5)"><rect/><foreignObject width="101.328125" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Postgres<br />source of truth</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-light-flowchart-Q-13" data-look="classic" transform="translate(810.78125, 72.4533920288086)"><rect class="basic label-container" style="" x="-52.671875" y="-37.5" width="105.34375" height="75"/><g class="label" style="" transform="translate(-22.671875, -22.5)"><rect/><foreignObject width="45.34375" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Kafka<br />events</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="m-58b7ff999bbf-light-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="m-58b7ff999bbf-light-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><linearGradient id="m-58b7ff999bbf-light-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#c8c5bb" stop-opacity="1"/><stop offset="100%" stop-color="#c8c5bb" stop-opacity="1"/></linearGradient></svg>
</div>
<div class="mermaid-svg mermaid-svg--dark">
<svg id="m-58b7ff999bbf-dark" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 1236.55px; background-color: transparent;" viewBox="0 0 1236.546875 312.40679931640625" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#m-58b7ff999bbf-dark{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;fill:#e8e6df;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#m-58b7ff999bbf-dark .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#m-58b7ff999bbf-dark .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#m-58b7ff999bbf-dark .error-icon{fill:#7f1d1d;}#m-58b7ff999bbf-dark .error-text{fill:#fecaca;stroke:#fecaca;}#m-58b7ff999bbf-dark .edge-thickness-normal{stroke-width:1px;}#m-58b7ff999bbf-dark .edge-thickness-thick{stroke-width:3.5px;}#m-58b7ff999bbf-dark .edge-pattern-solid{stroke-dasharray:0;}#m-58b7ff999bbf-dark .edge-thickness-invisible{stroke-width:0;fill:none;}#m-58b7ff999bbf-dark .edge-pattern-dashed{stroke-dasharray:3;}#m-58b7ff999bbf-dark .edge-pattern-dotted{stroke-dasharray:2;}#m-58b7ff999bbf-dark .marker{fill:#a8a89e;stroke:#a8a89e;}#m-58b7ff999bbf-dark .marker.cross{stroke:#a8a89e;}#m-58b7ff999bbf-dark svg{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;}#m-58b7ff999bbf-dark p{margin:0;}#m-58b7ff999bbf-dark .label{font-family:Inter,system-ui,-apple-system,sans-serif;color:#e8e6df;}#m-58b7ff999bbf-dark .cluster-label text{fill:#e8e6df;}#m-58b7ff999bbf-dark .cluster-label span{color:#e8e6df;}#m-58b7ff999bbf-dark .cluster-label span p{background-color:transparent;}#m-58b7ff999bbf-dark .label text,#m-58b7ff999bbf-dark span{fill:#e8e6df;color:#e8e6df;}#m-58b7ff999bbf-dark .node rect,#m-58b7ff999bbf-dark .node circle,#m-58b7ff999bbf-dark .node ellipse,#m-58b7ff999bbf-dark .node polygon,#m-58b7ff999bbf-dark .node path{fill:#23252a;stroke:#3f3f46;stroke-width:1px;}#m-58b7ff999bbf-dark .rough-node .label text,#m-58b7ff999bbf-dark .node .label text,#m-58b7ff999bbf-dark .image-shape .label,#m-58b7ff999bbf-dark .icon-shape .label{text-anchor:middle;}#m-58b7ff999bbf-dark .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#m-58b7ff999bbf-dark .rough-node .label,#m-58b7ff999bbf-dark .node .label,#m-58b7ff999bbf-dark .image-shape .label,#m-58b7ff999bbf-dark .icon-shape .label{text-align:center;}#m-58b7ff999bbf-dark .node.clickable{cursor:pointer;}#m-58b7ff999bbf-dark .root .anchor path{fill:#a8a89e!important;stroke-width:0;stroke:#a8a89e;}#m-58b7ff999bbf-dark .arrowheadPath{fill:rgba(255, 255, 255, 0);}#m-58b7ff999bbf-dark .edgePath .path{stroke:#a8a89e;stroke-width:1px;}#m-58b7ff999bbf-dark .flowchart-link{stroke:#a8a89e;fill:none;}#m-58b7ff999bbf-dark .edgeLabel{background-color:#1a1b1e;text-align:center;}#m-58b7ff999bbf-dark .edgeLabel p{background-color:#1a1b1e;}#m-58b7ff999bbf-dark .edgeLabel rect{opacity:0.5;background-color:#1a1b1e;fill:#1a1b1e;}#m-58b7ff999bbf-dark .labelBkg{background-color:rgba(26, 27, 30, 0.5);}#m-58b7ff999bbf-dark .cluster rect{fill:#2a2b2f;stroke:#3f3f46;stroke-width:1px;}#m-58b7ff999bbf-dark .cluster text{fill:#e8e6df;}#m-58b7ff999bbf-dark .cluster span{color:#e8e6df;}#m-58b7ff999bbf-dark div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:12px;background:#7c2d12;border:1px solid #fb923c;border-radius:2px;pointer-events:none;z-index:100;}#m-58b7ff999bbf-dark .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#e8e6df;}#m-58b7ff999bbf-dark rect.text{fill:none;stroke-width:0;}#m-58b7ff999bbf-dark .icon-shape,#m-58b7ff999bbf-dark .image-shape{background-color:#1a1b1e;text-align:center;}#m-58b7ff999bbf-dark .icon-shape p,#m-58b7ff999bbf-dark .image-shape p{background-color:#1a1b1e;padding:2px;}#m-58b7ff999bbf-dark .icon-shape .label rect,#m-58b7ff999bbf-dark .image-shape .label rect{opacity:0.5;background-color:#1a1b1e;fill:#1a1b1e;}#m-58b7ff999bbf-dark .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#m-58b7ff999bbf-dark .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#m-58b7ff999bbf-dark .node .neo-node{stroke:#3f3f46;}#m-58b7ff999bbf-dark [data-look="neo"].node rect,#m-58b7ff999bbf-dark [data-look="neo"].cluster rect,#m-58b7ff999bbf-dark [data-look="neo"].node polygon{stroke:url(#m-58b7ff999bbf-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-58b7ff999bbf-dark [data-look="neo"].node path{stroke:url(#m-58b7ff999bbf-dark-gradient);stroke-width:1px;}#m-58b7ff999bbf-dark [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-58b7ff999bbf-dark [data-look="neo"].node .neo-line path{stroke:#3f3f46;filter:none;}#m-58b7ff999bbf-dark [data-look="neo"].node circle{stroke:url(#m-58b7ff999bbf-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-58b7ff999bbf-dark [data-look="neo"].node circle .state-start{fill:#000000;}#m-58b7ff999bbf-dark [data-look="neo"].icon-shape .icon{fill:url(#m-58b7ff999bbf-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-58b7ff999bbf-dark [data-look="neo"].icon-shape .icon-neo path{stroke:url(#m-58b7ff999bbf-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-58b7ff999bbf-dark :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="m-58b7ff999bbf-dark_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-dark_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-dark_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-dark_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-dark_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-dark_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-dark_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-dark_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-dark_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-dark_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-dark_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="m-58b7ff999bbf-dark_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M119.801,158.43L131.868,148.593C143.935,138.756,168.069,119.081,186.669,109.244C205.268,99.407,218.333,99.407,224.866,99.407L231.398,99.407" id="m-58b7ff999bbf-dark-L_U_CDN_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_U_CDN_0" data-points="W3sieCI6MTE5LjgwMTQ1MjU4NjIxOTkxLCJ5IjoxNTguNDMwMDg4MDQzMjEyOX0seyJ4IjoxOTIuMjAzMTI1LCJ5Ijo5OS40MDY3ODQwNTc2MTcxOX0seyJ4IjoyMzUuMzk4NDM3NSwieSI6OTkuNDA2Nzg0MDU3NjE3MTl9XQ==" data-look="classic" marker-end="url(#m-58b7ff999bbf-dark_flowchart-v2-pointEnd)"/><path d="M126.287,210.93L137.273,218.385C148.259,225.839,170.231,240.748,184.717,248.202C199.203,255.657,206.203,255.657,209.703,255.657L213.203,255.657" id="m-58b7ff999bbf-dark-L_U_GLB_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_U_GLB_0" data-points="W3sieCI6MTI2LjI4NzM3MzA1MjA2ODUsInkiOjIxMC45MzAwODgwNDMyMTI5fSx7IngiOjE5Mi4yMDMxMjUsInkiOjI1NS42NTY3ODQwNTc2MTcyfSx7IngiOjIxNy4yMDMxMjUsInkiOjI1NS42NTY3ODQwNTc2MTcyfV0=" data-look="classic" marker-end="url(#m-58b7ff999bbf-dark_flowchart-v2-pointEnd)"/><path d="M422.656,255.657L426.823,255.657C430.99,255.657,439.323,255.657,446.99,255.657C454.656,255.657,461.656,255.657,465.156,255.657L468.656,255.657" id="m-58b7ff999bbf-dark-L_GLB_R_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_GLB_R_0" data-points="W3sieCI6NDIyLjY1NjI1LCJ5IjoyNTUuNjU2Nzg0MDU3NjE3Mn0seyJ4Ijo0NDcuNjU2MjUsInkiOjI1NS42NTY3ODQwNTc2MTcyfSx7IngiOjQ3Mi42NTYyNSwieSI6MjU1LjY1Njc4NDA1NzYxNzJ9XQ==" data-look="classic" marker-end="url(#m-58b7ff999bbf-dark_flowchart-v2-pointEnd)"/><path d="M626.813,260.518L633.618,260.947C640.424,261.376,654.036,262.235,666.997,261.32C679.958,260.406,692.267,257.718,698.422,256.375L704.576,255.031" id="m-58b7ff999bbf-dark-L_R_SS_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_R_SS_0" data-points="W3sieCI6NjI2LjgxMjUsInkiOjI2MC41MTc4Mjk2ODgyNzMyfSx7IngiOjY2Ny42NDg0Mzc1LCJ5IjoyNjMuMDkzMjA4MzEyOTg4M30seyJ4Ijo3MDguNDg0Mzc1LCJ5IjoyNTQuMTc3NTUxNDE2NTMwNjZ9XQ==" data-look="classic" marker-end="url(#m-58b7ff999bbf-dark_flowchart-v2-pointEnd)"/><path d="M883.965,194.343L898.2,187.049C912.435,179.755,940.905,165.167,963.995,151.054C987.084,136.941,1004.793,123.304,1013.648,116.485L1022.503,109.666" id="m-58b7ff999bbf-dark-L_SS_ES_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_SS_ES_0" data-points="W3sieCI6ODgzLjk2NTAyMDAxMTg5MTMsInkiOjE5NC4zNDMyMDgzMTI5ODgyOH0seyJ4Ijo5NjkuMzc1LCJ5IjoxNTAuNTc4MzkyMDI4ODA4Nn0seyJ4IjoxMDI1LjY3MTg3NSwieSI6MTA3LjIyNTkxOTQ4NzY0MDl9XQ==" data-look="classic" marker-end="url(#m-58b7ff999bbf-dark_flowchart-v2-pointEnd)"/><path d="M913.078,237.125L922.461,237.609C931.844,238.094,950.609,239.063,971.448,239.547C992.286,240.032,1015.198,240.032,1026.654,240.032L1038.109,240.032" id="m-58b7ff999bbf-dark-L_SS_RR_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_SS_RR_0" data-points="W3sieCI6OTEzLjA3ODEyNSwieSI6MjM3LjEyNTA0MTM1NzMzMTY3fSx7IngiOjk2OS4zNzUsInkiOjI0MC4wMzE3ODQwNTc2MTcyfSx7IngiOjEwNDIuMTA5Mzc1LCJ5IjoyNDAuMDMxNzg0MDU3NjE3Mn1d" data-look="classic" marker-end="url(#m-58b7ff999bbf-dark_flowchart-v2-pointEnd)"/><path d="M607.898,72.453L617.857,72.453C627.815,72.453,647.732,72.453,672.1,72.453C696.469,72.453,725.289,72.453,739.699,72.453L754.109,72.453" id="m-58b7ff999bbf-dark-L_PG_Q_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_PG_Q_0" data-points="W3sieCI6NjA3Ljg5ODQzNzUsInkiOjcyLjQ1MzM5MjAyODgwODZ9LHsieCI6NjY3LjY0ODQzNzUsInkiOjcyLjQ1MzM5MjAyODgwODZ9LHsieCI6NzU4LjEwOTM3NSwieSI6NzIuNDUzMzkyMDI4ODA4Nn1d" data-look="classic" marker-end="url(#m-58b7ff999bbf-dark_flowchart-v2-pointEnd)"/><path d="M863.453,72.453L881.107,72.453C898.76,72.453,934.068,72.453,960.438,72.453C986.807,72.453,1004.24,72.453,1012.956,72.453L1021.672,72.453" id="m-58b7ff999bbf-dark-L_Q_ES_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Q_ES_0" data-points="W3sieCI6ODYzLjQ1MzEyNSwieSI6NzIuNDUzMzkyMDI4ODA4Nn0seyJ4Ijo5NjkuMzc1LCJ5Ijo3Mi40NTMzOTIwMjg4MDg2fSx7IngiOjEwMjUuNjcxODc1LCJ5Ijo3Mi40NTMzOTIwMjg4MDg2fV0=" data-look="classic" marker-end="url(#m-58b7ff999bbf-dark_flowchart-v2-pointEnd)"/><path d="M626.813,240.09L633.618,238.716C640.424,237.341,654.036,234.592,666.982,233.218C679.927,231.843,692.206,231.843,698.345,231.843L704.484,231.843" id="m-58b7ff999bbf-dark-L_R_SS_2" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_R_SS_2" data-points="W3sieCI6NjI2LjgxMjUsInkiOjI0MC4wOTAzMTM2MjEyMjIyNn0seyJ4Ijo2NjcuNjQ4NDM3NSwieSI6MjMxLjg0MzIwODMxMjk4ODI4fSx7IngiOjcwOC40ODQzNzUsInkiOjIzMS44NDMyMDgzMTI5ODgyOH1d" data-look="classic" marker-end="url(#m-58b7ff999bbf-dark_flowchart-v2-pointEnd)"/><path d="M721.228,194.343L712.298,190.604C703.368,186.864,685.508,179.386,656.926,175.646C628.344,171.907,589.039,171.907,552.374,171.907C515.708,171.907,481.682,171.907,443.382,171.907C405.081,171.907,362.505,171.907,319.93,171.907C277.354,171.907,234.779,171.907,209.986,172.335C185.193,172.763,178.183,173.619,174.679,174.047L171.174,174.475" id="m-58b7ff999bbf-dark-L_SS_U_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_SS_U_0" data-points="W3sieCI6NzIxLjIyODM1MjMxODI3MDEsInkiOjE5NC4zNDMyMDgzMTI5ODgyOH0seyJ4Ijo2NjcuNjQ4NDM3NSwieSI6MTcxLjkwNjc4NDA1NzYxNzJ9LHsieCI6NTQ5LjczNDM3NSwieSI6MTcxLjkwNjc4NDA1NzYxNzJ9LHsieCI6NDQ3LjY1NjI1LCJ5IjoxNzEuOTA2Nzg0MDU3NjE3Mn0seyJ4IjozMTkuOTI5Njg3NSwieSI6MTcxLjkwNjc4NDA1NzYxNzJ9LHsieCI6MTkyLjIwMzEyNSwieSI6MTcxLjkwNjc4NDA1NzYxNzJ9LHsieCI6MTY3LjIwMzEyNSwieSI6MTc0Ljk1OTYzMTM3NjYwMzR9XQ==" data-look="classic" marker-end="url(#m-58b7ff999bbf-dark_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_U_CDN_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_U_GLB_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_GLB_R_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(668.07871, 262.99927)"><g class="label" data-id="L_R_SS_0" transform="translate(-15.6953125, -11.25)"><foreignObject width="31.390625" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>miss</p></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_SS_ES_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_SS_RR_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(667.6484375, 72.4533920288086)"><g class="label" data-id="L_PG_Q_0" transform="translate(-15.8359375, -11.25)"><foreignObject width="31.671875" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>CDC</p></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(969.375, 72.4533920288086)"><g class="label" data-id="L_Q_ES_0" transform="translate(-31.296875, -11.25)"><foreignObject width="62.59375" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>consume</p></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_R_SS_2" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_SS_U_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="m-58b7ff999bbf-dark-flowchart-U-0" data-look="classic" transform="translate(87.6015625, 184.6800880432129)"><rect class="basic label-container" style="" x="-79.6015625" y="-26.25" width="159.203125" height="52.5"/><g class="label" style="" transform="translate(-49.6015625, -11.25)"><rect/><foreignObject width="99.203125" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Пользователь</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-dark-flowchart-CDN-1" data-look="classic" transform="translate(319.9296875, 99.40678405761719)"><rect class="basic label-container" style="" x="-84.53125" y="-37.5" width="169.0625" height="75"/><g class="label" style="" transform="translate(-54.53125, -22.5)"><rect/><foreignObject width="109.0625" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>CDN<br />статика, медиа</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-dark-flowchart-GLB-3" data-look="classic" transform="translate(319.9296875, 255.6567840576172)"><rect class="basic label-container" style="" x="-102.7265625" y="-48.75" width="205.453125" height="97.5"/><g class="label" style="" transform="translate(-72.7265625, -33.75)"><rect/><foreignObject width="145.453125" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Global LB<br />гео-роутинг<br />в 1 активный регион</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-dark-flowchart-R-5" data-look="classic" transform="translate(549.734375, 255.6567840576172)"><rect class="basic label-container" style="" x="-77.078125" y="-48.75" width="154.15625" height="97.5"/><g class="label" style="" transform="translate(-47.078125, -33.75)"><rect/><foreignObject width="94.15625" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Redis Cluster<br />top queries +<br />autocomplete</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-dark-flowchart-SS-7" data-look="classic" transform="translate(810.78125, 231.84320831298828)"><rect class="basic label-container" style="" x="-102.296875" y="-37.5" width="204.59375" height="75"/><g class="label" style="" transform="translate(-72.296875, -22.5)"><rect/><foreignObject width="144.59375" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Search Service<br />app-tier, 12–20 инст.</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-dark-flowchart-ES-9" data-look="classic" transform="translate(1127.109375, 72.4533920288086)"><path d="M0,15.468928707586732 a101.4375,15.468928707586732 0,0,0 202.875,0 a101.4375,15.468928707586732 0,0,0 -202.875,0 l0,97.96892870758673 a101.4375,15.468928707586732 0,0,0 202.875,0 l0,-97.96892870758673" class="basic label-container outer-path" style="" transform="translate(-101.4375, -64.4533930613801)"/><g class="label" style="" transform="translate(-93.9375, -23.75)"><rect/><foreignObject width="187.875" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Elasticsearch<br />8–12 нод, 6 primary shards<br />× 2 replicas</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-dark-flowchart-RR-11" data-look="classic" transform="translate(1127.109375, 240.0317840576172)"><rect class="basic label-container" style="" x="-85" y="-37.5" width="170" height="75"/><g class="label" style="" transform="translate(-55, -22.5)"><rect/><foreignObject width="110" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Ranking Service<br />отдельный SLO</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-dark-flowchart-PG-12" data-look="classic" transform="translate(549.734375, 72.4533920288086)"><path d="M0,12.050825509873746 a58.1640625,12.050825509873746 0,0,0 116.328125,0 a58.1640625,12.050825509873746 0,0,0 -116.328125,0 l0,72.05082550987375 a58.1640625,12.050825509873746 0,0,0 116.328125,0 l0,-72.05082550987375" class="basic label-container outer-path" style="" transform="translate(-58.1640625, -48.07623826481062)"/><g class="label" style="" transform="translate(-50.6640625, -12.5)"><rect/><foreignObject width="101.328125" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Postgres<br />source of truth</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-dark-flowchart-Q-13" data-look="classic" transform="translate(810.78125, 72.4533920288086)"><rect class="basic label-container" style="" x="-52.671875" y="-37.5" width="105.34375" height="75"/><g class="label" style="" transform="translate(-22.671875, -22.5)"><rect/><foreignObject width="45.34375" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Kafka<br />events</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="m-58b7ff999bbf-dark-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="m-58b7ff999bbf-dark-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><linearGradient id="m-58b7ff999bbf-dark-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#3f3f46" stop-opacity="1"/><stop offset="100%" stop-color="#3f3f46" stop-opacity="1"/></linearGradient></svg>
</div>
</figure><p><strong>Числовые прикидки:</strong></p>
<ul>
<li><strong>Capacity.</strong> 30k RPS пика → допустимо терять ~30 запросов/сек. На Elasticsearch при 50M документов и <code>6 primary shards × 1 replica</code> (~33 GB на шард, в коридоре best-practice 30–50 GB): запрос идёт в координатор, координатор делает fan-out на 6 шардов, агрегирует. Целевая нагрузка <code>30–40k RPS</code> с запасом. На 8–12 ES-нодах (<code>64–128 GB RAM</code> каждая) держится с P99 в районе <code>300–400 ms</code> чистого ES-времени.</li>
<li><strong>Кэш Redis.</strong> Кластер на 3–6 нодах, <code>~50 GB</code> под топовые запросы и autocomplete. Hit rate <code>65–75%</code> — ключевой множитель: при 70% hit rate на ES падает только 30% от 30k RPS, то есть <code>~9k RPS</code>. Это уже посильно для умеренного ES-кластера. Прогрев после деплоя — 5–10 минут на горячих топ-1000 запросах.</li>
<li><strong>Индексирование.</strong> Postgres → Debezium / собственный CDC → Kafka → потребитель в ES. Lag индексирования: <code>15–60 секунд</code> на типовых изменениях, <code>2–5 минут</code> на массовых обновлениях цен (например, при загрузке от продавца XML-фида). Это <strong>freshness-SLI</strong> — ценник старше 60 секунд считается «плохим событием» по SLI-4.</li>
<li><strong>Структура документа и размер индекса.</strong> Каждая карточка в ES — денормализованный документ: <code>title, description, attributes (10–20 полей), price, stock, seller_rating, geo, popularity</code>. Размер ~3–5 KB на документ. <code>50M × 4 KB = ~200 GB primary</code> + 200 GB replica = 400 GB Lucene-данных. На 12 нодах ≈ ~33 GB на ноду, рабочее множество легко помещается в RAM.</li>
<li><strong>Failover.</strong> Active-passive между двумя AZ внутри региона. RTO <code>1–3 минуты</code> через автоматический promote secondary. RPO ~30 секунд через CDC.</li>
<li><strong>Алерты.</strong> Multi-window multi-burn-rate: две пары окон со своими threshold — быстрая пара <code>5 мин + 1 час</code> с burn-rate <code>14.4×</code> (срабатывает на острый инцидент за минуты, 2% бюджета за час) и медленная пара <code>30 мин + 6 часов</code> с burn-rate <code>6×</code> (ловит «тихую» деградацию, 5% бюджета за 6 часов). Это табличные значения из главы Alerting on SLOs в Google SRE Workbook. Подробно про burn-rate как множитель — в моей предыдущей статье <a href="/posts/burn-rate-is-not-speed/">«Скорость сгорания бюджета ошибок»</a>
.</li>
</ul>
<p><strong>Что добавилось по сравнению с 99.0%:</strong></p>
<ul>
<li>Отдельный поисковый индекс (ES) — потому что <code>pg_trgm</code> на 30k RPS + ranking + facets уже не вытянет с нужной P99.</li>
<li>Redis-кластер — без него ES под пиком пришлось бы масштабировать в 3–4 раза.</li>
<li>CDC + Kafka — из-за разделения source of truth и поискового индекса нужна асинхронная синхронизация. Это новый слой риска (lag, потеря событий) и новый SLO на freshness.</li>
<li>Active-passive failover — потому что 43 минуты бюджета мало для ручного переключения.</li>
<li>Burn-rate-алерты — потому что классические «5xx &gt; 1%» при 0.1% бюджета будут срабатывать слишком поздно или генерить шум.</li>
</ul>
<p><strong>Что намеренно НЕ делаем:</strong></p>
<ul>
<li>Не делаем active-active multi-region. На 99.9% это избыточно: один регион с грамотным failover между AZ покрывает бюджет с большим запасом, а active-active добавляет проблем синхронизации (split-brain, write-write конфликты, кросс-региональные чтения по сети).</li>
<li>Не делаем repair-aware кэш — на 99.9% достаточно правильного TTL и event-driven invalidation.</li>
<li>Не делаем graceful degradation на уровне UI («поиск работает, ranking упал»). Это усложнение, оправданное на <code>99.99%+</code>.</li>
</ul>
<p><strong>Стоимость:</strong> <strong>4–6× baseline</strong> в инфраструктуре, <strong>2–3× baseline</strong> в людях (нужна команда SRE с дежурствами, отдельные процессы для Kafka и ES).</p>
<h3 id="slo-9999-дорогая-надёжность-для-tier-1-сценариев">SLO 99.99%: дорогая надёжность для tier-1 сценариев</h3>
<p><strong>Бюджет:</strong> ~2.6M «плохих» запросов за 30 дней, или <strong>~1 мин 27 с</strong> полного даунтайма на пике / <strong>~4 мин 20 с</strong> при средней нагрузке. На инцидент остаются секунды-минуты — реакция должна быть <strong>автоматической</strong>. Ручной разбор перед remediation = превышение бюджета.</p>
<p><strong>Когда уместно:</strong> tier-1 пользовательские сценарии в крупном бизнесе уровня Ozon/Wildberries или сопоставимого по GMV, где минута даунтайма стоит сотни тысяч долларов и оправдывает мультипликатор инфраструктуры. Платёжные шлюзы, биржи, ключевые поисковые сценарии больших маркетплейсов.</p>
<p><strong>Read path:</strong></p>
<figure class="mermaid mermaid--prerendered" aria-label="Mermaid diagram">
<div class="mermaid-svg mermaid-svg--light">
<svg id="m-94d254942e3a-light" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 1388.78px; background-color: transparent;" viewBox="0 -35 1388.78125 476.625" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#m-94d254942e3a-light{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;fill:#1c1c1f;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#m-94d254942e3a-light .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#m-94d254942e3a-light .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#m-94d254942e3a-light .error-icon{fill:#fee2e2;}#m-94d254942e3a-light .error-text{fill:#7f1d1d;stroke:#7f1d1d;}#m-94d254942e3a-light .edge-thickness-normal{stroke-width:1px;}#m-94d254942e3a-light .edge-thickness-thick{stroke-width:3.5px;}#m-94d254942e3a-light .edge-pattern-solid{stroke-dasharray:0;}#m-94d254942e3a-light .edge-thickness-invisible{stroke-width:0;fill:none;}#m-94d254942e3a-light .edge-pattern-dashed{stroke-dasharray:3;}#m-94d254942e3a-light .edge-pattern-dotted{stroke-dasharray:2;}#m-94d254942e3a-light .marker{fill:#5b5b62;stroke:#5b5b62;}#m-94d254942e3a-light .marker.cross{stroke:#5b5b62;}#m-94d254942e3a-light svg{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;}#m-94d254942e3a-light p{margin:0;}#m-94d254942e3a-light .label{font-family:Inter,system-ui,-apple-system,sans-serif;color:#1c1c1f;}#m-94d254942e3a-light .cluster-label text{fill:#1c1c1f;}#m-94d254942e3a-light .cluster-label span{color:#1c1c1f;}#m-94d254942e3a-light .cluster-label span p{background-color:transparent;}#m-94d254942e3a-light .label text,#m-94d254942e3a-light span{fill:#1c1c1f;color:#1c1c1f;}#m-94d254942e3a-light .node rect,#m-94d254942e3a-light .node circle,#m-94d254942e3a-light .node ellipse,#m-94d254942e3a-light .node polygon,#m-94d254942e3a-light .node path{fill:#ffffff;stroke:#c8c5bb;stroke-width:1px;}#m-94d254942e3a-light .rough-node .label text,#m-94d254942e3a-light .node .label text,#m-94d254942e3a-light .image-shape .label,#m-94d254942e3a-light .icon-shape .label{text-anchor:middle;}#m-94d254942e3a-light .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#m-94d254942e3a-light .rough-node .label,#m-94d254942e3a-light .node .label,#m-94d254942e3a-light .image-shape .label,#m-94d254942e3a-light .icon-shape .label{text-align:center;}#m-94d254942e3a-light .node.clickable{cursor:pointer;}#m-94d254942e3a-light .root .anchor path{fill:#5b5b62!important;stroke-width:0;stroke:#5b5b62;}#m-94d254942e3a-light .arrowheadPath{fill:rgba(255, 255, 255, 0);}#m-94d254942e3a-light .edgePath .path{stroke:#5b5b62;stroke-width:1px;}#m-94d254942e3a-light .flowchart-link{stroke:#5b5b62;fill:none;}#m-94d254942e3a-light .edgeLabel{background-color:#fafaf7;text-align:center;}#m-94d254942e3a-light .edgeLabel p{background-color:#fafaf7;}#m-94d254942e3a-light .edgeLabel rect{opacity:0.5;background-color:#fafaf7;fill:#fafaf7;}#m-94d254942e3a-light .labelBkg{background-color:rgba(250, 250, 247, 0.5);}#m-94d254942e3a-light .cluster rect{fill:#f3f1ed;stroke:#c8c5bb;stroke-width:1px;}#m-94d254942e3a-light .cluster text{fill:#1c1c1f;}#m-94d254942e3a-light .cluster span{color:#1c1c1f;}#m-94d254942e3a-light div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:12px;background:#fed7aa;border:1px solid #c2410c;border-radius:2px;pointer-events:none;z-index:100;}#m-94d254942e3a-light .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#1c1c1f;}#m-94d254942e3a-light rect.text{fill:none;stroke-width:0;}#m-94d254942e3a-light .icon-shape,#m-94d254942e3a-light .image-shape{background-color:#fafaf7;text-align:center;}#m-94d254942e3a-light .icon-shape p,#m-94d254942e3a-light .image-shape p{background-color:#fafaf7;padding:2px;}#m-94d254942e3a-light .icon-shape .label rect,#m-94d254942e3a-light .image-shape .label rect{opacity:0.5;background-color:#fafaf7;fill:#fafaf7;}#m-94d254942e3a-light .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#m-94d254942e3a-light .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#m-94d254942e3a-light .node .neo-node{stroke:#c8c5bb;}#m-94d254942e3a-light [data-look="neo"].node rect,#m-94d254942e3a-light [data-look="neo"].cluster rect,#m-94d254942e3a-light [data-look="neo"].node polygon{stroke:url(#m-94d254942e3a-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-94d254942e3a-light [data-look="neo"].node path{stroke:url(#m-94d254942e3a-light-gradient);stroke-width:1px;}#m-94d254942e3a-light [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-94d254942e3a-light [data-look="neo"].node .neo-line path{stroke:#c8c5bb;filter:none;}#m-94d254942e3a-light [data-look="neo"].node circle{stroke:url(#m-94d254942e3a-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-94d254942e3a-light [data-look="neo"].node circle .state-start{fill:#000000;}#m-94d254942e3a-light [data-look="neo"].icon-shape .icon{fill:url(#m-94d254942e3a-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-94d254942e3a-light [data-look="neo"].icon-shape .icon-neo path{stroke:url(#m-94d254942e3a-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-94d254942e3a-light :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="m-94d254942e3a-light_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-light_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-light_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-light_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-light_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-light_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-light_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-light_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-light_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-light_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-light_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="m-94d254942e3a-light_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M146.97,265.5L154.509,268.833C162.048,272.167,177.125,278.833,188.164,282.167C199.203,285.5,206.203,285.5,209.703,285.5L213.203,285.5" id="m-94d254942e3a-light-L_U_GA_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_U_GA_0" data-points="W3sieCI6MTQ2Ljk3MDAxNjg5MTg5MTksInkiOjI2NS41fSx7IngiOjE5Mi4yMDMxMjUsInkiOjI4NS41fSx7IngiOjIxNy4yMDMxMjUsInkiOjI4NS41fV0=" data-look="classic" marker-end="url(#m-94d254942e3a-light_flowchart-v2-pointEnd)"/><path d="M419.359,281.993L423.526,281.848C427.693,281.703,436.026,281.414,443.693,281.27C451.359,281.125,458.359,281.125,461.859,281.125L465.359,281.125" id="m-94d254942e3a-light-L_GA_RegA_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_GA_RegA_0" data-points="W3sieCI6NDE5LjM1OTM3NSwieSI6MjgxLjk5MjUxNzY2MDE4MDk3fSx7IngiOjQ0NC4zNTkzNzUsInkiOjI4MS4xMjV9LHsieCI6NDY5LjM1OTM3NSwieSI6MjgxLjEyNX1d" data-look="classic" marker-end="url(#m-94d254942e3a-light_flowchart-v2-pointEnd)"/><path d="M395.715,334.25L403.822,339.354C411.93,344.458,428.145,354.667,455.072,359.771C482,364.875,519.641,364.875,565.663,364.875C611.685,364.875,666.089,364.875,705.182,366.999C744.276,369.123,768.06,373.371,779.952,375.496L791.844,377.62" id="m-94d254942e3a-light-L_GA_RegB_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_GA_RegB_0" data-points="W3sieCI6Mzk1LjcxNTA1OTA1NTExODEsInkiOjMzNC4yNX0seyJ4Ijo0NDQuMzU5Mzc1LCJ5IjozNjQuODc1fSx7IngiOjU1Ny4yODEyNSwieSI6MzY0Ljg3NX0seyJ4Ijo3MjAuNDkyMTg3NSwieSI6MzY0Ljg3NX0seyJ4Ijo3OTUuNzgxMjUsInkiOjM3OC4zMjMwNzc2MTAwNzQxfV0=" data-look="classic" marker-end="url(#m-94d254942e3a-light_flowchart-v2-pointEnd)"/><path d="M337.949,236.75L355.684,192.792C373.419,148.833,408.889,60.917,445.445,16.958C482,-27,519.641,-27,565.663,-27C611.685,-27,666.089,-27,722.449,-27C778.81,-27,837.128,-27,898.426,-27C959.724,-27,1024.003,-27,1084.016,17.539C1144.03,62.078,1199.778,151.156,1227.652,195.695L1255.526,240.234" id="m-94d254942e3a-light-L_GA_RegC_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_GA_RegC_0" data-points="W3sieCI6MzM3Ljk0OTQzNzUsInkiOjIzNi43NX0seyJ4Ijo0NDQuMzU5Mzc1LCJ5IjotMjd9LHsieCI6NTU3LjI4MTI1LCJ5IjotMjd9LHsieCI6NzIwLjQ5MjE4NzUsInkiOi0yN30seyJ4Ijo4OTUuNDQ1MzEyNSwieSI6LTI3fSx7IngiOjEwODguMjgxMjUsInkiOi0yN30seyJ4IjoxMjU3LjY0ODMxMDcyNTE1MjIsInkiOjI0My42MjV9XQ==" data-look="classic" marker-end="url(#m-94d254942e3a-light_flowchart-v2-pointEnd)"/><path d="M626.468,329.875L642.139,340.917C657.81,351.958,689.151,374.042,716.703,385.083C744.255,396.125,768.018,396.125,779.9,396.125L791.781,396.125" id="m-94d254942e3a-light-L_RegA_RegB_0" class="edge-thickness-thick edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_RegA_RegB_0" data-points="W3sieCI6NjI2LjQ2ODQ5NTI0NDU2NTIsInkiOjMyOS44NzV9LHsieCI6NzIwLjQ5MjE4NzUsInkiOjM5Ni4xMjV9LHsieCI6Nzk1Ljc4MTI1LCJ5IjozOTYuMTI1fV0=" data-look="classic" marker-end="url(#m-94d254942e3a-light_flowchart-v2-pointEnd)"/><path d="M795.781,420.336L783.233,423.384C770.685,426.432,745.589,432.529,714.738,417.915C683.887,403.301,647.282,367.977,628.98,350.315L610.677,332.653" id="m-94d254942e3a-light-L_RegB_RegA_0" class="edge-thickness-thick edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_RegB_RegA_0" data-points="W3sieCI6Nzk1Ljc4MTI1LCJ5Ijo0MjAuMzM1NjE0NDUwMjk5Mn0seyJ4Ijo3MjAuNDkyMTg3NSwieSI6NDM4LjYyNX0seyJ4Ijo2MDcuNzk4OTIxMTMwOTUyNCwieSI6MzI5Ljg3NX1d" data-look="classic" marker-end="url(#m-94d254942e3a-light_flowchart-v2-pointEnd)"/><path d="M649.203,281.125L661.085,281.125C672.966,281.125,696.729,281.125,737.77,281.125C778.81,281.125,837.128,281.125,898.426,281.125C959.724,281.125,1024.003,281.125,1071.004,281.125C1118.005,281.125,1147.729,281.125,1162.591,281.125L1177.453,281.125" id="m-94d254942e3a-light-L_RegA_RegC_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_RegA_RegC_0" data-points="W3sieCI6NjQ1LjIwMzEyNSwieSI6MjgxLjEyNX0seyJ4Ijo3MjAuNDkyMTg3NSwieSI6MjgxLjEyNX0seyJ4Ijo4OTUuNDQ1MzEyNSwieSI6MjgxLjEyNX0seyJ4IjoxMDg4LjI4MTI1LCJ5IjoyODEuMTI1fSx7IngiOjExODEuNDUzMTI1LCJ5IjoyODEuMTI1fV0=" data-look="classic" marker-start="url(#m-94d254942e3a-light_flowchart-v2-pointStart)" marker-end="url(#m-94d254942e3a-light_flowchart-v2-pointEnd)"/><path d="M999.109,396.125L1013.971,396.125C1028.833,396.125,1058.557,396.125,1094.506,383.55C1130.454,370.975,1172.627,345.824,1193.714,333.249L1214.8,320.674" id="m-94d254942e3a-light-L_RegB_RegC_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_RegB_RegC_0" data-points="W3sieCI6OTk1LjEwOTM3NSwieSI6Mzk2LjEyNX0seyJ4IjoxMDg4LjI4MTI1LCJ5IjozOTYuMTI1fSx7IngiOjEyMTguMjM1OTAzNTMyNjA4NywieSI6MzE4LjYyNX1d" data-look="classic" marker-start="url(#m-94d254942e3a-light_flowchart-v2-pointStart)" marker-end="url(#m-94d254942e3a-light_flowchart-v2-pointEnd)"/><path d="M591.049,232.375L612.623,201.229C634.197,170.083,677.344,107.792,710.916,76.646C744.487,45.5,768.482,45.5,780.479,45.5L792.477,45.5" id="m-94d254942e3a-light-L_RegA_RAW_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_RegA_RAW_0" data-points="W3sieCI6NTkxLjA0OTAzMDE3MjQxMzgsInkiOjIzMi4zNzV9LHsieCI6NzIwLjQ5MjE4NzUsInkiOjQ1LjV9LHsieCI6Nzk2LjQ3NjU2MjUsInkiOjQ1LjV9XQ==" data-look="classic" marker-end="url(#m-94d254942e3a-light_flowchart-v2-pointEnd)"/><path d="M607.799,232.375L626.581,214.25C645.363,196.125,682.928,159.875,714.758,146.085C746.589,132.295,772.685,140.965,785.734,145.3L798.782,149.635" id="m-94d254942e3a-light-L_RegA_Deg_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_RegA_Deg_0" data-points="W3sieCI6NjA3Ljc5ODkyMTEzMDk1MjQsInkiOjIzMi4zNzV9LHsieCI6NzIwLjQ5MjE4NzUsInkiOjEyMy42MjV9LHsieCI6ODAyLjU3ODEyNSwieSI6MTUwLjg5NjU2MjY5NTM2NDgyfV0=" data-look="classic" marker-end="url(#m-94d254942e3a-light_flowchart-v2-pointEnd)"/><path d="M802.578,187.058L788.897,187.84C775.216,188.622,747.854,190.186,706.971,190.968C666.089,191.75,611.685,191.75,565.663,191.75C519.641,191.75,482,191.75,442.167,191.75C402.333,191.75,360.307,191.75,318.281,191.75C276.255,191.75,234.229,191.75,206.024,195.016C177.819,198.282,163.434,204.814,156.242,208.08L149.05,211.346" id="m-94d254942e3a-light-L_Deg_U_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Deg_U_0" data-points="W3sieCI6ODAyLjU3ODEyNSwieSI6MTg3LjA1ODExODI0NTk1ODc1fSx7IngiOjcyMC40OTIxODc1LCJ5IjoxOTEuNzV9LHsieCI6NTU3LjI4MTI1LCJ5IjoxOTEuNzV9LHsieCI6NDQ0LjM1OTM3NSwieSI6MTkxLjc1fSx7IngiOjMxOC4yODEyNSwieSI6MTkxLjc1fSx7IngiOjE5Mi4yMDMxMjUsInkiOjE5MS43NX0seyJ4IjoxNDUuNDA3Njg5MTQ0NzM2ODUsInkiOjIxM31d" data-look="classic" marker-end="url(#m-94d254942e3a-light_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_U_GA_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_GA_RegA_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_GA_RegB_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_GA_RegC_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(720.4921875, 396.125)"><g class="label" data-id="L_RegA_RegB_0" transform="translate(-50.2890625, -11.25)"><foreignObject width="100.578125" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>sync для tier-1</p></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(692.02177, 411.15079)"><g class="label" data-id="L_RegB_RegA_0" transform="translate(-50.2890625, -11.25)"><foreignObject width="100.578125" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>sync для tier-1</p></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(895.4453125, 281.125)"><g class="label" data-id="L_RegA_RegC_0" transform="translate(-68.171875, -11.25)"><foreignObject width="136.34375" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>async для каталога</p></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(1088.28125, 396.125)"><g class="label" data-id="L_RegB_RegC_0" transform="translate(-68.171875, -11.25)"><foreignObject width="136.34375" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>async для каталога</p></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_RegA_RAW_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_RegA_Deg_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Deg_U_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="m-94d254942e3a-light-flowchart-U-0" data-look="classic" transform="translate(87.6015625, 239.25)"><rect class="basic label-container" style="" x="-79.6015625" y="-26.25" width="159.203125" height="52.5"/><g class="label" style="" transform="translate(-49.6015625, -11.25)"><rect/><foreignObject width="99.203125" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Пользователь</p></span></div></foreignObject></g></g><g class="node default" id="m-94d254942e3a-light-flowchart-GA-1" data-look="classic" transform="translate(318.28125, 285.5)"><rect class="basic label-container" style="" x="-101.078125" y="-48.75" width="202.15625" height="97.5"/><g class="label" style="" transform="translate(-71.078125, -33.75)"><rect/><foreignObject width="142.15625" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Geo-Anycast<br />+ Global LB<br />health-aware routing</p></span></div></foreignObject></g></g><g class="node default" id="m-94d254942e3a-light-flowchart-RegA-3" data-look="classic" transform="translate(557.28125, 281.125)"><rect class="basic label-container" style="" x="-87.921875" y="-48.75" width="175.84375" height="97.5"/><g class="label" style="" transform="translate(-57.921875, -33.75)"><rect/><foreignObject width="115.84375" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Регион A<br />Search + Redis +<br />ES + Postgres</p></span></div></foreignObject></g></g><g class="node default" id="m-94d254942e3a-light-flowchart-RegB-5" data-look="classic" transform="translate(895.4453125, 396.125)"><rect class="basic label-container" style="" x="-99.6640625" y="-37.5" width="199.328125" height="75"/><g class="label" style="" transform="translate(-69.6640625, -22.5)"><rect/><foreignObject width="139.328125" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Регион B<br />полная копия стека</p></span></div></foreignObject></g></g><g class="node default" id="m-94d254942e3a-light-flowchart-RegC-7" data-look="classic" transform="translate(1281.1171875, 281.125)"><rect class="basic label-container" style="" x="-99.6640625" y="-37.5" width="199.328125" height="75"/><g class="label" style="" transform="translate(-69.6640625, -22.5)"><rect/><foreignObject width="139.328125" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Регион C<br />полная копия стека</p></span></div></foreignObject></g></g><g class="node default" id="m-94d254942e3a-light-flowchart-RAW-17" data-look="classic" transform="translate(895.4453125, 45.5)"><rect class="basic label-container" style="" x="-98.96875" y="-37.5" width="197.9375" height="75"/><g class="label" style="" transform="translate(-68.96875, -22.5)"><rect/><foreignObject width="137.9375" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Repair-aware Cache<br />per-region</p></span></div></foreignObject></g></g><g class="node default" id="m-94d254942e3a-light-flowchart-Deg-19" data-look="classic" transform="translate(895.4453125, 181.75)"><rect class="basic label-container" style="" x="-92.8671875" y="-48.75" width="185.734375" height="97.5"/><g class="label" style="" transform="translate(-62.8671875, -33.75)"><rect/><foreignObject width="125.734375" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Degradation Layer<br />ranking упал —<br />отдаём базовое</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="m-94d254942e3a-light-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="m-94d254942e3a-light-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><linearGradient id="m-94d254942e3a-light-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#c8c5bb" stop-opacity="1"/><stop offset="100%" stop-color="#c8c5bb" stop-opacity="1"/></linearGradient></svg>
</div>
<div class="mermaid-svg mermaid-svg--dark">
<svg id="m-94d254942e3a-dark" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 1388.78px; background-color: transparent;" viewBox="0 -35 1388.78125 476.625" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#m-94d254942e3a-dark{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;fill:#e8e6df;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#m-94d254942e3a-dark .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#m-94d254942e3a-dark .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#m-94d254942e3a-dark .error-icon{fill:#7f1d1d;}#m-94d254942e3a-dark .error-text{fill:#fecaca;stroke:#fecaca;}#m-94d254942e3a-dark .edge-thickness-normal{stroke-width:1px;}#m-94d254942e3a-dark .edge-thickness-thick{stroke-width:3.5px;}#m-94d254942e3a-dark .edge-pattern-solid{stroke-dasharray:0;}#m-94d254942e3a-dark .edge-thickness-invisible{stroke-width:0;fill:none;}#m-94d254942e3a-dark .edge-pattern-dashed{stroke-dasharray:3;}#m-94d254942e3a-dark .edge-pattern-dotted{stroke-dasharray:2;}#m-94d254942e3a-dark .marker{fill:#a8a89e;stroke:#a8a89e;}#m-94d254942e3a-dark .marker.cross{stroke:#a8a89e;}#m-94d254942e3a-dark svg{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;}#m-94d254942e3a-dark p{margin:0;}#m-94d254942e3a-dark .label{font-family:Inter,system-ui,-apple-system,sans-serif;color:#e8e6df;}#m-94d254942e3a-dark .cluster-label text{fill:#e8e6df;}#m-94d254942e3a-dark .cluster-label span{color:#e8e6df;}#m-94d254942e3a-dark .cluster-label span p{background-color:transparent;}#m-94d254942e3a-dark .label text,#m-94d254942e3a-dark span{fill:#e8e6df;color:#e8e6df;}#m-94d254942e3a-dark .node rect,#m-94d254942e3a-dark .node circle,#m-94d254942e3a-dark .node ellipse,#m-94d254942e3a-dark .node polygon,#m-94d254942e3a-dark .node path{fill:#23252a;stroke:#3f3f46;stroke-width:1px;}#m-94d254942e3a-dark .rough-node .label text,#m-94d254942e3a-dark .node .label text,#m-94d254942e3a-dark .image-shape .label,#m-94d254942e3a-dark .icon-shape .label{text-anchor:middle;}#m-94d254942e3a-dark .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#m-94d254942e3a-dark .rough-node .label,#m-94d254942e3a-dark .node .label,#m-94d254942e3a-dark .image-shape .label,#m-94d254942e3a-dark .icon-shape .label{text-align:center;}#m-94d254942e3a-dark .node.clickable{cursor:pointer;}#m-94d254942e3a-dark .root .anchor path{fill:#a8a89e!important;stroke-width:0;stroke:#a8a89e;}#m-94d254942e3a-dark .arrowheadPath{fill:rgba(255, 255, 255, 0);}#m-94d254942e3a-dark .edgePath .path{stroke:#a8a89e;stroke-width:1px;}#m-94d254942e3a-dark .flowchart-link{stroke:#a8a89e;fill:none;}#m-94d254942e3a-dark .edgeLabel{background-color:#1a1b1e;text-align:center;}#m-94d254942e3a-dark .edgeLabel p{background-color:#1a1b1e;}#m-94d254942e3a-dark .edgeLabel rect{opacity:0.5;background-color:#1a1b1e;fill:#1a1b1e;}#m-94d254942e3a-dark .labelBkg{background-color:rgba(26, 27, 30, 0.5);}#m-94d254942e3a-dark .cluster rect{fill:#2a2b2f;stroke:#3f3f46;stroke-width:1px;}#m-94d254942e3a-dark .cluster text{fill:#e8e6df;}#m-94d254942e3a-dark .cluster span{color:#e8e6df;}#m-94d254942e3a-dark div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:12px;background:#7c2d12;border:1px solid #fb923c;border-radius:2px;pointer-events:none;z-index:100;}#m-94d254942e3a-dark .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#e8e6df;}#m-94d254942e3a-dark rect.text{fill:none;stroke-width:0;}#m-94d254942e3a-dark .icon-shape,#m-94d254942e3a-dark .image-shape{background-color:#1a1b1e;text-align:center;}#m-94d254942e3a-dark .icon-shape p,#m-94d254942e3a-dark .image-shape p{background-color:#1a1b1e;padding:2px;}#m-94d254942e3a-dark .icon-shape .label rect,#m-94d254942e3a-dark .image-shape .label rect{opacity:0.5;background-color:#1a1b1e;fill:#1a1b1e;}#m-94d254942e3a-dark .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#m-94d254942e3a-dark .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#m-94d254942e3a-dark .node .neo-node{stroke:#3f3f46;}#m-94d254942e3a-dark [data-look="neo"].node rect,#m-94d254942e3a-dark [data-look="neo"].cluster rect,#m-94d254942e3a-dark [data-look="neo"].node polygon{stroke:url(#m-94d254942e3a-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-94d254942e3a-dark [data-look="neo"].node path{stroke:url(#m-94d254942e3a-dark-gradient);stroke-width:1px;}#m-94d254942e3a-dark [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-94d254942e3a-dark [data-look="neo"].node .neo-line path{stroke:#3f3f46;filter:none;}#m-94d254942e3a-dark [data-look="neo"].node circle{stroke:url(#m-94d254942e3a-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-94d254942e3a-dark [data-look="neo"].node circle .state-start{fill:#000000;}#m-94d254942e3a-dark [data-look="neo"].icon-shape .icon{fill:url(#m-94d254942e3a-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-94d254942e3a-dark [data-look="neo"].icon-shape .icon-neo path{stroke:url(#m-94d254942e3a-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-94d254942e3a-dark :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="m-94d254942e3a-dark_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-dark_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-dark_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-dark_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-dark_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-dark_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-dark_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-dark_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-dark_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-dark_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-dark_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="m-94d254942e3a-dark_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M146.97,265.5L154.509,268.833C162.048,272.167,177.125,278.833,188.164,282.167C199.203,285.5,206.203,285.5,209.703,285.5L213.203,285.5" id="m-94d254942e3a-dark-L_U_GA_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_U_GA_0" data-points="W3sieCI6MTQ2Ljk3MDAxNjg5MTg5MTksInkiOjI2NS41fSx7IngiOjE5Mi4yMDMxMjUsInkiOjI4NS41fSx7IngiOjIxNy4yMDMxMjUsInkiOjI4NS41fV0=" data-look="classic" marker-end="url(#m-94d254942e3a-dark_flowchart-v2-pointEnd)"/><path d="M419.359,281.993L423.526,281.848C427.693,281.703,436.026,281.414,443.693,281.27C451.359,281.125,458.359,281.125,461.859,281.125L465.359,281.125" id="m-94d254942e3a-dark-L_GA_RegA_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_GA_RegA_0" data-points="W3sieCI6NDE5LjM1OTM3NSwieSI6MjgxLjk5MjUxNzY2MDE4MDk3fSx7IngiOjQ0NC4zNTkzNzUsInkiOjI4MS4xMjV9LHsieCI6NDY5LjM1OTM3NSwieSI6MjgxLjEyNX1d" data-look="classic" marker-end="url(#m-94d254942e3a-dark_flowchart-v2-pointEnd)"/><path d="M395.715,334.25L403.822,339.354C411.93,344.458,428.145,354.667,455.072,359.771C482,364.875,519.641,364.875,565.663,364.875C611.685,364.875,666.089,364.875,705.182,366.999C744.276,369.123,768.06,373.371,779.952,375.496L791.844,377.62" id="m-94d254942e3a-dark-L_GA_RegB_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_GA_RegB_0" data-points="W3sieCI6Mzk1LjcxNTA1OTA1NTExODEsInkiOjMzNC4yNX0seyJ4Ijo0NDQuMzU5Mzc1LCJ5IjozNjQuODc1fSx7IngiOjU1Ny4yODEyNSwieSI6MzY0Ljg3NX0seyJ4Ijo3MjAuNDkyMTg3NSwieSI6MzY0Ljg3NX0seyJ4Ijo3OTUuNzgxMjUsInkiOjM3OC4zMjMwNzc2MTAwNzQxfV0=" data-look="classic" marker-end="url(#m-94d254942e3a-dark_flowchart-v2-pointEnd)"/><path d="M337.949,236.75L355.684,192.792C373.419,148.833,408.889,60.917,445.445,16.958C482,-27,519.641,-27,565.663,-27C611.685,-27,666.089,-27,722.449,-27C778.81,-27,837.128,-27,898.426,-27C959.724,-27,1024.003,-27,1084.016,17.539C1144.03,62.078,1199.778,151.156,1227.652,195.695L1255.526,240.234" id="m-94d254942e3a-dark-L_GA_RegC_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_GA_RegC_0" data-points="W3sieCI6MzM3Ljk0OTQzNzUsInkiOjIzNi43NX0seyJ4Ijo0NDQuMzU5Mzc1LCJ5IjotMjd9LHsieCI6NTU3LjI4MTI1LCJ5IjotMjd9LHsieCI6NzIwLjQ5MjE4NzUsInkiOi0yN30seyJ4Ijo4OTUuNDQ1MzEyNSwieSI6LTI3fSx7IngiOjEwODguMjgxMjUsInkiOi0yN30seyJ4IjoxMjU3LjY0ODMxMDcyNTE1MjIsInkiOjI0My42MjV9XQ==" data-look="classic" marker-end="url(#m-94d254942e3a-dark_flowchart-v2-pointEnd)"/><path d="M626.468,329.875L642.139,340.917C657.81,351.958,689.151,374.042,716.703,385.083C744.255,396.125,768.018,396.125,779.9,396.125L791.781,396.125" id="m-94d254942e3a-dark-L_RegA_RegB_0" class="edge-thickness-thick edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_RegA_RegB_0" data-points="W3sieCI6NjI2LjQ2ODQ5NTI0NDU2NTIsInkiOjMyOS44NzV9LHsieCI6NzIwLjQ5MjE4NzUsInkiOjM5Ni4xMjV9LHsieCI6Nzk1Ljc4MTI1LCJ5IjozOTYuMTI1fV0=" data-look="classic" marker-end="url(#m-94d254942e3a-dark_flowchart-v2-pointEnd)"/><path d="M795.781,420.336L783.233,423.384C770.685,426.432,745.589,432.529,714.738,417.915C683.887,403.301,647.282,367.977,628.98,350.315L610.677,332.653" id="m-94d254942e3a-dark-L_RegB_RegA_0" class="edge-thickness-thick edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_RegB_RegA_0" data-points="W3sieCI6Nzk1Ljc4MTI1LCJ5Ijo0MjAuMzM1NjE0NDUwMjk5Mn0seyJ4Ijo3MjAuNDkyMTg3NSwieSI6NDM4LjYyNX0seyJ4Ijo2MDcuNzk4OTIxMTMwOTUyNCwieSI6MzI5Ljg3NX1d" data-look="classic" marker-end="url(#m-94d254942e3a-dark_flowchart-v2-pointEnd)"/><path d="M649.203,281.125L661.085,281.125C672.966,281.125,696.729,281.125,737.77,281.125C778.81,281.125,837.128,281.125,898.426,281.125C959.724,281.125,1024.003,281.125,1071.004,281.125C1118.005,281.125,1147.729,281.125,1162.591,281.125L1177.453,281.125" id="m-94d254942e3a-dark-L_RegA_RegC_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_RegA_RegC_0" data-points="W3sieCI6NjQ1LjIwMzEyNSwieSI6MjgxLjEyNX0seyJ4Ijo3MjAuNDkyMTg3NSwieSI6MjgxLjEyNX0seyJ4Ijo4OTUuNDQ1MzEyNSwieSI6MjgxLjEyNX0seyJ4IjoxMDg4LjI4MTI1LCJ5IjoyODEuMTI1fSx7IngiOjExODEuNDUzMTI1LCJ5IjoyODEuMTI1fV0=" data-look="classic" marker-start="url(#m-94d254942e3a-dark_flowchart-v2-pointStart)" marker-end="url(#m-94d254942e3a-dark_flowchart-v2-pointEnd)"/><path d="M999.109,396.125L1013.971,396.125C1028.833,396.125,1058.557,396.125,1094.506,383.55C1130.454,370.975,1172.627,345.824,1193.714,333.249L1214.8,320.674" id="m-94d254942e3a-dark-L_RegB_RegC_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_RegB_RegC_0" data-points="W3sieCI6OTk1LjEwOTM3NSwieSI6Mzk2LjEyNX0seyJ4IjoxMDg4LjI4MTI1LCJ5IjozOTYuMTI1fSx7IngiOjEyMTguMjM1OTAzNTMyNjA4NywieSI6MzE4LjYyNX1d" data-look="classic" marker-start="url(#m-94d254942e3a-dark_flowchart-v2-pointStart)" marker-end="url(#m-94d254942e3a-dark_flowchart-v2-pointEnd)"/><path d="M591.049,232.375L612.623,201.229C634.197,170.083,677.344,107.792,710.916,76.646C744.487,45.5,768.482,45.5,780.479,45.5L792.477,45.5" id="m-94d254942e3a-dark-L_RegA_RAW_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_RegA_RAW_0" data-points="W3sieCI6NTkxLjA0OTAzMDE3MjQxMzgsInkiOjIzMi4zNzV9LHsieCI6NzIwLjQ5MjE4NzUsInkiOjQ1LjV9LHsieCI6Nzk2LjQ3NjU2MjUsInkiOjQ1LjV9XQ==" data-look="classic" marker-end="url(#m-94d254942e3a-dark_flowchart-v2-pointEnd)"/><path d="M607.799,232.375L626.581,214.25C645.363,196.125,682.928,159.875,714.758,146.085C746.589,132.295,772.685,140.965,785.734,145.3L798.782,149.635" id="m-94d254942e3a-dark-L_RegA_Deg_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_RegA_Deg_0" data-points="W3sieCI6NjA3Ljc5ODkyMTEzMDk1MjQsInkiOjIzMi4zNzV9LHsieCI6NzIwLjQ5MjE4NzUsInkiOjEyMy42MjV9LHsieCI6ODAyLjU3ODEyNSwieSI6MTUwLjg5NjU2MjY5NTM2NDgyfV0=" data-look="classic" marker-end="url(#m-94d254942e3a-dark_flowchart-v2-pointEnd)"/><path d="M802.578,187.058L788.897,187.84C775.216,188.622,747.854,190.186,706.971,190.968C666.089,191.75,611.685,191.75,565.663,191.75C519.641,191.75,482,191.75,442.167,191.75C402.333,191.75,360.307,191.75,318.281,191.75C276.255,191.75,234.229,191.75,206.024,195.016C177.819,198.282,163.434,204.814,156.242,208.08L149.05,211.346" id="m-94d254942e3a-dark-L_Deg_U_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Deg_U_0" data-points="W3sieCI6ODAyLjU3ODEyNSwieSI6MTg3LjA1ODExODI0NTk1ODc1fSx7IngiOjcyMC40OTIxODc1LCJ5IjoxOTEuNzV9LHsieCI6NTU3LjI4MTI1LCJ5IjoxOTEuNzV9LHsieCI6NDQ0LjM1OTM3NSwieSI6MTkxLjc1fSx7IngiOjMxOC4yODEyNSwieSI6MTkxLjc1fSx7IngiOjE5Mi4yMDMxMjUsInkiOjE5MS43NX0seyJ4IjoxNDUuNDA3Njg5MTQ0NzM2ODUsInkiOjIxM31d" data-look="classic" marker-end="url(#m-94d254942e3a-dark_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_U_GA_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_GA_RegA_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_GA_RegB_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_GA_RegC_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(720.4921875, 396.125)"><g class="label" data-id="L_RegA_RegB_0" transform="translate(-50.2890625, -11.25)"><foreignObject width="100.578125" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>sync для tier-1</p></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(692.02177, 411.15079)"><g class="label" data-id="L_RegB_RegA_0" transform="translate(-50.2890625, -11.25)"><foreignObject width="100.578125" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>sync для tier-1</p></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(895.4453125, 281.125)"><g class="label" data-id="L_RegA_RegC_0" transform="translate(-68.171875, -11.25)"><foreignObject width="136.34375" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>async для каталога</p></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(1088.28125, 396.125)"><g class="label" data-id="L_RegB_RegC_0" transform="translate(-68.171875, -11.25)"><foreignObject width="136.34375" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>async для каталога</p></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_RegA_RAW_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_RegA_Deg_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Deg_U_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="m-94d254942e3a-dark-flowchart-U-0" data-look="classic" transform="translate(87.6015625, 239.25)"><rect class="basic label-container" style="" x="-79.6015625" y="-26.25" width="159.203125" height="52.5"/><g class="label" style="" transform="translate(-49.6015625, -11.25)"><rect/><foreignObject width="99.203125" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Пользователь</p></span></div></foreignObject></g></g><g class="node default" id="m-94d254942e3a-dark-flowchart-GA-1" data-look="classic" transform="translate(318.28125, 285.5)"><rect class="basic label-container" style="" x="-101.078125" y="-48.75" width="202.15625" height="97.5"/><g class="label" style="" transform="translate(-71.078125, -33.75)"><rect/><foreignObject width="142.15625" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Geo-Anycast<br />+ Global LB<br />health-aware routing</p></span></div></foreignObject></g></g><g class="node default" id="m-94d254942e3a-dark-flowchart-RegA-3" data-look="classic" transform="translate(557.28125, 281.125)"><rect class="basic label-container" style="" x="-87.921875" y="-48.75" width="175.84375" height="97.5"/><g class="label" style="" transform="translate(-57.921875, -33.75)"><rect/><foreignObject width="115.84375" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Регион A<br />Search + Redis +<br />ES + Postgres</p></span></div></foreignObject></g></g><g class="node default" id="m-94d254942e3a-dark-flowchart-RegB-5" data-look="classic" transform="translate(895.4453125, 396.125)"><rect class="basic label-container" style="" x="-99.6640625" y="-37.5" width="199.328125" height="75"/><g class="label" style="" transform="translate(-69.6640625, -22.5)"><rect/><foreignObject width="139.328125" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Регион B<br />полная копия стека</p></span></div></foreignObject></g></g><g class="node default" id="m-94d254942e3a-dark-flowchart-RegC-7" data-look="classic" transform="translate(1281.1171875, 281.125)"><rect class="basic label-container" style="" x="-99.6640625" y="-37.5" width="199.328125" height="75"/><g class="label" style="" transform="translate(-69.6640625, -22.5)"><rect/><foreignObject width="139.328125" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Регион C<br />полная копия стека</p></span></div></foreignObject></g></g><g class="node default" id="m-94d254942e3a-dark-flowchart-RAW-17" data-look="classic" transform="translate(895.4453125, 45.5)"><rect class="basic label-container" style="" x="-98.96875" y="-37.5" width="197.9375" height="75"/><g class="label" style="" transform="translate(-68.96875, -22.5)"><rect/><foreignObject width="137.9375" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Repair-aware Cache<br />per-region</p></span></div></foreignObject></g></g><g class="node default" id="m-94d254942e3a-dark-flowchart-Deg-19" data-look="classic" transform="translate(895.4453125, 181.75)"><rect class="basic label-container" style="" x="-92.8671875" y="-48.75" width="185.734375" height="97.5"/><g class="label" style="" transform="translate(-62.8671875, -33.75)"><rect/><foreignObject width="125.734375" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Degradation Layer<br />ranking упал —<br />отдаём базовое</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="m-94d254942e3a-dark-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="m-94d254942e3a-dark-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><linearGradient id="m-94d254942e3a-dark-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#3f3f46" stop-opacity="1"/><stop offset="100%" stop-color="#3f3f46" stop-opacity="1"/></linearGradient></svg>
</div>
</figure><p><strong>Числовые прикидки:</strong></p>
<ul>
<li><strong>Capacity.</strong> 30k RPS пика делятся между 3 регионами <code>~по 10k RPS</code> нормально. Но <strong>каждый регион должен один переварить 100% трафика</strong> при отказе двух других — то есть sized под <code>30–40k RPS</code>. Это утроение инфраструктуры по сравнению с одним регионом 99.9%, плюс запас.</li>
<li><strong>Кросс-региональная синхронизация индексов.</strong> ES → Kafka MirrorMaker (или managed cross-region streaming) → ES в каждом регионе. Lag <code>5–30 секунд</code> между регионами в нормальном режиме, <code>1–3 минуты</code> при региональной сетевой деградации. Eventually consistent модель данных — для поиска приемлемо, для цен/наличия (freshness-SLI) — узкое место, требующее отдельной стратегии (часто — fetch цены при клике в карточку из локального region-БД).</li>
<li><strong>Repair-aware кэш.</strong> Когда регион вышел из деградации и снова healthy, кэш в нём может содержать <code>«грязные»</code> ключи — данные, менявшиеся в других регионах, но не доехавшие. Решение: каждый ключ в кэше помечен суффиксом версии данных (<code>hash</code> или <code>LSN</code>); при возврате региона — проактивный прогрев топовых ключей со свежими версиями. Это отдельный сервис, обычно in-house.</li>
<li><strong>Graceful degradation.</strong> Если ranking-сервис упал — поиск отдаёт базовое ранжирование (popularity + recency) без персонализации. Если упал autocomplete — прячем подсказки, оставляя ввод. Если упал ES — отдаём кэш-результаты + предупреждение «возможно, не самые свежие». Каждый из этих режимов — отдельный код-path и отдельный SLI.</li>
<li><strong>Failover.</strong> Автоматический на уровне geo-anycast / global LB, RTO <code>5–30 секунд</code> на регион. Health-чеки агрегируют SLI критичного пути, а не пинг сервера.</li>
<li><strong>RPO.</strong> Околонулевой для критичных данных (заказы, корзина) через synchronous replication между двумя регионами + async на третий. Для каталога/индекса — <code>до 1 минуты</code>.</li>
<li><strong>Алерты.</strong> Multi-window multi-burn-rate с поджатыми окнами: быстрая пара <code>2 мин + 1 час</code> с threshold <code>36×</code> (для tier-1 порог берут агрессивнее, чем 14.4× — иначе быстрый алерт догонит инцидент уже после исчерпания бюджета) + медленная пара <code>15 мин + 3 часа</code> с threshold <code>~10×</code> для затяжной деградации. Auto-remediation для известных классов: автоматический drain региона при превышении burn-rate, автоматический rollback деплоя.</li>
</ul>
<p><strong>Что добавилось по сравнению с 99.9%:</strong></p>
<ul>
<li>Multi-region active-active — потому что 1 минута 27 секунд бюджета на пике не покрывают ни один региональный инцидент (4 мин 20 с в среднем — тоже).</li>
<li>Repair-aware кэш — потому что после возврата региона данные могут разойтись, и без проактивного прогрева накопится freshness-долг, съедающий SLI-4.</li>
<li>Graceful degradation — потому что без неё любой отказ зависимости (ranking, persona) забирает весь бюджет.</li>
<li>Auto-remediation — потому что человек физически не успевает посмотреть пейдж за 1 мин 27 с пикового бюджета, не то что разобраться.</li>
<li>Канареечный rollout с автоматическим откатом по burn-rate — каждый деплой иначе ставит весь бюджет.</li>
</ul>
<p><strong>Что намеренно НЕ делаем (и здесь это особенно важно):</strong></p>
<ul>
<li>Не идём в <code>99.999%</code> без очень сильного бизнес-обоснования. 26 секунд в месяц требуют существенно более сложной модели резервирования, чем 99.99%: multi-cloud или multi-provider, независимые DNS, частично независимые кодовые базы, подходы из telecom/aerospace. Это часто <strong>дешевле решить через UX</strong> — например, кэшированием выдачи на клиенте на минуту, чтобы из 100% даунтайма пользователь увидел только новые сессии.</li>
</ul>
<p><strong>Стоимость:</strong> <strong>15–25× baseline</strong> в инфраструктуре, <strong>8–10× baseline</strong> в людях (24/7 SRE, регулярные game days, отдельная команда reliability engineering).</p>
<h3 id="сводная-таблица-slo-как-бюджет-на-сложность">Сводная таблица: SLO как бюджет на сложность</h3>
<table>
  <thead>
      <tr>
          <th>Аспект</th>
          <th>99.0%</th>
          <th>99.9%</th>
          <th>99.99%</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Бюджет на пике (30 дней)</td>
          <td>~2 ч 24 мин</td>
          <td>~14 мин 26 с</td>
          <td>~1 мин 27 с</td>
      </tr>
      <tr>
          <td>Бюджет при средней нагрузке (30 дней)</td>
          <td>~7 ч 12 мин</td>
          <td>~43 мин</td>
          <td>~4 мин 20 с</td>
      </tr>
      <tr>
          <td>Бюджет в запросах (30 дней)</td>
          <td>~260M</td>
          <td>~26M</td>
          <td>~2.6M</td>
      </tr>
      <tr>
          <td>Регионы</td>
          <td>1</td>
          <td>1 (active-passive AZ)</td>
          <td>3+ (active-active)</td>
      </tr>
      <tr>
          <td>Поисковый индекс</td>
          <td><code>pg_trgm</code> в Postgres</td>
          <td>Elasticsearch (8–12 нод)</td>
          <td>ES per region</td>
      </tr>
      <tr>
          <td>Кэш</td>
          <td>In-memory LRU на app</td>
          <td>Redis cluster (~50 GB)</td>
          <td>Repair-aware Redis × N</td>
      </tr>
      <tr>
          <td>Индексирование</td>
          <td>Триггеры в БД</td>
          <td>CDC + Kafka</td>
          <td>Cross-region MirrorMaker</td>
      </tr>
      <tr>
          <td>Failover</td>
          <td>Ручной, RTO 30–60 мин</td>
          <td>Авто между AZ, RTO 1–3 мин</td>
          <td>Авто между регионами, RTO 5–30 с</td>
      </tr>
      <tr>
          <td>RPO</td>
          <td>~5 мин</td>
          <td>~30 с</td>
          <td>~0 для tier-1 / ~1 мин для каталога</td>
      </tr>
      <tr>
          <td>Алерты</td>
          <td>На симптомы</td>
          <td>Multi-window burn-rate</td>
          <td>+ Auto-remediation</td>
      </tr>
      <tr>
          <td>Деплои</td>
          <td>Без особых процедур</td>
          <td>Постепенный rollout</td>
          <td>Канарейка + auto-откат</td>
      </tr>
      <tr>
          <td>Graceful degradation</td>
          <td>Нет</td>
          <td>Частично</td>
          <td>Полная</td>
      </tr>
      <tr>
          <td><strong>Инфраструктура (× baseline)</strong></td>
          <td><strong>1×</strong></td>
          <td><strong>4–6×</strong></td>
          <td><strong>15–25×</strong></td>
      </tr>
      <tr>
          <td><strong>Люди (× baseline)</strong></td>
          <td><strong>1×</strong></td>
          <td><strong>2–3×</strong></td>
          <td><strong>8–10×</strong></td>
      </tr>
      <tr>
          <td>Когда оправдано</td>
          <td>Внутренние tools, MVP, не-критичные пути</td>
          <td>Production e-commerce средней руки</td>
          <td>Tier-1 в крупном бизнесе</td>
      </tr>
  </tbody>
</table>
<h3 id="главный-вывод-раздела">Главный вывод раздела</h3>
<p>Один и тот же кейс на трёх SLO — это <strong>три разные инженерные задачи</strong>. Не «та же задача с разными настройками», а с разной топологией, разными технологиями, разной операционной моделью, разной стоимостью.</p>
<p>Из этого следуют две вещи, которые часто упускают:</p>
<ol>
<li><strong>Поднять SLO задним числом — это переписать систему</strong>, а не «добавить мониторинга». Если архитектура построена под 99.0%, поднять её до 99.99% означает: добавить регионы, переписать индексирование под cross-region, ввести graceful degradation, перепроектировать кэш. Не «настройка пары флагов» — <strong>рефакторинг порядка половины кодовой базы</strong>.</li>
<li><strong>Снизить SLO задним числом</strong> освобождает бюджет, но <strong>не возвращает потраченных денег</strong>. Если ты построил под 99.99%, а реально нужно 99.9% — лишний регион уже куплен, репликация уже настроена, команда SRE уже нанята. Снижение SLO в этом случае имеет смысл только перед следующим циклом капекса.</li>
</ol>
<p>Поэтому SLO выбирается <strong>до</strong> дизайна, а не после. И выбирается <strong>с участием бизнеса</strong> — потому что цифра в нём в итоге привязана к деньгам, а не к самочувствию инженеров.</p>
<h2 id="sla-что-уходит-наружу">SLA: что уходит наружу</h2>
<p>Третий и последний термин «троицы» — <strong>SLA (Service Level Agreement)</strong>. Это контракт с пользователем (или клиентом, партнёром, регулятором), оформленный обычно юридически, с финансовыми санкциями за нарушение.</p>
<p>Принципиальное отличие от SLO:</p>
<table>
  <thead>
      <tr>
          <th></th>
          <th>SLO</th>
          <th>SLA</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Кому обещаем</td>
          <td>Самим себе (внутри команды/компании)</td>
          <td>Внешнему пользователю или клиенту</td>
      </tr>
      <tr>
          <td>Последствия нарушения</td>
          <td>Перераспределение бюджета на reliability, freeze</td>
          <td>Финансовые санкции, отток, репутация</td>
      </tr>
      <tr>
          <td>Гранулярность</td>
          <td>Может быть сколько угодно (по шагу, по сегменту)</td>
          <td>Обычно одно-два простых числа</td>
      </tr>
      <tr>
          <td>Частота пересмотра</td>
          <td>Раз в квартал</td>
          <td>Раз в год или реже</td>
      </tr>
  </tbody>
</table>
<h3 id="главное-правило-sla--slo--запас">Главное правило: SLA ≤ SLO − запас</h3>
<p>Самая частая ошибка — поставить SLA равным SLO. Например, инженеры обещают себе 99.99%, и юристы пишут пользователю «гарантируем 99.99%». В этом случае любое попадание в нижнюю границу SLO — уже автоматически нарушение SLA.</p>
<p>Правильно: между SLO и SLA должен быть <strong>запас</strong>, обычно один-два разряда <code>9</code>.</p>
<ul>
<li>SLO 99.99% → SLA 99.9% или 99.95%.</li>
<li>SLO 99.9% → SLA 99.5%.</li>
</ul>
<p>Запас не стоит ничего — это просто разница между «что мы хотим внутри» и «что мы готовы юридически защищать снаружи».</p>
<h3 id="и-ещё-одно-важное">И ещё одно важное</h3>
<p>SLA пишется не на ту же метрику, что SLO. SLA обычно — это <strong>availability в чистом виде</strong> (грубое «отвечает / не отвечает»). SLO — набор тонких индикаторов (latency, freshness, correctness). Ты внутри живёшь на сложной картине из 4–8 SLI, наружу выдаёшь одну простую цифру с запасом.</p>
<h2 id="golden-signals-red-use--какую-призму-брать-и-когда">Golden Signals, RED, USE — какую призму брать и когда</h2>
<p>Кейс выше показал три разные системы под три SLO. Прежде чем переходить к разговору про error budget как арбитр в спорах, важно понять — а каким набором метрик мы вообще смотрим на эти системы. В SRE-сообществе живут три популярных набора-призмы для метрик:</p>
<ul>
<li><strong>Golden Signals</strong> — <code>Latency, Traffic, Errors, Saturation</code>. Универсальный набор для пользовательских сервисов. Введён Rob Ewaschuk и закреплён в Google SRE Book (глава «Monitoring Distributed Systems», O&rsquo;Reilly, 2016).</li>
<li><strong>RED</strong> — <code>Rate, Errors, Duration</code>. Подмножество Golden Signals, ориентированное на запрос-ответные сервисы. Введён Tom Wilkie (Weaveworks, ныне Grafana Labs) в докладе «The RED Method» (2017).</li>
<li><strong>USE</strong> — <code>Utilization, Saturation, Errors</code>. Для ресурсов: CPU, диск, память, сеть. Введён Brendan Gregg в «Systems Performance» (2-е изд., 2020) и серии постов на brendangregg.com (2012+).</li>
</ul>
<p>Эти призмы часто валят в одну кучу и спорят, какая «правильная». Спор бессмысленный — они отвечают на <strong>разные вопросы</strong>.</p>
<h3 id="golden-signals--самая-полная-призма-для-сервиса">Golden Signals — самая полная призма для сервиса</h3>
<p>Если ты только начинаешь и не знаешь, что меряет — начни с Golden Signals на каждый твой сервис:</p>
<ul>
<li><strong>Latency.</strong> Сколько времени занял успешный запрос (отдельно — неуспешный, потому что медленный 500 искажает картину).</li>
<li><strong>Traffic.</strong> Сколько запросов обрабатываем (RPS, qps, events/sec).</li>
<li><strong>Errors.</strong> Доля «плохих» — 5xx, таймауты, протокольные ошибки, неуспешные заказы.</li>
<li><strong>Saturation.</strong> Насколько ресурс заполнен — очередь, пул соединений, утилизация worker-ов.</li>
</ul>
<p>В нашем кейсе для search-сервиса Golden Signals разворачиваются так:</p>
<ul>
<li><strong>Latency:</strong> P50/P95/P99 на эндпоинт <code>/search</code>, разбитые по типу запроса (autocomplete vs full search).</li>
<li><strong>Traffic:</strong> RPS на <code>/search</code>, отдельно по регионам.</li>
<li><strong>Errors:</strong> доля 5xx + таймаутов к ES + ошибок ranking-сервиса.</li>
<li><strong>Saturation:</strong> размер очереди в Kafka-consumer индексирования, пул коннектов в ES, hit rate Redis.</li>
</ul>
<p>Эти четыре сразу дают <strong>верхнеуровневую картину здоровья сервиса</strong>. SLI ты выбираешь из них (обычно — Latency и Errors), но мониторить нужно все четыре.</p>
<h3 id="red--тот-же-набор-проще-запомнить">RED — тот же набор, проще запомнить</h3>
<p>RED (<code>Rate, Errors, Duration</code>) — это Golden Signals минус <code>Saturation</code>. Удобный мнемоник, особенно для request/response-сервисов: каждый эндпоинт обязательно имеет три метрики и хотя бы один дашборд по ним.</p>
<p>Когда брать RED вместо Golden Signals: если ты делаешь дашборд per-endpoint в большом сервисе и не хочешь ставить четыре графика на каждый эндпоинт. Saturation — ресурсная метрика, и она часто живёт отдельно (на дашборде ресурсов или инфраструктуры), а не на дашборде эндпоинтов.</p>
<h3 id="use--призма-для-ресурсов-не-для-сервисов">USE — призма для ресурсов, не для сервисов</h3>
<p>USE (<code>Utilization, Saturation, Errors</code>) — про <strong>ресурс</strong>, не про сервис. Когда мерить:</p>
<ul>
<li><strong>CPU</strong> — utilization = % busy, saturation = run queue, errors = throttling.</li>
<li><strong>Диск</strong> — utilization = busy time, saturation = await, errors = bad sectors / IO errors.</li>
<li><strong>Сеть</strong> — utilization = bandwidth %, saturation = drops, errors = retransmits.</li>
<li><strong>Пул соединений</strong> — utilization = used/max, saturation = очередь ожидания, errors = таймауты.</li>
</ul>
<p>USE — для <strong>диагностики</strong>, не для SLO. Никогда не делай SLO на CPU utilization напрямую — это служебный сигнал. Но USE-метрики бесценны, когда burn-rate-алерт сработал и нужно быстро понять, <strong>где</strong> в стеке давит.</p>
<h3 id="когда-какую-призму-брать--простое-правило">Когда какую призму брать — простое правило</h3>
<table>
  <thead>
      <tr>
          <th>Ситуация</th>
          <th>Призма</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Дашборд верхнего уровня по сервису</td>
          <td>Golden Signals</td>
      </tr>
      <tr>
          <td>Дашборд per-endpoint в большом сервисе</td>
          <td>RED</td>
      </tr>
      <tr>
          <td>Дашборд ресурса (CPU, диск, БД-пул)</td>
          <td>USE</td>
      </tr>
      <tr>
          <td>Выбор кандидатов в SLI</td>
          <td>Golden Signals → Latency и Errors</td>
      </tr>
      <tr>
          <td>Диагностика после burn-rate-алерта</td>
          <td>USE — где жмёт по ресурсам</td>
      </tr>
  </tbody>
</table>
<h3 id="главное-смещение">Главное смещение</h3>
<p>Призмы не противоречат — они <strong>дополняют</strong>. У зрелой команды есть все три уровня дашбордов:</p>
<ul>
<li><strong>Верхний</strong> — Golden Signals + дашборд SLI/SLO с burn-rate. Заходишь и сразу видишь, всё ли в порядке с пользовательским опытом.</li>
<li><strong>Средний</strong> — RED по эндпоинтам. Заходишь, когда верхний показывает деградацию, и видишь, какой эндпоинт вносит вклад.</li>
<li><strong>Нижний</strong> — USE по ресурсам. Заходишь, когда RED показывает, какой эндпоинт болит, и нужно понять, в каком ресурсе упёрлись.</li>
</ul>
<h2 id="error-budget-как-арбитр-в-спорах-фича-vs-рефакторинг">Error budget как арбитр в спорах «фича vs рефакторинг»</h2>
<p>Самый недооценённый эффект от грамотного SLO — это не алерты и не отчёты. Это то, что бюджет ошибок становится <strong>валютой в архитектурных спорах</strong>, и решения принимаются на цифрах, а не на ощущениях.</p>
<h3 id="классический-спор-без-бюджета">Классический спор без бюджета</h3>
<p>Сценарий, знакомый каждому, кто работал в продуктовой команде дольше года:</p>
<blockquote><p><strong>Продакт:</strong> «Нам нужно срочно выкатить персонализированную выдачу до Чёрной пятницы».<br>
<strong>SRE:</strong> «Мы только что прошли через два инцидента из-за деплоя. Я хочу заморозить деплои на неделю и провести post-mortem».<br>
<strong>Продакт:</strong> «Каждая неделя задержки — это $500k недополученной выручки».<br>
<strong>SRE:</strong> «Каждый инцидент — это репутация».</p>
</blockquote><p>Без бюджета этот спор решается <strong>властью</strong>. Кто громче, выше по иерархии или ближе к CEO — тот побеждает. Решения принимаются эмоционально, обе стороны выходят с ощущением, что их аргументы недослушаны.</p>
<h3 id="тот-же-спор-с-бюджетом">Тот же спор с бюджетом</h3>
<blockquote><p><strong>Продакт:</strong> «Хочу выкатить персонализацию до BF».<br>
<strong>SRE:</strong> «Бюджет на этот месяц — 26M запросов. За последние две недели мы сожгли 22M на двух инцидентах. У нас осталось 4M на оставшиеся 16 дней. Вот burn-rate-график за неделю».<br>
<strong>Продакт:</strong> «Сколько бюджета съедает выкатка персонализации?»<br>
<strong>SRE:</strong> «По прошлым выкаткам сопоставимого риска — медианно 3–4M запросов на постепенный rollout. То есть канарейка съест от 75% до 100% оставшегося бюджета. Если что-то пойдёт не так — превышаем SLO до конца окна».<br>
<strong>Продакт:</strong> «Сколько ждать, пока бюджет восстановится?»<br>
<strong>SRE:</strong> «Окно rolling, считается на последних 30 днях — каждые сутки самые старые сутки выпадают, новые входят. Самые тяжёлые инциденты были 28 и 25 дней назад: через 2–5 дней они выпадут из окна, и мы откатимся к ~10M свободного бюджета без всяких новых усилий».<br>
<strong>Продакт:</strong> «До BF — 24 дня. Подождём 5 дней, потом выкатываем канарейку — рискуем уже на восстановленном бюджете, а не на остатках от инцидентов».</p>
</blockquote><p>Спор кончился за 5 минут, без эмоций, на цифрах. Это и есть «бюджет как валюта»: он переводит инженерное «надо подождать» и продуктовое «надо быстрее» в <strong>единицу измерения, значимую обеим сторонам</strong>.</p>
<p>Это сводится к трём операционным следствиям, которые я уже разбирал в Шаге 4 как «на что тратится бюджет»: решение «деплоить vs морозить», переключение на reliability при систематическом сгорании, осознанная трата бюджета на учения и эксперименты. Здесь добавляется только одно: каждое из этих следствий теперь становится <strong>цифровым аргументом в диалоге</strong>, а не «инженерным интуитивным решением».</p>
<h3 id="что-разрушает-бюджет-как-арбитр">Что разрушает «бюджет как арбитр»</h3>
<ul>
<li><strong>Несогласованный SLO.</strong> Если бюджет в глазах продакта — «инженерная штука», он не примет его как аргумент. SLO нужно <strong>согласовывать</strong> с продуктом, а не объявлять.</li>
<li><strong>SLO без явного оперативного следствия.</strong> Если «бюджет сгорел» не запускает freeze автоматически, это просто график на дашборде. Должна быть <strong>записанная политика</strong>, что делать.</li>
<li><strong>Слишком жёсткое SLO.</strong> Если SLO нереалистичный («99.99% на сервисе, который объективно может только 99.9%»), бюджет всё время в минусе, и команда привыкает его игнорировать. Лучше реалистичный SLO с дисциплиной, чем красивая цифра, в которую никто не верит.</li>
</ul>
<p>Бюджет — это не магический инструмент, а <strong>дисциплина</strong>. Он работает, если команда договорилась его соблюдать. Не работает — если нет.</p>
<h2 id="типичные-ошибки-выбора-slislo-и-чек-лист">Типичные ошибки выбора SLI/SLO и чек-лист</h2>
<p>Соберу в один блок самые частые ошибки, которые ломают SLO-практику. Часть из них уже разобрана в основных разделах — в этом блоке они сведены в одну строку для самопроверки. Развёрнутые контрпримеры — в соответствующих главах выше.</p>
<h3 id="ошибка-1-sli--всё-что-не-5xx">Ошибка 1. SLI = «всё, что не 5xx»</h3>
<p><strong>Правильно:</strong> SLI — это <code>success AND fast</code>, и оба критерия записаны явно. Полный разбор — в Шаге 3 (про «хорошее событие»).</p>
<h3 id="ошибка-2-slo-по-системе-вместо-slo-по-шагу-пути">Ошибка 2. SLO «по системе» вместо SLO «по шагу пути»</h3>
<p><strong>Правильно:</strong> SLO живёт на каждом шаге критичного пути, а не на сервисе в целом. Развёрнуто — в Шаге 1 (ловушка «среднего по системе»).</p>
<h3 id="ошибка-3-slo-без-error-budget-policy">Ошибка 3. SLO без error budget policy</h3>
<p>SLO написано, бюджет считается, но что делать, когда бюджет сгорел — не записано. В итоге команда живёт в режиме «дашборд красный, ну ладно, продолжаем выкатку».</p>
<p><strong>Правильно:</strong> записанная политика: при превышении burn-rate <code>X×</code> за окно <code>Y</code> минут — freeze деплоев до конца окна / привлечение reliability-команды / эскалация. Без процедуры SLO — это украшение. Развёрнуто — в разделе «Что разрушает „бюджет как арбитр“».</p>
<h3 id="ошибка-4-slo--sla">Ошибка 4. SLO = SLA</h3>
<p><strong>Правильно:</strong> между SLO и SLA — запас один-два разряда <code>9</code>. Подробнее — в разделе «SLA: что уходит наружу».</p>
<h3 id="ошибка-5-среднее-вместо-перцентилей">Ошибка 5. Среднее вместо перцентилей</h3>
<p><strong>Правильно:</strong> SLI на latency — это перцентиль (P95/P99), не среднее. Развёрнуто — в Шаге 3, блок «Что мы НЕ берём как SLI».</p>
<h3 id="ошибка-6-sli-на-cpumemory-utilization">Ошибка 6. SLI на CPU/Memory utilization</h3>
<p><strong>Правильно:</strong> SLI — на пользовательских следствиях (latency, errors). Утилизация — служебная метрика для USE-дашборда. Развёрнуто — в Шаге 3, блок «Что мы НЕ берём как SLI».</p>
<h3 id="ошибка-7-слишком-много-sli">Ошибка 7. Слишком много SLI</h3>
<p>«У нас 50 SLI на сервис» — означает, что SLI никто не читает, и алерты по ним — шум. SLI должен фокусировать внимание, а не размывать его.</p>
<p>Маленькое терминологическое уточнение, без которого пункт читается двусмысленно: <strong>«сервис» здесь — пользовательский сервис в смысле CUJ</strong>, а не каждый микросервис в твоей архитектуре. На один CUJ (поиск каталога) — 4–8 SLI; на ranking-микросервис, который обслуживает этот же CUJ, не нужно отдельно вешать ещё 4–8. Иначе «50 SLI» получаются арифметически — суммой по микросервисам, — и читать их никто не будет.</p>
<p><strong>Правильно:</strong> 4–8 SLI на пользовательский сервис (CUJ), привязанных к ключевым шагам пути. Если хочется больше — это, скорее всего, сигнал, что внутри одного «сервиса» спрятаны два CUJ, и его пора разделить. Развёрнуто — в Шаге 3, блок «Конкретные SLI для нашего кейса».</p>
<h3 id="ошибка-8-slo-выбран-копированием">Ошибка 8. SLO выбран копированием</h3>
<p>«У Google 99.99%, у нас тоже будет». Без разговора с бизнесом, без расчёта стоимости, без понимания, тянет ли архитектура.</p>
<p><strong>Правильно:</strong> SLO выбирается из двух чисел — что <strong>окупается</strong> (бизнес) и что <strong>достижимо</strong> (архитектура). Между ними может быть зазор — он отражает либо недоинвест в reliability, либо переинвест в обещания.</p>
<h3 id="ошибка-9-slo-не-пересматривается">Ошибка 9. SLO не пересматривается</h3>
<p>Поставили SLO 99.9% год назад, написали в Confluence, забыли. Бизнес-контекст изменился, нагрузка выросла в 10 раз, продукт перешёл в зрелую фазу — SLO остался прежним.</p>
<p><strong>Правильно:</strong> SLO пересматривается раз в квартал минимум, в idle-режиме — раз в полгода. Каждый пересмотр — короткий ритуал «изменилось ли что-то в бизнесе или в системе, что меняет нужное число».</p>
<h3 id="ошибка-10-slo-выбран-без-учёта-зависимостей">Ошибка 10. SLO выбран без учёта зависимостей</h3>
<p>Сервис обещает 99.99%, но критически зависит от внешнего сервиса с 99.5%. Математика: твой SLO не может быть выше произведения SLO твоих критичных зависимостей.</p>
<p><strong>Правильно:</strong> при выборе SLO учитывай <strong>dependency budget</strong>. Если у тебя 3 последовательные критичные зависимости с 99.9% каждая, твой достижимый максимум — <code>~99.7%</code>. Для опциональных или параллельных зависимостей формула мягче — но любую цепочку нужно явно проговорить.</p>
<h3 id="чек-лист-10-вопросов-до-утверждения-slo">Чек-лист: 10 вопросов до утверждения SLO</h3>
<p>Если ответ «нет» хотя бы на один — SLO ещё не готов.</p>
<ul>
<li><input disabled="" type="checkbox"> Привязан ли SLO к конкретному шагу критичного пути, а не к сервису целиком?</li>
<li><input disabled="" type="checkbox"> Прописаны ли числитель, знаменатель и окно агрегации?</li>
<li><input disabled="" type="checkbox"> Пройдён ли тест «5xx за 5 секунд = плохое событие»?</li>
<li><input disabled="" type="checkbox"> Используется ли перцентиль, а не среднее?</li>
<li><input disabled="" type="checkbox"> Есть ли error budget в абсолютных значениях для текущего объёма трафика?</li>
<li><input disabled="" type="checkbox"> Есть ли записанная error budget policy (что делать при сгорании)?</li>
<li><input disabled="" type="checkbox"> Есть ли запас между SLO и SLA (если SLA вообще обещаем)?</li>
<li><input disabled="" type="checkbox"> Согласованы ли числа с бизнесом (а не «команда придумала»)?</li>
<li><input disabled="" type="checkbox"> Учтены ли SLO критичных зависимостей в верхней границе нашего?</li>
<li><input disabled="" type="checkbox"> Назначена ли дата следующего пересмотра?</li>
</ul>
<h2 id="заключение-slo--это-мост-между-системой-и-деньгами">Заключение: SLO — это мост между системой и деньгами</h2>
<p>Я начинал статью с тезиса, что архитектура без SLO — это эстетика, не инженерия. К концу хочется его уточнить.</p>
<p>SLO — не просто <strong>constraint</strong> на архитектуру, хотя я почти всю статью акцентировал именно это. SLO — это <strong>общий язык</strong> между четырьмя ролями, которые иначе говорят на разных:</p>
<ul>
<li><strong>Продакт / аналитик</strong> говорит: конверсия, retention, GMV, NPS.</li>
<li><strong>Бэкенд</strong> говорит: P99, шарды, hit rate, репликация.</li>
<li><strong>SRE</strong> говорит: error budget, burn rate, MTTR, blast radius.</li>
<li><strong>Бизнес</strong> говорит: деньги, репутация, регуляторика.</li>
</ul>
<p>SLO — это формат, в котором все четверо могут договориться. «Поднять availability с 99.9% до 99.99% стоит 4× инфраструктуры и сэкономит N часов даунтайма в год, что на нашем GMV $X — это <code>Y</code> денег. Делаем или нет?». Этот вопрос имеет ответ, к которому пришли все четверо. Без SLO такого вопроса просто не существует — есть только предчувствия.</p>
<h3 id="что-сделать-в-понедельник">Что сделать в понедельник</h3>
<ol>
<li><strong>Возьми один пользовательский путь и разложи его на шаги.</strong> Не сервис целиком — один сценарий, шесть-семь шагов, как в нашем кейсе. На каждый шаг — кандидаты в SLI. Это упражнение делается за два часа и показывает, где ты измеряешь не то.</li>
<li><strong>Сравни свои текущие SLO с реальными зависимостями.</strong> Если твой SLO выше произведения SLO критичных зависимостей — ты обещаешь больше, чем можешь дать. Цифру лучше пересмотреть до того, как её пересмотрит пользователь.</li>
<li><strong>Напиши error budget policy на одну страницу.</strong> Что происходит при превышении burn-rate <code>X×</code> за <code>Y</code> минут? Кто принимает решение freeze? Без этого документа SLO остаётся графиком на дашборде, а не дисциплиной.</li>
</ol>
<p>Спасибо, что дочитал до конца. Эта статья — переработанная версия плана несостоявшегося доклада для <a href="https://t.me/system_design_world" rel="noopener noreferrer" target="_blank">System Design World</a>
. Если у тебя есть свой опыт работы с SLO в системе высокой нагрузки — особенно интересны истории, как менялся выбор SLO с ростом продукта или после крупного инцидента — пиши в комменты или в мой Telegram-канал «<a href="https://t.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">Мишка на сервере</a>
».</p>
<p>Чертёж — это половина дела. Как именно выглядит тот самый диалог с бизнесом, без которого SLO остаётся картинкой на дашборде, я разбираю в продолжении: <a href="/posts/reliability-is-a-conversation/">«Надёжность строится в диалоге с бизнесом»</a>
.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></description>
      <content:encoded><![CDATA[<style>/* Inline-CSS, который тема вкладывает в <description> каждого item'а
   RSS-фида (layouts/index.rss.xml). RSS-ридеры (Feedly, Inoreader,
   NetNewsWire) уважают <style> внутри description с переменной
   степенью энтузиазма — это базовый fallback, достаточный для читаемой
   типографики, не более.

   Цвета продублированы из 00-vars.css (light-палитра) — поправь
   синхронно при изменении --bg / --text / --accent / --border. */

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  line-height: 1.6;
  color: #1c1c1f;
  max-width: 720px;
  margin: 0 auto;
  padding: 1em;
}
h1, h2, h3 { line-height: 1.25; margin-top: 1.4em; }
a { color: #c2410c; }
pre {
  background: #1e1e24;
  color: #e8e6df;
  padding: 1em;
  border-radius: 6px;
  overflow-x: auto;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.9em;
}
code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  background: #f3f1ed;
  padding: 0.1em 0.4em;
  border-radius: 4px;
}
pre code { background: transparent; padding: 0; }
blockquote {
  border-left: 3px solid #c2410c;
  padding-left: 1em;
  color: #5b5b62;
  font-style: italic;
  margin-left: 0;
}
img { max-width: 100%; height: auto; border-radius: 6px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #e5e3dc; padding: 6px 10px; text-align: left; }
</style><div><p>Привет, <code>%username%</code>! На системном дизайне 9 из 10 кандидатов начинают с компонентов: API gateway, Kafka, Redis, Postgres-реплики, шардинг, CDN. Это не дизайн — это плакат с логотипами. Дизайн начинается с вопроса, на который почти никто не отвечает первым: «какой надёжности я обещаю и почему именно этой, а не другой?».</p>
<p>Без числа в этом ответе — <code>99.5</code>, <code>99.9</code>, <code>99.99</code> — все архитектурные решения ниже становятся вопросом эстетики. С числом — превращаются в инженерные ограничения, которые решают за тебя, нужна ли вторая БД-реплика, имеет ли смысл repair-aware кэш и сколько регионов держать в active-active.</p>
<p>В этой статье я беру одну каноничную задачу с собеса — <strong>поиск каталога маркетплейса</strong> — и прокручиваю её сквозь три уровня SLO: <code>99.0%</code>, <code>99.9%</code>, <code>99.99%</code>. На каждом уровне меняется не «настройка пары флагов», а сама архитектура. Главный тезис: SLI/SLO — это не SRE-декорация поверх готовой системы, а <strong>интерфейс между System Design и бизнесом</strong>. Тот самый, через который аналитик, бэкенд и SRE говорят на одном языке.</p>
<h2 id="что-ты-унесёшь-из-статьи">Что ты унесёшь из статьи</h2>
<p>Статья длинная (~55 000 знаков), поэтому сразу — что заберёт каждая ЦА:</p>
<ul>
<li><strong>Аналитик / продакт.</strong> Рамка для перевода бизнес-метрик в SLI и для разговора с инженерами в стиле «а если снизим SLO с 99.99% до 99.9% — что освободится?».</li>
<li><strong>Бэкенд-инженер.</strong> Как один и тот же поиск каталога превращается в три разные системы при смене таргета SLO — read path, кэш, индекс, failover.</li>
<li><strong>SRE / DevOps.</strong> Error budget как валюта в спорах «фича vs рефакторинг» + типовые ошибки выбора SLI: что делать, когда дашборд зелёный, а пользователи — в саппорте.</li>
</ul>
<p>Общий блок для всех: разница между <strong>Observability</strong>, <strong>Monitoring</strong> и <strong>Alerting</strong> — в одной схеме.</p>
<h2 id="tldr-если-читать-дальше-уже-некогда">TL;DR (если читать дальше уже некогда)</h2>
<p>Если у тебя нет 30 минут на длинный разбор — четыре тезиса, к которым приходит статья:</p>
<ol>
<li><strong>SLO выбирается до архитектуры, а не после.</strong> Поднять SLO задним числом — это переписать систему, а не «добавить мониторинга». Снизить — освободить бюджет, но не вернуть деньги.</li>
<li><strong>Один и тот же кейс на трёх SLO (<code>99.0%</code> / <code>99.9%</code> / <code>99.99%</code>) — это три разные системы.</strong> Меняется не «настройка флагов», а топология, технологии, capacity, RTO/RPO, операционная модель и стоимость (<code>1×</code> → <code>4–6×</code> → <code>15–25×</code> baseline).</li>
<li><strong>SLI вешаются на шаги критичного пользовательского пути (CUJ), а не «на сервис в целом».</strong> «99.9% по системе» — это псевдо-метрика, которая прячет деградацию ключевого шага за здоровьем фоновых эндпоинтов.</li>
<li><strong>Error budget работает как валюта в спорах «фича vs рефакторинг», только если есть записанная error budget policy.</strong> Без неё SLO — это график на дашборде, а не дисциплина.</li>
</ol>
<p>Дальше — как до этих четырёх тезисов прийти через один сквозной кейс. Если интересует только инженерная кульминация — переходи сразу к разделу <a href="#%d0%be%d0%b4%d0%b8%d0%bd-%d0%ba%d0%b5%d0%b9%d1%81--%d1%82%d1%80%d0%b8-slo--%d1%82%d1%80%d0%b8-%d0%b0%d1%80%d1%85%d0%b8%d1%82%d0%b5%d0%ba%d1%82%d1%83%d1%80%d1%8b">Один кейс — три SLO — три архитектуры</a>
.</p>
<h2 id="кейс-поиск-каталога-маркетплейса">Кейс: поиск каталога маркетплейса</h2>
<p>Чтобы не разговаривать абстракциями, возьмём одну сквозную задачу. Формулирую как на собеседовании:</p>
<blockquote><p>Спроектируйте сервис поиска и выдачи карточек товаров для крупного маркетплейса. На вход — поисковый запрос пользователя и фильтры (категория, цена, доставка, регион). На выход — отранжированный список карточек с превью, пагинация, фасеты.</p>
</blockquote><p>Параметры — реалистичные для маркетплейса масштаба Ozon / Wildberries / Avito, но «приглаженные» под удобство арифметики:</p>
<table>
  <thead>
      <tr>
          <th>Характеристика</th>
          <th>Значение</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Активный каталог</td>
          <td>~50M товаров</td>
      </tr>
      <tr>
          <td>Пиковый RPS на поиск</td>
          <td>~30 000 запросов/сек</td>
      </tr>
      <tr>
          <td>Активных одновременных пользователей</td>
          <td>~200 000</td>
      </tr>
      <tr>
          <td>Доля mobile-трафика</td>
          <td>~70%</td>
      </tr>
      <tr>
          <td>География</td>
          <td>5 регионов, основной — central RU</td>
      </tr>
      <tr>
          <td>Целевая P50 латентность read path</td>
          <td>&lt; 150 ms</td>
      </tr>
      <tr>
          <td>Целевая P99 латентность read path</td>
          <td>&lt; 500 ms</td>
      </tr>
      <tr>
          <td>Сезонные пики (BF, распродажи)</td>
          <td>x3–x5 от обычного RPS</td>
      </tr>
  </tbody>
</table>
<p>Бизнес-контекст, про который часто забывают на собесе, и зря:</p>
<ul>
<li><strong>Поиск — главный драйвер конверсии.</strong> По публичным отчётам (SimilarWeb, ContentSquare, материалы крупных маркетплейсов) на больших площадках 40–70% покупок начинается с поисковой строки, не с категорий или баннеров. Конкретный процент гуляет по сегментам и площадкам, но порядок одинаков. Любая деградация поиска — это прямая просадка GMV, не «инженерная неприятность».</li>
<li><strong>Эластичность по latency измерима.</strong> Цифры из публикаций Amazon (Greg Linden, 2006), Akamai (2017), Google/SOASTA (2017) и Deloitte (2020) разнятся по методологии и сегменту, но порядок сходится: каждые <code>+100 ms</code> latency на ключевом read path стоят примерно <code>−0.5…1.5%</code> конверсии. Для маркетплейса с GMV $10M в день это $50–150k недополученной выручки <strong>в день</strong>, если регресс закрепится. Это не разовый ущерб, а просадка, в которую конвертируется latency на ключевом read path.</li>
<li><strong>Стоимость недоступности нелинейна.</strong> 5 минут даунтайма обычным вторником и 5 минут даунтайма в Чёрную пятницу — это разные деньги в десятки раз. SLO должно учитывать сезонность, иначе оно меряет не то.</li>
</ul>
<p>Эти три факта — ровно то, что превращает SLI/SLO из «инженерной гигиены» в инструмент бизнес-разговора. Я буду к ним возвращаться в каждом следующем разделе.</p>
<h2 id="что-обычно-ломается-на-собесе-без-slo">Что обычно ломается на собесе без SLO</h2>
<p>Послушаешь сотню system-design интервью — и складывается узнаваемый паттерн ответа.</p>
<h3 id="типичная-траектория">Типичная траектория</h3>
<ol>
<li><strong>Уточнили требования.</strong> «Сколько пользователей? Какая нагрузка?» — кандидат услышал «много», и в голове щёлкнуло «значит, надо много всего».</li>
<li><strong>Нарисовали API.</strong> REST с парой эндпоинтов, gateway, auth-middleware. Пока без сюрпризов.</li>
<li><strong>Добавили слой данных.</strong> Postgres / MySQL — «реляционка для каталога норм». Кто-то сразу предложит Elasticsearch, потому что слышал про full-text search.</li>
<li><strong>Поставили кэш.</strong> Redis — потому что «Redis fast». Без обсуждения, что именно кэшируем, какой hit rate ожидаем, как инвалидируем при изменении цены или остатков.</li>
<li><strong>Подняли реплики.</strong> «На чтение пойдут реплики, на запись — мастер». Без обсуждения, насколько асинхронная репликация критична: а если пользователь не увидит свой только что выложенный товар?</li>
<li><strong>Зашардировали.</strong> Чаще всего по <code>category_id</code> или <code>seller_id</code>. Потому что «у больших так».</li>
<li><strong>Накинули CDN и очередь.</strong> Kafka — куда же без неё. Async-обработка событий, чтобы «развязать сервисы».</li>
</ol>
<p>К концу интервью на доске — красивая распределённая система. Интервьюер кивает. Кандидат уверен, что справился.</p>
<h3 id="что-в-этой-траектории-не-так">Что в этой траектории не так</h3>
<p>Простой тест. Ответь сам себе: <strong>какое из решений выше изменилось бы, если бы требование к доступности было <code>99.0%</code>, а не <code>99.99%</code>?</strong> А если бы P99 была не 500 ms, а 2 секунды?</p>
<p>Если ответ «никакое» — значит, дизайн не привязан к требованиям к надёжности. Кандидат строил систему «как принято», а не «как нужно бизнесу». А раз все решения принимались независимо от целевого SLO — значит, любые из них могут быть и преждевременными, и недостаточными одновременно. Точно сказать нельзя, потому что точки отсчёта нет.</p>
<p>Чтобы было совсем больно — разберём по решениям:</p>
<ul>
<li><strong>Кэш Redis.</strong> Имеет смысл, если твой SLO по latency — десятки миллисекунд для горячих запросов или ты упираешься в нагрузку на БД при текущем availability-таргете. При расслабленном SLO P99 = 2 секунды кэш в read path — преждевременная оптимизация: ты поднимаешь эксплуатационную сложность (инвалидация, прогрев, репликация Redis-кластера, отдельный SLO на сам кэш) ради цели, которая выполнима и без него.</li>
<li><strong>Реплики на чтение.</strong> Имеют смысл, если твой SLO availability такой, что мастер-only архитектура не уложится в бюджет ошибок при типовом MTTR. На SLO <code>99.0%</code> (~7 часов даунтайма в месяц) одного хорошо настроенного primary с мониторингом и быстрым backup-восстановлением часто достаточно.</li>
<li><strong>Шардинг.</strong> Оправдан, когда объём данных или write QPS упирается в один инстанс физически. До этого — это удвоение операционной нагрузки (rebalancing, hot shards, резолв cross-shard запросов) без выигрыша по SLI, ради которого его делают.</li>
<li><strong>Multi-region active-active.</strong> Имеет смысл при SLO availability <code>99.99%</code>+ или когда регуляторика обязывает (data residency, ФЗ-149/ФЗ-152/ФЗ-242/GDPR-аналоги). На <code>99.9%</code> обычно дешевле и предсказуемее active-passive с автоматическим failover и RTO в минутах.</li>
</ul>
<p>Каждое из этих решений — правильное в одних условиях и преждевременное в других. Условия задаёт SLO. Без него ты выбираешь архитектуру не под задачу, а под насмотренность.</p>
<h3 id="главный-сдвиг--направление-дизайна">Главный сдвиг — направление дизайна</h3>
<p>Хороший дизайн идёт <strong>сверху вниз</strong>: бизнес-цель → критичный пользовательский путь (CUJ, critical user journey) → SLI на каждый шаг этого пути → SLO как контракт → архитектура, которая в этот SLO укладывается с разумным запасом.</p>
<p>Плохой дизайн идёт <strong>снизу вверх</strong>: «у крутых ребят такая схема — нарисуем такую же». На выходе получается архитектура, в которую любой SLO «впихнуть можно постфактум» — потому что под её требования не задавали ни одного числа, и теперь любая цифра одинаково годится для отчётности и одинаково плохо отражает реальное поведение системы.</p>
<p>В следующих разделах я разворачиваю верхний путь — сверху вниз — на нашем кейсе с маркетплейсом. Начнём с шага 1: как из функциональных требований получается тот самый критичный пользовательский путь.</p>
<h2 id="шаг-1-от-фт-к-критичному-пользовательскому-пути">Шаг 1: от ФТ к критичному пользовательскому пути</h2>
<p>Раз направление дизайна сверху вниз — нужна точка отсчёта на самом верху. Это <strong>функциональные требования (ФТ)</strong>: что система делает в терминах пользователя и продукта. Не «использует Elasticsearch», а «возвращает релевантную выдачу по запросу».</p>
<h3 id="фт-для-нашего-кейса">ФТ для нашего кейса</h3>
<ul>
<li>Принять поисковый запрос (текст + фильтры) от авторизованного и анонимного пользователя.</li>
<li>Подбирать товары из активного каталога с учётом региона и доступной доставки.</li>
<li>Ранжировать результаты с учётом релевантности, цены, рейтинга продавца и персонализации.</li>
<li>Возвращать пагинированную выдачу с фасетами (категории, ценовые диапазоны, бренды).</li>
<li>Поддерживать sorting (price asc/desc, popularity, rating).</li>
<li>Подсказки и автодополнение по мере набора запроса.</li>
</ul>
<p>Это всё одинаково «функциональные требования» — но <strong>не одинаково критичные</strong>. Если автодополнение тормозит на 200 ms, пользователь поморщится. Если выдача не приходит вовсе — он закроет вкладку и пойдёт к конкуренту. ФТ сами по себе плоские, в них нет приоритета. Этот приоритет приносит <strong>критичный пользовательский путь</strong>.</p>
<h3 id="критичный-пользовательский-путь-cuj--critical-user-journey">Критичный пользовательский путь (CUJ — critical user journey)</h3>
<p>Это сценарий пользователя, который напрямую кормит ключевую бизнес-метрику. У маркетплейса бизнес-метрика — GMV, точка входа в неё — поиск, точка выхода — клик в карточку и далее в корзину. Получаем такой путь:</p>
<blockquote><p>Пользователь приходит на сайт с намерением купить → формулирует запрос → получает релевантную выдачу → выбирает товар → переходит в карточку.</p>
</blockquote><p>Это и есть «золотой путь», за который держимся в дизайне. Всё, что не обслуживает этот путь напрямую (статистика для аналитики, A/B-эксперименты, персональные рекомендации в стороннем виджете), может быть менее надёжным — и это нормально.</p>
<aside class="callout callout--note" role="note">
  <div class="callout__icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg></div>
  <div class="callout__body"><p class="callout__title">Терминологическая дисциплина</p>
    <div class="callout__content"><p>Дальше по тексту слово <strong>«сервис»</strong> работает в двух разных значениях, и я их буду стараться разводить явно:</p>
<ul>
<li><strong>Пользовательский сервис</strong> — это CUJ (поиск каталога целиком). К нему привязаны SLI и SLO.</li>
<li><strong>Микросервис</strong> — это юнит деплоя (Search Service, Ranking Service на схеме архитектуры). К нему привязаны Golden Signals для внутренней диагностики, но <strong>не отдельный набор SLI</strong>.</li>
</ul>
<p>Один пользовательский сервис может реализовываться десятью микросервисами — но SLI по-прежнему 4–8, не 4–8 × 10. К этому различию ещё вернёмся в разделе про типичные ошибки.</p></div>
  </div>
</aside><h3 id="декомпозиция-пути-на-шаги">Декомпозиция пути на шаги</h3>
<p>Дальше путь режется на дискретные шаги, каждый из которых станет отдельной точкой измерения:</p>
<table>
  <thead>
      <tr>
          <th>#</th>
          <th>Шаг</th>
          <th>Что делает система</th>
          <th>Что замечает пользователь</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1</td>
          <td>Загрузка поискового интерфейса</td>
          <td>Отдать HTML/SPA-bundle, инициализировать клиент</td>
          <td>Страница появилась, поле поиска кликабельно</td>
      </tr>
      <tr>
          <td>2</td>
          <td>Автодополнение (suggest)</td>
          <td>На каждое нажатие клавиши вернуть top-N подсказок</td>
          <td>Подсказки появляются «без задержки»</td>
      </tr>
      <tr>
          <td>3</td>
          <td>Отправка запроса</td>
          <td>Получить query + фильтры, направить в search backend</td>
          <td>Лоадер крутится недолго</td>
      </tr>
      <tr>
          <td>4</td>
          <td>Получение выдачи</td>
          <td>Поиск в индексе, ранжирование, обогащение карточек</td>
          <td>Выдача отрисовалась, скроллится плавно</td>
      </tr>
      <tr>
          <td>5</td>
          <td>Применение фильтра / сортировки</td>
          <td>Реквест с уточнёнными параметрами</td>
          <td>Список перестроился без рывков</td>
      </tr>
      <tr>
          <td>6</td>
          <td>Клик в карточку</td>
          <td>Переход на страницу товара, прелоад данных</td>
          <td>Карточка открылась, цена и наличие актуальны</td>
      </tr>
  </tbody>
</table>
<p>Эти шесть шагов — каркас, на котором будет висеть всё дальнейшее. На каждый шаг повесим SLI, на каждый SLI — SLO. И увидим, что они <strong>не равноценны</strong>: шаг 4 (получение выдачи) для бизнеса принципиально важнее, чем шаг 2 (автодополнение). А значит, и инженерных усилий на их надёжность нужно несоизмеримо больше.</p>
<h3 id="почему-это-важно-ловушка-среднего-по-системе">Почему это важно: ловушка «среднего по системе»</h3>
<p>На многих собеседованиях кандидат, отвечая на «какую ты доступность хочешь», говорит «99.9% по системе». Это бесполезное число: если оно посчитано как «суммарный аптайм всех эндпоинтов», оно скрывает то, что выдача упала на 30 минут, а суммарно «вышло 99.9%, потому что autocomplete и health-чеки крутились». Пользователь страдал, дашборд зелёный.</p>
<p>Шаги критичного пути — антидот этой ловушки. Каждый шаг получает свою цифру, и провал шага 4 невозможно «размазать» доступностью соседних шагов.</p>
<h2 id="шаг-2-нфт-как-свойства-шагов-а-не-системы">Шаг 2: НФТ как свойства шагов, а не системы</h2>
<p>Когда есть карта шагов, нефункциональные требования (НФТ) перестают быть размытым «надёжно, быстро, безопасно». Они становятся набором конкретных свойств <strong>каждого шага</strong>.</p>
<h3 id="свойства-которые-нас-интересуют">Свойства, которые нас интересуют</h3>
<p>Для read-heavy критичного пути маркетплейса базовый набор НФТ выглядит так:</p>
<ul>
<li><strong>Латентность.</strong> Сколько миллисекунд занял шаг. Меряем перцентилями (P50/P95/P99), не средним — оно скрывает хвосты, а хвосты и есть пользовательская боль.</li>
<li><strong>Доступность.</strong> Доля успешных шагов. Не «200/всего HTTP», а именно «шаг выполнен корректно с точки зрения сценария».</li>
<li><strong>Корректность.</strong> Получил ли пользователь ожидаемый результат. Для шага 4 — вернулась ли релевантная выдача или 0 результатов из-за бага в ранжировании.</li>
<li><strong>Свежесть.</strong> Насколько актуальны данные. Цена и наличие на карточке после клика — критичная свежесть; popularity-score в ранжировании — терпит часовую задержку.</li>
<li><strong>Целостность.</strong> Не «исчезает» ли часть результатов из-за частичного сбоя ноды или таймаута к шарду. Это специфично для распределённого поиска и шардированных индексов.</li>
</ul>
<h3 id="привязка-свойств-к-шагам-пути">Привязка свойств к шагам пути</h3>
<p>Не каждое свойство одинаково важно на каждом шаге. Покажу таблицей, какие НФТ для каких шагов нашего кейса критичны:</p>
<table>
  <thead>
      <tr>
          <th>Шаг</th>
          <th>Латентность</th>
          <th>Доступность</th>
          <th>Корректность</th>
          <th>Свежесть</th>
          <th>Целостность</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1. Загрузка интерфейса</td>
          <td>средне</td>
          <td>высоко</td>
          <td>низко</td>
          <td>низко</td>
          <td>низко</td>
      </tr>
      <tr>
          <td>2. Autocomplete</td>
          <td>высоко</td>
          <td>средне</td>
          <td>средне</td>
          <td>низко</td>
          <td>низко</td>
      </tr>
      <tr>
          <td>3. Отправка запроса</td>
          <td>средне</td>
          <td>высоко</td>
          <td>низко</td>
          <td>низко</td>
          <td>низко</td>
      </tr>
      <tr>
          <td>4. Получение выдачи</td>
          <td><strong>высоко</strong></td>
          <td><strong>высоко</strong></td>
          <td><strong>высоко</strong></td>
          <td>средне</td>
          <td><strong>высоко</strong></td>
      </tr>
      <tr>
          <td>5. Фильтр / сортировка</td>
          <td>высоко</td>
          <td>высоко</td>
          <td>высоко</td>
          <td>средне</td>
          <td>высоко</td>
      </tr>
      <tr>
          <td>6. Клик в карточку</td>
          <td>средне</td>
          <td>высоко</td>
          <td>высоко</td>
          <td><strong>высоко</strong></td>
          <td>низко</td>
      </tr>
  </tbody>
</table>
<p>Сразу видно: шаг 4 — концентратор НФТ, на нём горят почти все колонки. Шаг 6 особенно требователен к свежести — потому что показать пользователю карточку с «вчерашней» ценой (а на чекауте уже другая) — это худший UX и часто прямой ущерб бизнесу через возвраты и репутацию.</p>
<h3 id="главное-смещение-от-привычных-нфт-из-тз">Главное смещение от привычных НФТ из ТЗ</h3>
<p>Классические нефункциональные требования — «система должна обеспечивать 99.9% доступности» — это <strong>средневзвешенное по чему попало</strong>. Они одинаково оценивают и autocomplete, и финальную выдачу. В реальной эксплуатации это приводит к двум симметричным болям:</p>
<ol>
<li><strong>Деньги тратятся не туда.</strong> Команда вкладывает усилия в надёжность шагов, которые этого не требуют (autocomplete с 99.99% — приятно, но конверсию не трогает), а критичные шаги остаются на «общем уровне».</li>
<li><strong>Алерты молчат, когда болит.</strong> Дашборд показывает зелёный «99.9% по системе», пока шаг 4 деградирует и теряет каждую десятую выдачу. Эту потерю топит «здоровье» десятка других эндпоинтов и фоновых хелсчеков.</li>
</ol>
<p>НФТ-по-шагам убирают эту усреднённость. Следующий шаг сверху вниз — превращаем эти свойства в <strong>измеримые SLI</strong>, чтобы было что мерить и за что отчитываться. Но прежде чем давать формулу — нужен общий словарь, без него разговор про SLI получится поверхностным.</p>
<h2 id="шаг-3-sli-как-индикатор-пользовательского-опыта">Шаг 3: SLI как индикатор пользовательского опыта</h2>
<h3 id="сначала--общий-словарь-observability--monitoring--alerting">Сначала — общий словарь: Observability ≠ Monitoring ≠ Alerting</h3>
<p>В SRE-практике три термина часто валят в одну кучу, и тогда любой разговор про SLI разваливается на терминологические уточнения. Развожу их через <strong>цель</strong> каждой практики:</p>
<ul>
<li><strong>Monitoring (мониторинг)</strong> отвечает на заранее заданные вопросы. Ты знаешь, что хочешь видеть: «жив ли primary», «какая P99 у эндпоинта <code>/search</code>», «не растёт ли latency». На каждую заготовку — метрика или дашборд. Это про <strong>known unknowns</strong> — вещи, о которых ты знаешь, что они могут пойти не так, и хочешь их видеть.</li>
<li><strong>Observability (наблюдаемость)</strong> — свойство системы, которое позволяет дойти до <strong>нового</strong> вопроса. Не «жив ли primary», а «почему именно в этом конкретном запросе latency 4 секунды». Высокая observability означает, что у тебя достаточно данных (метрик, структурированных логов, трейсов с tail-based sampling, событий) и инструментов поверх них, чтобы задать системе вопрос, который ты не предусмотрел заранее. Это про <strong>unknown unknowns</strong> — про неожиданности, которых ты не ждал. Такое разведение «monitoring = known unknowns / observability = unknown unknowns» — рамка из «Distributed Systems Observability» Cindy Sridharan (O&rsquo;Reilly, 2018) и развитая инженерами Honeycomb (Charity Majors et al.); внутри Google SRE Workbook грань между ними размытее, и я сознательно беру более жёсткую формулировку — на ней легче строить дизайн.</li>
<li><strong>Alerting (алертинг)</strong> — действие по событию. Это слой, надстроенный над мониторингом и observability: правила, которые превращают наблюдаемое состояние в инцидент с пейджингом. Алерт — это не метрика, это <strong>обещание разбудить человека</strong>, и за него надо отвечать. Alert fatigue — отдельная боль, и лечится она burn-rate-алертами, а не увеличением количества правил.</li>
</ul>
<p>Связь между ними — на одной схеме:</p>
<figure class="mermaid mermaid--prerendered" aria-label="Mermaid diagram">
<div class="mermaid-svg mermaid-svg--light">
<svg id="m-02e1152b1ac5-light" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 1109.69px; background-color: transparent;" viewBox="0 0 1109.6875 390.375" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#m-02e1152b1ac5-light{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;fill:#1c1c1f;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#m-02e1152b1ac5-light .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#m-02e1152b1ac5-light .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#m-02e1152b1ac5-light .error-icon{fill:#fee2e2;}#m-02e1152b1ac5-light .error-text{fill:#7f1d1d;stroke:#7f1d1d;}#m-02e1152b1ac5-light .edge-thickness-normal{stroke-width:1px;}#m-02e1152b1ac5-light .edge-thickness-thick{stroke-width:3.5px;}#m-02e1152b1ac5-light .edge-pattern-solid{stroke-dasharray:0;}#m-02e1152b1ac5-light .edge-thickness-invisible{stroke-width:0;fill:none;}#m-02e1152b1ac5-light .edge-pattern-dashed{stroke-dasharray:3;}#m-02e1152b1ac5-light .edge-pattern-dotted{stroke-dasharray:2;}#m-02e1152b1ac5-light .marker{fill:#5b5b62;stroke:#5b5b62;}#m-02e1152b1ac5-light .marker.cross{stroke:#5b5b62;}#m-02e1152b1ac5-light svg{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;}#m-02e1152b1ac5-light p{margin:0;}#m-02e1152b1ac5-light .label{font-family:Inter,system-ui,-apple-system,sans-serif;color:#1c1c1f;}#m-02e1152b1ac5-light .cluster-label text{fill:#1c1c1f;}#m-02e1152b1ac5-light .cluster-label span{color:#1c1c1f;}#m-02e1152b1ac5-light .cluster-label span p{background-color:transparent;}#m-02e1152b1ac5-light .label text,#m-02e1152b1ac5-light span{fill:#1c1c1f;color:#1c1c1f;}#m-02e1152b1ac5-light .node rect,#m-02e1152b1ac5-light .node circle,#m-02e1152b1ac5-light .node ellipse,#m-02e1152b1ac5-light .node polygon,#m-02e1152b1ac5-light .node path{fill:#ffffff;stroke:#c8c5bb;stroke-width:1px;}#m-02e1152b1ac5-light .rough-node .label text,#m-02e1152b1ac5-light .node .label text,#m-02e1152b1ac5-light .image-shape .label,#m-02e1152b1ac5-light .icon-shape .label{text-anchor:middle;}#m-02e1152b1ac5-light .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#m-02e1152b1ac5-light .rough-node .label,#m-02e1152b1ac5-light .node .label,#m-02e1152b1ac5-light .image-shape .label,#m-02e1152b1ac5-light .icon-shape .label{text-align:center;}#m-02e1152b1ac5-light .node.clickable{cursor:pointer;}#m-02e1152b1ac5-light .root .anchor path{fill:#5b5b62!important;stroke-width:0;stroke:#5b5b62;}#m-02e1152b1ac5-light .arrowheadPath{fill:rgba(255, 255, 255, 0);}#m-02e1152b1ac5-light .edgePath .path{stroke:#5b5b62;stroke-width:1px;}#m-02e1152b1ac5-light .flowchart-link{stroke:#5b5b62;fill:none;}#m-02e1152b1ac5-light .edgeLabel{background-color:#fafaf7;text-align:center;}#m-02e1152b1ac5-light .edgeLabel p{background-color:#fafaf7;}#m-02e1152b1ac5-light .edgeLabel rect{opacity:0.5;background-color:#fafaf7;fill:#fafaf7;}#m-02e1152b1ac5-light .labelBkg{background-color:rgba(250, 250, 247, 0.5);}#m-02e1152b1ac5-light .cluster rect{fill:#f3f1ed;stroke:#c8c5bb;stroke-width:1px;}#m-02e1152b1ac5-light .cluster text{fill:#1c1c1f;}#m-02e1152b1ac5-light .cluster span{color:#1c1c1f;}#m-02e1152b1ac5-light div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:12px;background:#fed7aa;border:1px solid #c2410c;border-radius:2px;pointer-events:none;z-index:100;}#m-02e1152b1ac5-light .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#1c1c1f;}#m-02e1152b1ac5-light rect.text{fill:none;stroke-width:0;}#m-02e1152b1ac5-light .icon-shape,#m-02e1152b1ac5-light .image-shape{background-color:#fafaf7;text-align:center;}#m-02e1152b1ac5-light .icon-shape p,#m-02e1152b1ac5-light .image-shape p{background-color:#fafaf7;padding:2px;}#m-02e1152b1ac5-light .icon-shape .label rect,#m-02e1152b1ac5-light .image-shape .label rect{opacity:0.5;background-color:#fafaf7;fill:#fafaf7;}#m-02e1152b1ac5-light .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#m-02e1152b1ac5-light .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#m-02e1152b1ac5-light .node .neo-node{stroke:#c8c5bb;}#m-02e1152b1ac5-light [data-look="neo"].node rect,#m-02e1152b1ac5-light [data-look="neo"].cluster rect,#m-02e1152b1ac5-light [data-look="neo"].node polygon{stroke:url(#m-02e1152b1ac5-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-02e1152b1ac5-light [data-look="neo"].node path{stroke:url(#m-02e1152b1ac5-light-gradient);stroke-width:1px;}#m-02e1152b1ac5-light [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-02e1152b1ac5-light [data-look="neo"].node .neo-line path{stroke:#c8c5bb;filter:none;}#m-02e1152b1ac5-light [data-look="neo"].node circle{stroke:url(#m-02e1152b1ac5-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-02e1152b1ac5-light [data-look="neo"].node circle .state-start{fill:#000000;}#m-02e1152b1ac5-light [data-look="neo"].icon-shape .icon{fill:url(#m-02e1152b1ac5-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-02e1152b1ac5-light [data-look="neo"].icon-shape .icon-neo path{stroke:url(#m-02e1152b1ac5-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-02e1152b1ac5-light :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="m-02e1152b1ac5-light_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-light_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-light_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-light_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-light_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-light_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-light_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-light_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-light_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-light_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-light_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="m-02e1152b1ac5-light_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M207.593,178L221.005,171.021C234.416,164.042,261.239,150.083,278.151,143.104C295.063,136.125,302.063,136.125,305.563,136.125L309.063,136.125" id="m-02e1152b1ac5-light-L_System_M_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_System_M_0" data-points="W3sieCI6MjA3LjU5MzI1Nzg3NDAxNTc2LCJ5IjoxNzh9LHsieCI6Mjg4LjA2MjUsInkiOjEzNi4xMjV9LHsieCI6MzEzLjA2MjUsInkiOjEzNi4xMjV9XQ==" data-look="classic" marker-end="url(#m-02e1152b1ac5-light_flowchart-v2-pointEnd)"/><path d="M207.593,253L221.005,259.979C234.416,266.958,261.239,280.917,282.315,287.896C303.391,294.875,318.719,294.875,326.383,294.875L334.047,294.875" id="m-02e1152b1ac5-light-L_System_O_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_System_O_0" data-points="W3sieCI6MjA3LjU5MzI1Nzg3NDAxNTc2LCJ5IjoyNTN9LHsieCI6Mjg4LjA2MjUsInkiOjI5NC44NzV9LHsieCI6MzM4LjA0Njg3NSwieSI6Mjk0Ljg3NX1d" data-look="classic" marker-end="url(#m-02e1152b1ac5-light_flowchart-v2-pointEnd)"/><path d="M537.651,87.375L547.282,82.479C556.913,77.583,576.175,67.792,589.308,63.122C602.44,58.452,609.443,58.904,612.944,59.129L616.446,59.355" id="m-02e1152b1ac5-light-L_M_A_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_M_A_0" data-points="W3sieCI6NTM3LjY1MSwieSI6ODcuMzc1fSx7IngiOjU5NS40Mzc1LCJ5Ijo1OH0seyJ4Ijo2MjAuNDM3NSwieSI6NTkuNjEyOTAzMjI1ODA2NDV9XQ==" data-look="classic" marker-end="url(#m-02e1152b1ac5-light_flowchart-v2-pointEnd)"/><path d="M504.267,234.875L519.462,220.292C534.657,205.708,565.047,176.542,585.955,159.033C606.862,141.524,618.287,135.674,623.999,132.749L629.712,129.823" id="m-02e1152b1ac5-light-L_O_A_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_O_A_0" data-points="W3sieCI6NTA0LjI2Njk0OTE1MjU0MjQsInkiOjIzNC44NzV9LHsieCI6NTk1LjQzNzUsInkiOjE0Ny4zNzV9LHsieCI6NjMzLjI3MjE0NTY2OTI5MTQsInkiOjEyOH1d" data-look="classic" marker-end="url(#m-02e1152b1ac5-light_flowchart-v2-pointEnd)"/><path d="M880.438,68L884.604,68C888.771,68,897.104,68,904.771,68C912.438,68,919.438,68,922.938,68L926.438,68" id="m-02e1152b1ac5-light-L_A_H_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_A_H_0" data-points="W3sieCI6ODgwLjQzNzUsInkiOjY4fSx7IngiOjkwNS40Mzc1LCJ5Ijo2OH0seyJ4Ijo5MzAuNDM3NSwieSI6Njh9XQ==" data-look="classic" marker-end="url(#m-02e1152b1ac5-light_flowchart-v2-pointEnd)"/><path d="M525.58,184.875L537.223,191.646C548.866,198.417,572.152,211.958,588.033,218.729C603.914,225.5,612.391,225.5,616.629,225.5L620.867,225.5" id="m-02e1152b1ac5-light-L_M_D_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_M_D_0" data-points="W3sieCI6NTI1LjU3OTU0NTQ1NDU0NTUsInkiOjE4NC44NzV9LHsieCI6NTk1LjQzNzUsInkiOjIyNS41fSx7IngiOjYyNC44NjcxODc1LCJ5IjoyMjUuNX1d" data-look="classic" marker-end="url(#m-02e1152b1ac5-light_flowchart-v2-pointEnd)"/><path d="M545.453,336.204L553.784,339.525C562.115,342.845,578.776,349.485,596.022,352.805C613.268,356.125,631.099,356.125,640.014,356.125L648.93,356.125" id="m-02e1152b1ac5-light-L_O_R_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_O_R_0" data-points="W3sieCI6NTQ1LjQ1MzEyNSwieSI6MzM2LjIwNDQyNzYxMjg1MDc0fSx7IngiOjU5NS40Mzc1LCJ5IjozNTYuMTI1fSx7IngiOjY1Mi45Mjk2ODc1LCJ5IjozNTYuMTI1fV0=" data-look="classic" marker-end="url(#m-02e1152b1ac5-light_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_System_M_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_System_O_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_M_A_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_O_A_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_A_H_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_M_D_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_O_R_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="m-02e1152b1ac5-light-flowchart-System-0" data-look="classic" transform="translate(135.53125, 215.5)"><rect class="basic label-container" style="" x="-127.53125" y="-37.5" width="255.0625" height="75"/><g class="label" style="" transform="translate(-97.53125, -22.5)"><rect/><foreignObject width="195.0625" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Система<br />сервисы, БД, кэш, очереди</p></span></div></foreignObject></g></g><g class="node default" id="m-02e1152b1ac5-light-flowchart-M-1" data-look="classic" transform="translate(441.75, 136.125)"><rect class="basic label-container" style="" x="-128.6875" y="-48.75" width="257.375" height="97.5"/><g class="label" style="" transform="translate(-98.6875, -33.75)"><rect/><foreignObject width="197.375" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Monitoring<br />known unknowns:<br />заранее заданные метрики</p></span></div></foreignObject></g></g><g class="node default" id="m-02e1152b1ac5-light-flowchart-O-3" data-look="classic" transform="translate(441.75, 294.875)"><rect class="basic label-container" style="" x="-103.703125" y="-60" width="207.40625" height="120"/><g class="label" style="" transform="translate(-73.703125, -45)"><rect/><foreignObject width="147.40625" height="90"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Observability<br />unknown unknowns:<br />возможность задать<br />новый вопрос</p></span></div></foreignObject></g></g><g class="node default" id="m-02e1152b1ac5-light-flowchart-A-5" data-look="classic" transform="translate(750.4375, 68)"><rect class="basic label-container" style="" x="-130" y="-60" width="260" height="120"/><g class="label" style="" transform="translate(-100, -45)"><rect/><foreignObject width="200" height="90"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>Alerting<br />правила, которые<br />превращают сигнал в инцидент</p></span></div></foreignObject></g></g><g class="node default" id="m-02e1152b1ac5-light-flowchart-H-9" data-look="classic" transform="translate(1016.0625, 68)"><rect class="basic label-container" style="" x="-85.625" y="-26.25" width="171.25" height="52.5"/><g class="label" style="" transform="translate(-55.625, -11.25)"><rect/><foreignObject width="111.25" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Человек on-call</p></span></div></foreignObject></g></g><g class="node default" id="m-02e1152b1ac5-light-flowchart-D-11" data-look="classic" transform="translate(750.4375, 225.5)"><rect class="basic label-container" style="" x="-125.5703125" y="-26.25" width="251.140625" height="52.5"/><g class="label" style="" transform="translate(-95.5703125, -11.25)"><rect/><foreignObject width="191.140625" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Дашборды и SLO-репорты</p></span></div></foreignObject></g></g><g class="node default" id="m-02e1152b1ac5-light-flowchart-R-13" data-look="classic" transform="translate(750.4375, 356.125)"><rect class="basic label-container" style="" x="-97.5078125" y="-26.25" width="195.015625" height="52.5"/><g class="label" style="" transform="translate(-67.5078125, -11.25)"><rect/><foreignObject width="135.015625" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Root cause analysis</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="m-02e1152b1ac5-light-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="m-02e1152b1ac5-light-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><linearGradient id="m-02e1152b1ac5-light-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#c8c5bb" stop-opacity="1"/><stop offset="100%" stop-color="#c8c5bb" stop-opacity="1"/></linearGradient></svg>
</div>
<div class="mermaid-svg mermaid-svg--dark">
<svg id="m-02e1152b1ac5-dark" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 1109.69px; background-color: transparent;" viewBox="0 0 1109.6875 390.375" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#m-02e1152b1ac5-dark{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;fill:#e8e6df;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#m-02e1152b1ac5-dark .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#m-02e1152b1ac5-dark .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#m-02e1152b1ac5-dark .error-icon{fill:#7f1d1d;}#m-02e1152b1ac5-dark .error-text{fill:#fecaca;stroke:#fecaca;}#m-02e1152b1ac5-dark .edge-thickness-normal{stroke-width:1px;}#m-02e1152b1ac5-dark .edge-thickness-thick{stroke-width:3.5px;}#m-02e1152b1ac5-dark .edge-pattern-solid{stroke-dasharray:0;}#m-02e1152b1ac5-dark .edge-thickness-invisible{stroke-width:0;fill:none;}#m-02e1152b1ac5-dark .edge-pattern-dashed{stroke-dasharray:3;}#m-02e1152b1ac5-dark .edge-pattern-dotted{stroke-dasharray:2;}#m-02e1152b1ac5-dark .marker{fill:#a8a89e;stroke:#a8a89e;}#m-02e1152b1ac5-dark .marker.cross{stroke:#a8a89e;}#m-02e1152b1ac5-dark svg{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;}#m-02e1152b1ac5-dark p{margin:0;}#m-02e1152b1ac5-dark .label{font-family:Inter,system-ui,-apple-system,sans-serif;color:#e8e6df;}#m-02e1152b1ac5-dark .cluster-label text{fill:#e8e6df;}#m-02e1152b1ac5-dark .cluster-label span{color:#e8e6df;}#m-02e1152b1ac5-dark .cluster-label span p{background-color:transparent;}#m-02e1152b1ac5-dark .label text,#m-02e1152b1ac5-dark span{fill:#e8e6df;color:#e8e6df;}#m-02e1152b1ac5-dark .node rect,#m-02e1152b1ac5-dark .node circle,#m-02e1152b1ac5-dark .node ellipse,#m-02e1152b1ac5-dark .node polygon,#m-02e1152b1ac5-dark .node path{fill:#23252a;stroke:#3f3f46;stroke-width:1px;}#m-02e1152b1ac5-dark .rough-node .label text,#m-02e1152b1ac5-dark .node .label text,#m-02e1152b1ac5-dark .image-shape .label,#m-02e1152b1ac5-dark .icon-shape .label{text-anchor:middle;}#m-02e1152b1ac5-dark .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#m-02e1152b1ac5-dark .rough-node .label,#m-02e1152b1ac5-dark .node .label,#m-02e1152b1ac5-dark .image-shape .label,#m-02e1152b1ac5-dark .icon-shape .label{text-align:center;}#m-02e1152b1ac5-dark .node.clickable{cursor:pointer;}#m-02e1152b1ac5-dark .root .anchor path{fill:#a8a89e!important;stroke-width:0;stroke:#a8a89e;}#m-02e1152b1ac5-dark .arrowheadPath{fill:rgba(255, 255, 255, 0);}#m-02e1152b1ac5-dark .edgePath .path{stroke:#a8a89e;stroke-width:1px;}#m-02e1152b1ac5-dark .flowchart-link{stroke:#a8a89e;fill:none;}#m-02e1152b1ac5-dark .edgeLabel{background-color:#1a1b1e;text-align:center;}#m-02e1152b1ac5-dark .edgeLabel p{background-color:#1a1b1e;}#m-02e1152b1ac5-dark .edgeLabel rect{opacity:0.5;background-color:#1a1b1e;fill:#1a1b1e;}#m-02e1152b1ac5-dark .labelBkg{background-color:rgba(26, 27, 30, 0.5);}#m-02e1152b1ac5-dark .cluster rect{fill:#2a2b2f;stroke:#3f3f46;stroke-width:1px;}#m-02e1152b1ac5-dark .cluster text{fill:#e8e6df;}#m-02e1152b1ac5-dark .cluster span{color:#e8e6df;}#m-02e1152b1ac5-dark div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:12px;background:#7c2d12;border:1px solid #fb923c;border-radius:2px;pointer-events:none;z-index:100;}#m-02e1152b1ac5-dark .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#e8e6df;}#m-02e1152b1ac5-dark rect.text{fill:none;stroke-width:0;}#m-02e1152b1ac5-dark .icon-shape,#m-02e1152b1ac5-dark .image-shape{background-color:#1a1b1e;text-align:center;}#m-02e1152b1ac5-dark .icon-shape p,#m-02e1152b1ac5-dark .image-shape p{background-color:#1a1b1e;padding:2px;}#m-02e1152b1ac5-dark .icon-shape .label rect,#m-02e1152b1ac5-dark .image-shape .label rect{opacity:0.5;background-color:#1a1b1e;fill:#1a1b1e;}#m-02e1152b1ac5-dark .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#m-02e1152b1ac5-dark .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#m-02e1152b1ac5-dark .node .neo-node{stroke:#3f3f46;}#m-02e1152b1ac5-dark [data-look="neo"].node rect,#m-02e1152b1ac5-dark [data-look="neo"].cluster rect,#m-02e1152b1ac5-dark [data-look="neo"].node polygon{stroke:url(#m-02e1152b1ac5-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-02e1152b1ac5-dark [data-look="neo"].node path{stroke:url(#m-02e1152b1ac5-dark-gradient);stroke-width:1px;}#m-02e1152b1ac5-dark [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-02e1152b1ac5-dark [data-look="neo"].node .neo-line path{stroke:#3f3f46;filter:none;}#m-02e1152b1ac5-dark [data-look="neo"].node circle{stroke:url(#m-02e1152b1ac5-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-02e1152b1ac5-dark [data-look="neo"].node circle .state-start{fill:#000000;}#m-02e1152b1ac5-dark [data-look="neo"].icon-shape .icon{fill:url(#m-02e1152b1ac5-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-02e1152b1ac5-dark [data-look="neo"].icon-shape .icon-neo path{stroke:url(#m-02e1152b1ac5-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-02e1152b1ac5-dark :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="m-02e1152b1ac5-dark_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-dark_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-dark_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-dark_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-dark_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-dark_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-dark_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-dark_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-dark_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-dark_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-02e1152b1ac5-dark_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="m-02e1152b1ac5-dark_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M207.593,178L221.005,171.021C234.416,164.042,261.239,150.083,278.151,143.104C295.063,136.125,302.063,136.125,305.563,136.125L309.063,136.125" id="m-02e1152b1ac5-dark-L_System_M_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_System_M_0" data-points="W3sieCI6MjA3LjU5MzI1Nzg3NDAxNTc2LCJ5IjoxNzh9LHsieCI6Mjg4LjA2MjUsInkiOjEzNi4xMjV9LHsieCI6MzEzLjA2MjUsInkiOjEzNi4xMjV9XQ==" data-look="classic" marker-end="url(#m-02e1152b1ac5-dark_flowchart-v2-pointEnd)"/><path d="M207.593,253L221.005,259.979C234.416,266.958,261.239,280.917,282.315,287.896C303.391,294.875,318.719,294.875,326.383,294.875L334.047,294.875" id="m-02e1152b1ac5-dark-L_System_O_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_System_O_0" data-points="W3sieCI6MjA3LjU5MzI1Nzg3NDAxNTc2LCJ5IjoyNTN9LHsieCI6Mjg4LjA2MjUsInkiOjI5NC44NzV9LHsieCI6MzM4LjA0Njg3NSwieSI6Mjk0Ljg3NX1d" data-look="classic" marker-end="url(#m-02e1152b1ac5-dark_flowchart-v2-pointEnd)"/><path d="M537.651,87.375L547.282,82.479C556.913,77.583,576.175,67.792,589.308,63.122C602.44,58.452,609.443,58.904,612.944,59.129L616.446,59.355" id="m-02e1152b1ac5-dark-L_M_A_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_M_A_0" data-points="W3sieCI6NTM3LjY1MSwieSI6ODcuMzc1fSx7IngiOjU5NS40Mzc1LCJ5Ijo1OH0seyJ4Ijo2MjAuNDM3NSwieSI6NTkuNjEyOTAzMjI1ODA2NDV9XQ==" data-look="classic" marker-end="url(#m-02e1152b1ac5-dark_flowchart-v2-pointEnd)"/><path d="M504.267,234.875L519.462,220.292C534.657,205.708,565.047,176.542,585.955,159.033C606.862,141.524,618.287,135.674,623.999,132.749L629.712,129.823" id="m-02e1152b1ac5-dark-L_O_A_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_O_A_0" data-points="W3sieCI6NTA0LjI2Njk0OTE1MjU0MjQsInkiOjIzNC44NzV9LHsieCI6NTk1LjQzNzUsInkiOjE0Ny4zNzV9LHsieCI6NjMzLjI3MjE0NTY2OTI5MTQsInkiOjEyOH1d" data-look="classic" marker-end="url(#m-02e1152b1ac5-dark_flowchart-v2-pointEnd)"/><path d="M880.438,68L884.604,68C888.771,68,897.104,68,904.771,68C912.438,68,919.438,68,922.938,68L926.438,68" id="m-02e1152b1ac5-dark-L_A_H_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_A_H_0" data-points="W3sieCI6ODgwLjQzNzUsInkiOjY4fSx7IngiOjkwNS40Mzc1LCJ5Ijo2OH0seyJ4Ijo5MzAuNDM3NSwieSI6Njh9XQ==" data-look="classic" marker-end="url(#m-02e1152b1ac5-dark_flowchart-v2-pointEnd)"/><path d="M525.58,184.875L537.223,191.646C548.866,198.417,572.152,211.958,588.033,218.729C603.914,225.5,612.391,225.5,616.629,225.5L620.867,225.5" id="m-02e1152b1ac5-dark-L_M_D_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_M_D_0" data-points="W3sieCI6NTI1LjU3OTU0NTQ1NDU0NTUsInkiOjE4NC44NzV9LHsieCI6NTk1LjQzNzUsInkiOjIyNS41fSx7IngiOjYyNC44NjcxODc1LCJ5IjoyMjUuNX1d" data-look="classic" marker-end="url(#m-02e1152b1ac5-dark_flowchart-v2-pointEnd)"/><path d="M545.453,336.204L553.784,339.525C562.115,342.845,578.776,349.485,596.022,352.805C613.268,356.125,631.099,356.125,640.014,356.125L648.93,356.125" id="m-02e1152b1ac5-dark-L_O_R_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_O_R_0" data-points="W3sieCI6NTQ1LjQ1MzEyNSwieSI6MzM2LjIwNDQyNzYxMjg1MDc0fSx7IngiOjU5NS40Mzc1LCJ5IjozNTYuMTI1fSx7IngiOjY1Mi45Mjk2ODc1LCJ5IjozNTYuMTI1fV0=" data-look="classic" marker-end="url(#m-02e1152b1ac5-dark_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_System_M_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_System_O_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_M_A_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_O_A_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_A_H_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_M_D_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_O_R_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="m-02e1152b1ac5-dark-flowchart-System-0" data-look="classic" transform="translate(135.53125, 215.5)"><rect class="basic label-container" style="" x="-127.53125" y="-37.5" width="255.0625" height="75"/><g class="label" style="" transform="translate(-97.53125, -22.5)"><rect/><foreignObject width="195.0625" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Система<br />сервисы, БД, кэш, очереди</p></span></div></foreignObject></g></g><g class="node default" id="m-02e1152b1ac5-dark-flowchart-M-1" data-look="classic" transform="translate(441.75, 136.125)"><rect class="basic label-container" style="" x="-128.6875" y="-48.75" width="257.375" height="97.5"/><g class="label" style="" transform="translate(-98.6875, -33.75)"><rect/><foreignObject width="197.375" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Monitoring<br />known unknowns:<br />заранее заданные метрики</p></span></div></foreignObject></g></g><g class="node default" id="m-02e1152b1ac5-dark-flowchart-O-3" data-look="classic" transform="translate(441.75, 294.875)"><rect class="basic label-container" style="" x="-103.703125" y="-60" width="207.40625" height="120"/><g class="label" style="" transform="translate(-73.703125, -45)"><rect/><foreignObject width="147.40625" height="90"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Observability<br />unknown unknowns:<br />возможность задать<br />новый вопрос</p></span></div></foreignObject></g></g><g class="node default" id="m-02e1152b1ac5-dark-flowchart-A-5" data-look="classic" transform="translate(750.4375, 68)"><rect class="basic label-container" style="" x="-130" y="-60" width="260" height="120"/><g class="label" style="" transform="translate(-100, -45)"><rect/><foreignObject width="200" height="90"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>Alerting<br />правила, которые<br />превращают сигнал в инцидент</p></span></div></foreignObject></g></g><g class="node default" id="m-02e1152b1ac5-dark-flowchart-H-9" data-look="classic" transform="translate(1016.0625, 68)"><rect class="basic label-container" style="" x="-85.625" y="-26.25" width="171.25" height="52.5"/><g class="label" style="" transform="translate(-55.625, -11.25)"><rect/><foreignObject width="111.25" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Человек on-call</p></span></div></foreignObject></g></g><g class="node default" id="m-02e1152b1ac5-dark-flowchart-D-11" data-look="classic" transform="translate(750.4375, 225.5)"><rect class="basic label-container" style="" x="-125.5703125" y="-26.25" width="251.140625" height="52.5"/><g class="label" style="" transform="translate(-95.5703125, -11.25)"><rect/><foreignObject width="191.140625" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Дашборды и SLO-репорты</p></span></div></foreignObject></g></g><g class="node default" id="m-02e1152b1ac5-dark-flowchart-R-13" data-look="classic" transform="translate(750.4375, 356.125)"><rect class="basic label-container" style="" x="-97.5078125" y="-26.25" width="195.015625" height="52.5"/><g class="label" style="" transform="translate(-67.5078125, -11.25)"><rect/><foreignObject width="135.015625" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Root cause analysis</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="m-02e1152b1ac5-dark-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="m-02e1152b1ac5-dark-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><linearGradient id="m-02e1152b1ac5-dark-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#3f3f46" stop-opacity="1"/><stop offset="100%" stop-color="#3f3f46" stop-opacity="1"/></linearGradient></svg>
</div>
</figure><p>В этой триаде SLI — это специально выделенные метрики из мониторинга, которые отражают пользовательский опыт. SLO — правило поверх SLI, которое мы хотим выполнять. Алерты по burn-rate — правила поверх SLO. Observability — страховка на случай, когда SLO сгорает, и нужно понять, <strong>почему именно сейчас и в этом запросе</strong>. Иначе говоря: мониторинг, SLI и SLO живут в плоскости «всё ли в порядке по тем критериям, которые мы назначили». Observability — в плоскости «что именно сейчас не так и почему», когда привычные метрики не дают ответа.</p>
<p>Теперь, с этим словарём — переходим к самому SLI.</p>
<h3 id="что-такое-sli">Что такое SLI</h3>
<p><strong>SLI (Service Level Indicator)</strong> — измеримая характеристика, которая отражает качество одного аспекта обслуживания пользователя. Ключевое слово — <strong>отражает</strong>. SLI меряет не «что система делает», а «насколько хорошо это видит пользователь».</p>
<p>Каноническая формула SLI — доля «хороших» событий от всех релевантных:</p>
$$ \text{SLI} = \dfrac{\text{количество хороших событий}}{\text{количество всех релевантных событий}} \times 100\% $$<p>Что такое «хорошее событие» и какие события «релевантны» — определяется <strong>явно</strong>, иначе SLI получится бесполезным. Самая частая ошибка здесь — посчитать «все HTTP 2xx» как «хорошие». Так делать нельзя по двум причинам:</p>
<ol>
<li><strong>Не все 2xx одинаковы.</strong> Запрос, ответивший <code>200 OK</code> за 5 секунд, формально успешен, но для пользователя это провал. SLI должен учитывать порог по латентности, иначе он маскирует деградацию.</li>
<li><strong>Не все запросы одинаковы.</strong> Health-чек с другого сервиса тоже летит как HTTP-запрос, но на пользовательский опыт не влияет. Если он попал в знаменатель — SLI размылся.</li>
</ol>
<h3 id="формат-хорошего-sli">Формат хорошего SLI</h3>
<p>У хорошего SLI всегда три явные части:</p>
<ul>
<li><strong>Числитель.</strong> Что считаем «хорошим» — порог по времени, корректности, объёму. Должно быть ясно, что туда входит, а что нет.</li>
<li><strong>Знаменатель.</strong> Какие события считаем релевантными — фильтр по эндпоинту, источнику трафика, типу запроса. Должно быть ясно, какие исключаем.</li>
<li><strong>Окно агрегации.</strong> За какой период считаем — 5 минут для алертов, 30 дней для отчётности. Без окна SLI — не число, а описание формы.</li>
</ul>
<h3 id="конкретные-sli-для-нашего-кейса">Конкретные SLI для нашего кейса</h3>
<p>Возьмём ключевые шаги из таблицы НФТ и сформулируем для них SLI. Останавливаюсь на четырёх — этого достаточно, чтобы показать механику; в реальном проде их обычно 4–8 на сервис.</p>
<p><strong>SLI-1 — Latency-SLI на шаге 4 «получение выдачи».</strong></p>
<blockquote><p>Доля поисковых запросов, на которые система ответила за время <code>&lt; 500 ms</code>, от всех релевантных поисковых запросов с пользовательского трафика, за окно 30 дней.</p>
</blockquote><ul>
<li><strong>Числитель:</strong> запросы с <code>status in {200, 204}</code> AND <code>request_duration &lt; 500 ms</code>.</li>
<li><strong>Знаменатель:</strong> запросы с <code>status in {200, 204, 5xx}</code> плюс таймауты, исключая 4xx-валидационные ответы (всё, что не health-check, не synthetic-проба, не вызов внутреннего сервиса).</li>
<li><strong>Окно:</strong> 30 дней rolling.</li>
</ul>
<p>Заметь две вещи. Во-первых, <strong>5xx в знаменателе</strong>: не учитывать их — значит нарисовать оптимистичную картинку, в которой провал «технически не считается». Во-вторых, <strong>4xx-ответы пользовательского трафика в знаменатель не идут</strong> — по канонической Google SRE-практике (глава «Service Level Objectives» в SRE Workbook, O&rsquo;Reilly, 2018) это корректное отвержение невалидного запроса (например, поисковая строка пустая или превышает лимит длины), система отработала ожидаемо. Включать их в знаменатель — раздуть его и сделать SLI оптимистичнее, чем он есть на самом деле.</p>
<p><strong>SLI-2 — Availability-SLI на шаге 4.</strong></p>
<blockquote><p>Доля поисковых запросов, завершившихся успешно (не 5xx, не таймаут), от всех релевантных запросов, за окно 30 дней.</p>
</blockquote><p>Это «классическая» availability. Но смотрим только на пользовательский трафик в шаг 4, не «по системе целиком». Знаменатель тот же, что у SLI-1, — 4xx-валидационные ответы исключены.</p>
<p><strong>SLI-3 — Correctness-SLI на шаге 4.</strong></p>
<blockquote><p>Доля поисковых запросов, вернувших непустую и валидную выдачу, от всех запросов, для которых должна была быть хотя бы одна позиция (не 0-result-by-design).</p>
</blockquote><p>Этот SLI сложнее, потому что нужно знать «должна была быть выдача или нет». Меряется офлайн-сэмплингом: берём X% запросов, прогоняем эталонный поиск, сравниваем долю «должно быть, но не было».</p>
<p><strong>SLI-4 — Freshness-SLI на шаге 6 «клик в карточку».</strong></p>
<blockquote><p>Доля переходов в карточку, на которых цена и наличие отображены не старше 60 секунд от истинного состояния товара.</p>
</blockquote><p>Этот SLI напрямую защищает от ситуации «увидел одну цену в выдаче — на чекауте другая». Без него ты рискуешь не техническим инцидентом, а <strong>репутационным</strong>: пользователь зол, возвраты растут, рейтинг продавцов падает.</p>
<p>Аналогичные SLI строятся для autocomplete, фильтра, отправки запроса по той же механике — повторять не буду. Достаточно принципа: один шаг — один или несколько SLI, каждый с явным числителем, знаменателем и окном.</p>
<h3 id="что-мы-не-берём-как-sli">Что мы НЕ берём как SLI</h3>
<p>Контрпримеры, чтобы калибровать чутьё:</p>
<ul>
<li><strong>CPU/Memory utilization.</strong> Это <strong>служебный сигнал</strong>, а не SLI. Пользователь не страдает от того, что у тебя CPU 80% — он страдает только если это превратилось в latency или 5xx. Утилизация — причина, SLI — следствие.</li>
<li><strong>Количество подов в реплике.</strong> Тоже служебный. Метрика для capacity planning, не для SLO.</li>
<li><strong>Среднее время ответа.</strong> Опасный «псевдо-SLI». Скрывает хвосты — а хвосты это и есть пользовательская боль. Только перцентили: P95 как минимум, P99 для критичных шагов.</li>
</ul>
<p>Дальше — превращаем SLI в обещание самим себе. То есть в SLO.</p>
<h2 id="шаг-4-slo-как-контракт-и-error-budget-математически">Шаг 4: SLO как контракт и error budget математически</h2>
<p><strong>SLO (Service Level Objective)</strong> — целевое значение SLI на оговорённом окне. Если SLI отвечает на вопрос «как было», то SLO — «как мы обещаем, что должно быть».</p>
<p>Формула:</p>
$$ \text{SLO}: \text{SLI} \geq T \text{ (на окне } W) $$<p>Где <code>T</code> — таргет (например, <code>99.9</code>), <code>W</code> — окно агрегации (например, 30 дней rolling).</p>
<h3 id="slo-для-нашего-sli-1">SLO для нашего SLI-1</h3>
<p>Берём SLI-1 (latency-SLI поиска: доля запросов <code>&lt; 500 ms</code>):</p>
<blockquote><p>SLO: 99.9% поисковых запросов отвечают быстрее <code>500 ms</code> на rolling-окне 30 дней.</p>
</blockquote><p>Это полноценный контракт. И он автоматически рождает <strong>error budget</strong>.</p>
<h3 id="error-budget-математически">Error budget математически</h3>
<p>Error budget — это <strong>разрешённая доля «плохих» событий</strong> за период:</p>
$$ \text{Error Budget} = 1 - \text{SLO} $$<p>Для SLO <code>99.9%</code> это <code>0.1%</code>, или 1 «плохой» запрос из 1000.</p>
<p>Дальше переводим в абсолютные значения. Берём типовой день нашего маркетплейса:</p>
<ul>
<li>Пиковый RPS: <code>30 000 запросов/сек</code>.</li>
<li>Средний по дню (с учётом ночи): <code>~10 000 запросов/сек</code>.</li>
<li>Запросов в сутки: <code>10 000 × 86 400 ≈ 864 000 000</code>.</li>
<li>Запросов за 30-дневное окно: <code>~26 миллиардов</code>.</li>
<li>Допустимая доля «плохих» при SLO <code>99.9%</code>: <code>0.1%</code>.</li>
<li><strong>Бюджет ошибок за 30 дней: ~26 миллионов запросов.</strong></li>
</ul>
<p>Если перевести в эквивалент простоя — двумя срезами, на пике и при средней нагрузке за сутки:</p>
<table>
  <thead>
      <tr>
          <th>SLO</th>
          <th>Бюджет ошибок</th>
          <th>На пике (30k RPS)</th>
          <th>При средней нагрузке (~10k RPS)</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>99.0%</td>
          <td>~260M запросов</td>
          <td>~2 ч 24 мин</td>
          <td>~7 ч 13 мин</td>
      </tr>
      <tr>
          <td>99.9%</td>
          <td>~26M запросов</td>
          <td>~14 мин 27 с</td>
          <td>~43 мин 20 с</td>
      </tr>
      <tr>
          <td>99.99%</td>
          <td>~2.6M запросов</td>
          <td>~1 мин 27 с</td>
          <td>~4 мин 20 с</td>
      </tr>
      <tr>
          <td>99.999%</td>
          <td>~260K запросов</td>
          <td>~8.7 с</td>
          <td>~26 с</td>
      </tr>
  </tbody>
</table>
<p>Две колонки — потому что бюджет ошибок «горит» неравномерно. На пике RPS ты расходуешь запросы в три раза быстрее, чем в среднем по суткам, — поэтому инцидент в Чёрную пятницу обходится сильно дороже, чем тот же инцидент во вторник в 4 утра. Колонка «На пике» — про худший случай, на который надо проектировать SLO; колонка «При средней нагрузке» — про календарный «эквивалент полного простоя», который чаще видят в отчётах.</p>
<p>Это не просто разные числа — это разные <strong>физические возможности</strong>. На пике 8.7 секунд в месяц означают, что человек не успеет даже заметить пейдж: реакция должна быть автоматической. 7 часов в месяц при средней нагрузке — означают, что можно позволить себе ручной разбор каждого инцидента.</p>
<h3 id="что-error-budget-значит-на-практике">Что error budget значит на практике</h3>
<p>Бюджет — не «допустимый ущерб», а <strong>бюджет на риск</strong>. На него тратятся:</p>
<ul>
<li><strong>Деплои.</strong> Каждый релиз — ставка из бюджета. Откат + время на восстановление = израсходованные ошибки.</li>
<li><strong>Эксперименты.</strong> A/B-тесты, постепенный rollout, фиче-флаги — потенциальные источники регрессии.</li>
<li><strong>Учения.</strong> Game days, chaos engineering, плановые отказы — расходуют бюджет, но взамен дают уверенность в стабильности на реальных инцидентах.</li>
</ul>
<p>Если бюджет полностью сгорел до конца окна — это сигнал к <strong>freeze: остановить рискованные деплои и вкладываться в reliability</strong>, пока окно не сдвинется. Если бюджет жирный — это <strong>разрешение рисковать</strong>: ускорять выкатки, экспериментировать, рефакторить.</p>
<p>К теме «бюджет как валюта в спорах» вернусь в разделе про error budget как арбитр. Сейчас важно зафиксировать одно: <strong>SLO без error budget — это пожелание, а не контракт.</strong> Бюджет — то, что превращает SLO из табло в инструмент принятия решений.</p>
<p>Дальше — главный технический разбор статьи. Берём один и тот же поиск маркетплейса и прокручиваем сквозь три уровня SLO: 99.0%, 99.9%, 99.99%. Покажу, что меняется в архитектуре, что — в стоимости, что — в эксплуатационной нагрузке.</p>
<h2 id="один-кейс--три-slo--три-архитектуры">Один кейс — три SLO — три архитектуры</h2>
<p>Дальше беру тот же поиск маркетплейса с теми же параметрами и проектирую <strong>три разные системы</strong>. Меняется структура read path, выбор технологий, capacity, RTO/RPO, эксплуатационная модель. Остаётся постановка задачи, объём каталога (50M), пиковый RPS (30k), 5 регионов, 70% mobile.</p>
<p>Структура каждого подраздела одинаковая: бюджет → схема read path → числа (capacity, RTO/RPO, кэш, индекс) → что добавилось по сравнению с предыдущим уровнем и зачем → чего намеренно НЕ делаем.</p>
<h3 id="slo-990-дешёвая-надёжность-для-не-критичных-сценариев">SLO 99.0%: «дешёвая надёжность» для не-критичных сценариев</h3>
<p><strong>Бюджет:</strong> ~260M «плохих» запросов за 30 дней, или <strong>~2 ч 24 мин</strong> полного даунтайма на пике / <strong>~7 ч 13 мин</strong> при средней нагрузке. Почти полный рабочий день на инциденты в месяц — много, но выживаемо при ручной операционной модели.</p>
<p><strong>Когда уместно:</strong> внутренние инструменты, ранний MVP стартапа, неосновные feature-paths в большом продукте (например, search в каталоге сторонних услуг, не кормящий основную конверсию).</p>
<p><strong>Read path:</strong></p>
<figure class="mermaid mermaid--prerendered" aria-label="Mermaid diagram">
<div class="mermaid-svg mermaid-svg--light">
<svg id="m-eda2ce005e57-light" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 1028.84px; background-color: transparent;" viewBox="0 0 1028.84375 138.9862823486328" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#m-eda2ce005e57-light{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;fill:#1c1c1f;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#m-eda2ce005e57-light .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#m-eda2ce005e57-light .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#m-eda2ce005e57-light .error-icon{fill:#fee2e2;}#m-eda2ce005e57-light .error-text{fill:#7f1d1d;stroke:#7f1d1d;}#m-eda2ce005e57-light .edge-thickness-normal{stroke-width:1px;}#m-eda2ce005e57-light .edge-thickness-thick{stroke-width:3.5px;}#m-eda2ce005e57-light .edge-pattern-solid{stroke-dasharray:0;}#m-eda2ce005e57-light .edge-thickness-invisible{stroke-width:0;fill:none;}#m-eda2ce005e57-light .edge-pattern-dashed{stroke-dasharray:3;}#m-eda2ce005e57-light .edge-pattern-dotted{stroke-dasharray:2;}#m-eda2ce005e57-light .marker{fill:#5b5b62;stroke:#5b5b62;}#m-eda2ce005e57-light .marker.cross{stroke:#5b5b62;}#m-eda2ce005e57-light svg{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;}#m-eda2ce005e57-light p{margin:0;}#m-eda2ce005e57-light .label{font-family:Inter,system-ui,-apple-system,sans-serif;color:#1c1c1f;}#m-eda2ce005e57-light .cluster-label text{fill:#1c1c1f;}#m-eda2ce005e57-light .cluster-label span{color:#1c1c1f;}#m-eda2ce005e57-light .cluster-label span p{background-color:transparent;}#m-eda2ce005e57-light .label text,#m-eda2ce005e57-light span{fill:#1c1c1f;color:#1c1c1f;}#m-eda2ce005e57-light .node rect,#m-eda2ce005e57-light .node circle,#m-eda2ce005e57-light .node ellipse,#m-eda2ce005e57-light .node polygon,#m-eda2ce005e57-light .node path{fill:#ffffff;stroke:#c8c5bb;stroke-width:1px;}#m-eda2ce005e57-light .rough-node .label text,#m-eda2ce005e57-light .node .label text,#m-eda2ce005e57-light .image-shape .label,#m-eda2ce005e57-light .icon-shape .label{text-anchor:middle;}#m-eda2ce005e57-light .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#m-eda2ce005e57-light .rough-node .label,#m-eda2ce005e57-light .node .label,#m-eda2ce005e57-light .image-shape .label,#m-eda2ce005e57-light .icon-shape .label{text-align:center;}#m-eda2ce005e57-light .node.clickable{cursor:pointer;}#m-eda2ce005e57-light .root .anchor path{fill:#5b5b62!important;stroke-width:0;stroke:#5b5b62;}#m-eda2ce005e57-light .arrowheadPath{fill:rgba(255, 255, 255, 0);}#m-eda2ce005e57-light .edgePath .path{stroke:#5b5b62;stroke-width:1px;}#m-eda2ce005e57-light .flowchart-link{stroke:#5b5b62;fill:none;}#m-eda2ce005e57-light .edgeLabel{background-color:#fafaf7;text-align:center;}#m-eda2ce005e57-light .edgeLabel p{background-color:#fafaf7;}#m-eda2ce005e57-light .edgeLabel rect{opacity:0.5;background-color:#fafaf7;fill:#fafaf7;}#m-eda2ce005e57-light .labelBkg{background-color:rgba(250, 250, 247, 0.5);}#m-eda2ce005e57-light .cluster rect{fill:#f3f1ed;stroke:#c8c5bb;stroke-width:1px;}#m-eda2ce005e57-light .cluster text{fill:#1c1c1f;}#m-eda2ce005e57-light .cluster span{color:#1c1c1f;}#m-eda2ce005e57-light div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:12px;background:#fed7aa;border:1px solid #c2410c;border-radius:2px;pointer-events:none;z-index:100;}#m-eda2ce005e57-light .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#1c1c1f;}#m-eda2ce005e57-light rect.text{fill:none;stroke-width:0;}#m-eda2ce005e57-light .icon-shape,#m-eda2ce005e57-light .image-shape{background-color:#fafaf7;text-align:center;}#m-eda2ce005e57-light .icon-shape p,#m-eda2ce005e57-light .image-shape p{background-color:#fafaf7;padding:2px;}#m-eda2ce005e57-light .icon-shape .label rect,#m-eda2ce005e57-light .image-shape .label rect{opacity:0.5;background-color:#fafaf7;fill:#fafaf7;}#m-eda2ce005e57-light .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#m-eda2ce005e57-light .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#m-eda2ce005e57-light .node .neo-node{stroke:#c8c5bb;}#m-eda2ce005e57-light [data-look="neo"].node rect,#m-eda2ce005e57-light [data-look="neo"].cluster rect,#m-eda2ce005e57-light [data-look="neo"].node polygon{stroke:url(#m-eda2ce005e57-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-eda2ce005e57-light [data-look="neo"].node path{stroke:url(#m-eda2ce005e57-light-gradient);stroke-width:1px;}#m-eda2ce005e57-light [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-eda2ce005e57-light [data-look="neo"].node .neo-line path{stroke:#c8c5bb;filter:none;}#m-eda2ce005e57-light [data-look="neo"].node circle{stroke:url(#m-eda2ce005e57-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-eda2ce005e57-light [data-look="neo"].node circle .state-start{fill:#000000;}#m-eda2ce005e57-light [data-look="neo"].icon-shape .icon{fill:url(#m-eda2ce005e57-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-eda2ce005e57-light [data-look="neo"].icon-shape .icon-neo path{stroke:url(#m-eda2ce005e57-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-eda2ce005e57-light :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="m-eda2ce005e57-light_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-light_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-light_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-light_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-light_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-light_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-light_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-light_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-light_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-light_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-light_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="m-eda2ce005e57-light_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M163.348,55.5L168.157,53.833C172.966,52.167,182.585,48.833,190.894,47.167C199.203,45.5,206.203,45.5,209.703,45.5L213.203,45.5" id="m-eda2ce005e57-light-L_U_LB_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_U_LB_0" data-points="W3sieCI6MTYzLjM0NzUyMTU1MTcyNDEzLCJ5Ijo1NS41fSx7IngiOjE5Mi4yMDMxMjUsInkiOjQ1LjV9LHsieCI6MjE3LjIwMzEyNSwieSI6NDUuNX1d" data-look="classic" marker-end="url(#m-eda2ce005e57-light_flowchart-v2-pointEnd)"/><path d="M374.516,45.5L378.682,45.5C382.849,45.5,391.182,45.5,398.884,46.69C406.585,47.879,413.655,50.259,417.19,51.448L420.725,52.638" id="m-eda2ce005e57-light-L_LB_A_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_LB_A_0" data-points="W3sieCI6Mzc0LjUxNTYyNSwieSI6NDUuNX0seyJ4IjozOTkuNTE1NjI1LCJ5Ijo0NS41fSx7IngiOjQyNC41MTU2MjUsInkiOjUzLjkxMzcyMzA3MjQ1OTU2fV0=" data-look="classic" marker-end="url(#m-eda2ce005e57-light_flowchart-v2-pointEnd)"/><path d="M589.938,53.914L594.104,52.511C598.271,51.109,606.604,48.305,614.271,46.902C621.938,45.5,628.938,45.5,632.438,45.5L635.938,45.5" id="m-eda2ce005e57-light-L_A_C_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_A_C_0" data-points="W3sieCI6NTg5LjkzNzUsInkiOjUzLjkxMzcyMzA3MjQ1OTU2fSx7IngiOjYxNC45Mzc1LCJ5Ijo0NS41fSx7IngiOjYzOS45Mzc1LCJ5Ijo0NS41fV0=" data-look="classic" marker-end="url(#m-eda2ce005e57-light_flowchart-v2-pointEnd)"/><path d="M807.797,45.5L814.579,45.5C821.362,45.5,834.927,45.5,847.861,47.593C860.795,49.687,873.098,53.873,879.249,55.967L885.401,58.06" id="m-eda2ce005e57-light-L_C_P_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_C_P_0" data-points="W3sieCI6ODA3Ljc5Njg3NSwieSI6NDUuNX0seyJ4Ijo4NDguNDkyMTg3NSwieSI6NDUuNX0seyJ4Ijo4ODkuMTg3NSwieSI6NTkuMzQ4NjQzMTk3NjUzMTA0fV0=" data-look="classic" marker-end="url(#m-eda2ce005e57-light_flowchart-v2-pointEnd)"/><path d="M889.188,104.151L882.405,106.459C875.622,108.768,862.057,113.384,834.504,115.692C806.951,118,765.409,118,726.483,118C687.557,118,651.247,118,629.558,116.81C607.868,115.621,600.798,113.241,597.263,112.052L593.729,110.862" id="m-eda2ce005e57-light-L_P_A_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_P_A_0" data-points="W3sieCI6ODg5LjE4NzUsInkiOjEwNC4xNTEzNTY4MDIzNDY5fSx7IngiOjg0OC40OTIxODc1LCJ5IjoxMTh9LHsieCI6NzIzLjg2NzE4NzUsInkiOjExOH0seyJ4Ijo2MTQuOTM3NSwieSI6MTE4fSx7IngiOjU4OS45Mzc1LCJ5IjoxMDkuNTg2Mjc2OTI3NTQwNDR9XQ==" data-look="classic" marker-end="url(#m-eda2ce005e57-light_flowchart-v2-pointEnd)"/><path d="M424.516,109.586L420.349,110.989C416.182,112.391,407.849,115.195,386.406,116.598C364.964,118,330.411,118,295.859,118C261.307,118,226.755,118,205.3,116.552C183.844,115.103,175.486,112.207,171.306,110.758L167.127,109.31" id="m-eda2ce005e57-light-L_A_U_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_A_U_0" data-points="W3sieCI6NDI0LjUxNTYyNSwieSI6MTA5LjU4NjI3NjkyNzU0MDQ0fSx7IngiOjM5OS41MTU2MjUsInkiOjExOH0seyJ4IjoyOTUuODU5Mzc1LCJ5IjoxMTh9LHsieCI6MTkyLjIwMzEyNSwieSI6MTE4fSx7IngiOjE2My4zNDc1MjE1NTE3MjQxMywieSI6MTA4fV0=" data-look="classic" marker-end="url(#m-eda2ce005e57-light_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_U_LB_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_LB_A_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_A_C_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(848.4921875, 45.5)"><g class="label" data-id="L_C_P_0" transform="translate(-15.6953125, -11.25)"><foreignObject width="31.390625" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>miss</p></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_P_A_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_A_U_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="m-eda2ce005e57-light-flowchart-U-0" data-look="classic" transform="translate(87.6015625, 81.75)"><rect class="basic label-container" style="" x="-79.6015625" y="-26.25" width="159.203125" height="52.5"/><g class="label" style="" transform="translate(-49.6015625, -11.25)"><rect/><foreignObject width="99.203125" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Пользователь</p></span></div></foreignObject></g></g><g class="node default" id="m-eda2ce005e57-light-flowchart-LB-1" data-look="classic" transform="translate(295.859375, 45.5)"><rect class="basic label-container" style="" x="-78.65625" y="-37.5" width="157.3125" height="75"/><g class="label" style="" transform="translate(-48.65625, -22.5)"><rect/><foreignObject width="97.3125" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Load Balancer<br />1 регион</p></span></div></foreignObject></g></g><g class="node default" id="m-eda2ce005e57-light-flowchart-A-3" data-look="classic" transform="translate(507.2265625, 81.75)"><rect class="basic label-container" style="" x="-82.7109375" y="-37.5" width="165.421875" height="75"/><g class="label" style="" transform="translate(-52.7109375, -22.5)"><rect/><foreignObject width="105.421875" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>App-сервер<br />3–5 инстансов</p></span></div></foreignObject></g></g><g class="node default" id="m-eda2ce005e57-light-flowchart-C-5" data-look="classic" transform="translate(723.8671875, 45.5)"><rect class="basic label-container" style="" x="-83.9296875" y="-37.5" width="167.859375" height="75"/><g class="label" style="" transform="translate(-53.9296875, -22.5)"><rect/><foreignObject width="107.859375" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>In-memory LRU<br />per-instance</p></span></div></foreignObject></g></g><g class="node default" id="m-eda2ce005e57-light-flowchart-P-7" data-look="classic" transform="translate(955.015625, 81.75)"><path d="M0,12.8241811761841 a65.828125,12.8241811761841 0,0,0 131.65625,0 a65.828125,12.8241811761841 0,0,0 -131.65625,0 l0,72.8241811761841 a65.828125,12.8241811761841 0,0,0 131.65625,0 l0,-72.8241811761841" class="basic label-container outer-path" style="" transform="translate(-65.828125, -49.23627176427615)"/><g class="label" style="" transform="translate(-58.328125, -12.5)"><rect/><foreignObject width="116.65625" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Postgres primary<br />+ 1 read replica</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="m-eda2ce005e57-light-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="m-eda2ce005e57-light-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><linearGradient id="m-eda2ce005e57-light-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#c8c5bb" stop-opacity="1"/><stop offset="100%" stop-color="#c8c5bb" stop-opacity="1"/></linearGradient></svg>
</div>
<div class="mermaid-svg mermaid-svg--dark">
<svg id="m-eda2ce005e57-dark" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 1028.84px; background-color: transparent;" viewBox="0 0 1028.84375 138.9862823486328" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#m-eda2ce005e57-dark{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;fill:#e8e6df;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#m-eda2ce005e57-dark .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#m-eda2ce005e57-dark .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#m-eda2ce005e57-dark .error-icon{fill:#7f1d1d;}#m-eda2ce005e57-dark .error-text{fill:#fecaca;stroke:#fecaca;}#m-eda2ce005e57-dark .edge-thickness-normal{stroke-width:1px;}#m-eda2ce005e57-dark .edge-thickness-thick{stroke-width:3.5px;}#m-eda2ce005e57-dark .edge-pattern-solid{stroke-dasharray:0;}#m-eda2ce005e57-dark .edge-thickness-invisible{stroke-width:0;fill:none;}#m-eda2ce005e57-dark .edge-pattern-dashed{stroke-dasharray:3;}#m-eda2ce005e57-dark .edge-pattern-dotted{stroke-dasharray:2;}#m-eda2ce005e57-dark .marker{fill:#a8a89e;stroke:#a8a89e;}#m-eda2ce005e57-dark .marker.cross{stroke:#a8a89e;}#m-eda2ce005e57-dark svg{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;}#m-eda2ce005e57-dark p{margin:0;}#m-eda2ce005e57-dark .label{font-family:Inter,system-ui,-apple-system,sans-serif;color:#e8e6df;}#m-eda2ce005e57-dark .cluster-label text{fill:#e8e6df;}#m-eda2ce005e57-dark .cluster-label span{color:#e8e6df;}#m-eda2ce005e57-dark .cluster-label span p{background-color:transparent;}#m-eda2ce005e57-dark .label text,#m-eda2ce005e57-dark span{fill:#e8e6df;color:#e8e6df;}#m-eda2ce005e57-dark .node rect,#m-eda2ce005e57-dark .node circle,#m-eda2ce005e57-dark .node ellipse,#m-eda2ce005e57-dark .node polygon,#m-eda2ce005e57-dark .node path{fill:#23252a;stroke:#3f3f46;stroke-width:1px;}#m-eda2ce005e57-dark .rough-node .label text,#m-eda2ce005e57-dark .node .label text,#m-eda2ce005e57-dark .image-shape .label,#m-eda2ce005e57-dark .icon-shape .label{text-anchor:middle;}#m-eda2ce005e57-dark .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#m-eda2ce005e57-dark .rough-node .label,#m-eda2ce005e57-dark .node .label,#m-eda2ce005e57-dark .image-shape .label,#m-eda2ce005e57-dark .icon-shape .label{text-align:center;}#m-eda2ce005e57-dark .node.clickable{cursor:pointer;}#m-eda2ce005e57-dark .root .anchor path{fill:#a8a89e!important;stroke-width:0;stroke:#a8a89e;}#m-eda2ce005e57-dark .arrowheadPath{fill:rgba(255, 255, 255, 0);}#m-eda2ce005e57-dark .edgePath .path{stroke:#a8a89e;stroke-width:1px;}#m-eda2ce005e57-dark .flowchart-link{stroke:#a8a89e;fill:none;}#m-eda2ce005e57-dark .edgeLabel{background-color:#1a1b1e;text-align:center;}#m-eda2ce005e57-dark .edgeLabel p{background-color:#1a1b1e;}#m-eda2ce005e57-dark .edgeLabel rect{opacity:0.5;background-color:#1a1b1e;fill:#1a1b1e;}#m-eda2ce005e57-dark .labelBkg{background-color:rgba(26, 27, 30, 0.5);}#m-eda2ce005e57-dark .cluster rect{fill:#2a2b2f;stroke:#3f3f46;stroke-width:1px;}#m-eda2ce005e57-dark .cluster text{fill:#e8e6df;}#m-eda2ce005e57-dark .cluster span{color:#e8e6df;}#m-eda2ce005e57-dark div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:12px;background:#7c2d12;border:1px solid #fb923c;border-radius:2px;pointer-events:none;z-index:100;}#m-eda2ce005e57-dark .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#e8e6df;}#m-eda2ce005e57-dark rect.text{fill:none;stroke-width:0;}#m-eda2ce005e57-dark .icon-shape,#m-eda2ce005e57-dark .image-shape{background-color:#1a1b1e;text-align:center;}#m-eda2ce005e57-dark .icon-shape p,#m-eda2ce005e57-dark .image-shape p{background-color:#1a1b1e;padding:2px;}#m-eda2ce005e57-dark .icon-shape .label rect,#m-eda2ce005e57-dark .image-shape .label rect{opacity:0.5;background-color:#1a1b1e;fill:#1a1b1e;}#m-eda2ce005e57-dark .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#m-eda2ce005e57-dark .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#m-eda2ce005e57-dark .node .neo-node{stroke:#3f3f46;}#m-eda2ce005e57-dark [data-look="neo"].node rect,#m-eda2ce005e57-dark [data-look="neo"].cluster rect,#m-eda2ce005e57-dark [data-look="neo"].node polygon{stroke:url(#m-eda2ce005e57-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-eda2ce005e57-dark [data-look="neo"].node path{stroke:url(#m-eda2ce005e57-dark-gradient);stroke-width:1px;}#m-eda2ce005e57-dark [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-eda2ce005e57-dark [data-look="neo"].node .neo-line path{stroke:#3f3f46;filter:none;}#m-eda2ce005e57-dark [data-look="neo"].node circle{stroke:url(#m-eda2ce005e57-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-eda2ce005e57-dark [data-look="neo"].node circle .state-start{fill:#000000;}#m-eda2ce005e57-dark [data-look="neo"].icon-shape .icon{fill:url(#m-eda2ce005e57-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-eda2ce005e57-dark [data-look="neo"].icon-shape .icon-neo path{stroke:url(#m-eda2ce005e57-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-eda2ce005e57-dark :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="m-eda2ce005e57-dark_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-dark_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-dark_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-dark_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-dark_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-dark_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-dark_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-dark_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-dark_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-dark_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-eda2ce005e57-dark_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="m-eda2ce005e57-dark_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M163.348,55.5L168.157,53.833C172.966,52.167,182.585,48.833,190.894,47.167C199.203,45.5,206.203,45.5,209.703,45.5L213.203,45.5" id="m-eda2ce005e57-dark-L_U_LB_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_U_LB_0" data-points="W3sieCI6MTYzLjM0NzUyMTU1MTcyNDEzLCJ5Ijo1NS41fSx7IngiOjE5Mi4yMDMxMjUsInkiOjQ1LjV9LHsieCI6MjE3LjIwMzEyNSwieSI6NDUuNX1d" data-look="classic" marker-end="url(#m-eda2ce005e57-dark_flowchart-v2-pointEnd)"/><path d="M374.516,45.5L378.682,45.5C382.849,45.5,391.182,45.5,398.884,46.69C406.585,47.879,413.655,50.259,417.19,51.448L420.725,52.638" id="m-eda2ce005e57-dark-L_LB_A_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_LB_A_0" data-points="W3sieCI6Mzc0LjUxNTYyNSwieSI6NDUuNX0seyJ4IjozOTkuNTE1NjI1LCJ5Ijo0NS41fSx7IngiOjQyNC41MTU2MjUsInkiOjUzLjkxMzcyMzA3MjQ1OTU2fV0=" data-look="classic" marker-end="url(#m-eda2ce005e57-dark_flowchart-v2-pointEnd)"/><path d="M589.938,53.914L594.104,52.511C598.271,51.109,606.604,48.305,614.271,46.902C621.938,45.5,628.938,45.5,632.438,45.5L635.938,45.5" id="m-eda2ce005e57-dark-L_A_C_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_A_C_0" data-points="W3sieCI6NTg5LjkzNzUsInkiOjUzLjkxMzcyMzA3MjQ1OTU2fSx7IngiOjYxNC45Mzc1LCJ5Ijo0NS41fSx7IngiOjYzOS45Mzc1LCJ5Ijo0NS41fV0=" data-look="classic" marker-end="url(#m-eda2ce005e57-dark_flowchart-v2-pointEnd)"/><path d="M807.797,45.5L814.579,45.5C821.362,45.5,834.927,45.5,847.861,47.593C860.795,49.687,873.098,53.873,879.249,55.967L885.401,58.06" id="m-eda2ce005e57-dark-L_C_P_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_C_P_0" data-points="W3sieCI6ODA3Ljc5Njg3NSwieSI6NDUuNX0seyJ4Ijo4NDguNDkyMTg3NSwieSI6NDUuNX0seyJ4Ijo4ODkuMTg3NSwieSI6NTkuMzQ4NjQzMTk3NjUzMTA0fV0=" data-look="classic" marker-end="url(#m-eda2ce005e57-dark_flowchart-v2-pointEnd)"/><path d="M889.188,104.151L882.405,106.459C875.622,108.768,862.057,113.384,834.504,115.692C806.951,118,765.409,118,726.483,118C687.557,118,651.247,118,629.558,116.81C607.868,115.621,600.798,113.241,597.263,112.052L593.729,110.862" id="m-eda2ce005e57-dark-L_P_A_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_P_A_0" data-points="W3sieCI6ODg5LjE4NzUsInkiOjEwNC4xNTEzNTY4MDIzNDY5fSx7IngiOjg0OC40OTIxODc1LCJ5IjoxMTh9LHsieCI6NzIzLjg2NzE4NzUsInkiOjExOH0seyJ4Ijo2MTQuOTM3NSwieSI6MTE4fSx7IngiOjU4OS45Mzc1LCJ5IjoxMDkuNTg2Mjc2OTI3NTQwNDR9XQ==" data-look="classic" marker-end="url(#m-eda2ce005e57-dark_flowchart-v2-pointEnd)"/><path d="M424.516,109.586L420.349,110.989C416.182,112.391,407.849,115.195,386.406,116.598C364.964,118,330.411,118,295.859,118C261.307,118,226.755,118,205.3,116.552C183.844,115.103,175.486,112.207,171.306,110.758L167.127,109.31" id="m-eda2ce005e57-dark-L_A_U_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_A_U_0" data-points="W3sieCI6NDI0LjUxNTYyNSwieSI6MTA5LjU4NjI3NjkyNzU0MDQ0fSx7IngiOjM5OS41MTU2MjUsInkiOjExOH0seyJ4IjoyOTUuODU5Mzc1LCJ5IjoxMTh9LHsieCI6MTkyLjIwMzEyNSwieSI6MTE4fSx7IngiOjE2My4zNDc1MjE1NTE3MjQxMywieSI6MTA4fV0=" data-look="classic" marker-end="url(#m-eda2ce005e57-dark_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_U_LB_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_LB_A_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_A_C_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(848.4921875, 45.5)"><g class="label" data-id="L_C_P_0" transform="translate(-15.6953125, -11.25)"><foreignObject width="31.390625" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>miss</p></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_P_A_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_A_U_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="m-eda2ce005e57-dark-flowchart-U-0" data-look="classic" transform="translate(87.6015625, 81.75)"><rect class="basic label-container" style="" x="-79.6015625" y="-26.25" width="159.203125" height="52.5"/><g class="label" style="" transform="translate(-49.6015625, -11.25)"><rect/><foreignObject width="99.203125" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Пользователь</p></span></div></foreignObject></g></g><g class="node default" id="m-eda2ce005e57-dark-flowchart-LB-1" data-look="classic" transform="translate(295.859375, 45.5)"><rect class="basic label-container" style="" x="-78.65625" y="-37.5" width="157.3125" height="75"/><g class="label" style="" transform="translate(-48.65625, -22.5)"><rect/><foreignObject width="97.3125" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Load Balancer<br />1 регион</p></span></div></foreignObject></g></g><g class="node default" id="m-eda2ce005e57-dark-flowchart-A-3" data-look="classic" transform="translate(507.2265625, 81.75)"><rect class="basic label-container" style="" x="-82.7109375" y="-37.5" width="165.421875" height="75"/><g class="label" style="" transform="translate(-52.7109375, -22.5)"><rect/><foreignObject width="105.421875" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>App-сервер<br />3–5 инстансов</p></span></div></foreignObject></g></g><g class="node default" id="m-eda2ce005e57-dark-flowchart-C-5" data-look="classic" transform="translate(723.8671875, 45.5)"><rect class="basic label-container" style="" x="-83.9296875" y="-37.5" width="167.859375" height="75"/><g class="label" style="" transform="translate(-53.9296875, -22.5)"><rect/><foreignObject width="107.859375" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>In-memory LRU<br />per-instance</p></span></div></foreignObject></g></g><g class="node default" id="m-eda2ce005e57-dark-flowchart-P-7" data-look="classic" transform="translate(955.015625, 81.75)"><path d="M0,12.8241811761841 a65.828125,12.8241811761841 0,0,0 131.65625,0 a65.828125,12.8241811761841 0,0,0 -131.65625,0 l0,72.8241811761841 a65.828125,12.8241811761841 0,0,0 131.65625,0 l0,-72.8241811761841" class="basic label-container outer-path" style="" transform="translate(-65.828125, -49.23627176427615)"/><g class="label" style="" transform="translate(-58.328125, -12.5)"><rect/><foreignObject width="116.65625" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Postgres primary<br />+ 1 read replica</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="m-eda2ce005e57-dark-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="m-eda2ce005e57-dark-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><linearGradient id="m-eda2ce005e57-dark-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#3f3f46" stop-opacity="1"/><stop offset="100%" stop-color="#3f3f46" stop-opacity="1"/></linearGradient></svg>
</div>
</figure><p><strong>Числовые прикидки:</strong></p>
<ul>
<li><strong>Capacity.</strong> 30k RPS пика → при <code>99.0%</code> можно потерять ~300 запросов/сек без нарушения SLO. Один хорошо настроенный Postgres primary с trigram-индексом на <code>title/description</code> тянет 1–3k RPS read на сложных запросах с фильтрами и фасетами, до 5–8k RPS — на простых коротких запросах с маленькой выборкой (P99 &lt; 200 ms, при правильном connection pooling). Read replica удваивает чтение, итого <code>~2–15k RPS</code> в зависимости от профиля. На пике 30k ты либо урежешь long-tail запросы кэшем приложения, либо примешь деградацию — бюджет позволяет.</li>
<li><strong>Кэш.</strong> In-memory LRU на каждом app-инстансе, размер <code>~256 MB</code>. Hit rate 30–40% на популярных запросах. Без Redis — отдельный сервис добавил бы операционную сложность, нерелевантную для этого SLO.</li>
<li><strong>Полнотекстовый индекс.</strong> <code>pg_trgm</code> + <code>tsvector</code> поверх 50M товаров занимают <code>3–5×</code> от размера индексируемых текстовых полей (title, description, attributes-text). Для нашего каталога с расширенными текстовыми атрибутами это порядка <code>1.5–2.5 TB</code> индексов. Реалистично на одной мощной машине (NVMe, 256 GB RAM).</li>
<li><strong>RTO.</strong> До 30–60 минут на ручной failover на реплику. Автоматизации нет — стоит отдельный сервис.</li>
<li><strong>RPO.</strong> До 5 минут (типовая асинхронная репликация Postgres).</li>
<li><strong>Алерты.</strong> На симптомы: 5xx-rate, P99 latency, replication lag. Реакция оператором, не автоматическая remediation.</li>
</ul>
<p><strong>Почему этого достаточно — счёт по бюджету.</strong> Бюджет 99.0% — это <code>~7 часов даунтайма в месяц</code> при средней нагрузке. Типовой худший случай выхода из строя primary с восстановлением из <code>pg_basebackup</code> + PITR — <code>30–90 минут</code> от пейджа до возобновления read path (включая ручное переключение приложений на реплику и прогрев кэша). Даже два таких инцидента в месяц съедают <code>~3 часа</code> — это меньше половины бюджета. Платить за синхронную репликацию, автоматический failover-tooling (Patroni / RepMgr / Stolon) и дежурную команду, способную их обслуживать, на этом уровне SLO нечем: бюджет покрывает ручной MTTR с большим запасом. На 99.9% этого запаса уже нет — отсюда и Active-passive failover на следующем уровне.</p>
<p><strong>Что намеренно НЕ делаем:</strong></p>
<ul>
<li>Не поднимаем Elasticsearch — он добавит +1 систему-источник истины, требующую отдельного индексирования, мониторинга и SLO. На 99.0% это лишний оверхед.</li>
<li>Не делаем шардинг — одна машина с 256 GB RAM в 2025 году утаскивает 50M документов с trigram-индексом без проблем.</li>
<li>Не делаем multi-region даже active-passive. Бюджет 7 часов покрывает любой региональный инцидент с ручным восстановлением.</li>
</ul>
<p><strong>Стоимость:</strong> обозначу как <strong>1× baseline</strong> для последующего сравнения.</p>
<h3 id="slo-999-рабочий-production-уровень">SLO 99.9%: рабочий production-уровень</h3>
<p><strong>Бюджет:</strong> ~26M «плохих» запросов за 30 дней, или <strong>~14 мин 27 с</strong> полного даунтайма на пике / <strong>~43 мин 20 с</strong> при средней нагрузке. На инцидент при средней нагрузке остаётся минут 20–30 — хватает на автоматический failover, но не на ручной разбор каждого 5xx.</p>
<p><strong>Когда уместно:</strong> основные пользовательские пути в среднем e-commerce, обычный production. Большинство сервисов в индустрии живут в этом диапазоне.</p>
<p><strong>Read path:</strong></p>
<figure class="mermaid mermaid--prerendered" aria-label="Mermaid diagram">
<div class="mermaid-svg mermaid-svg--light">
<svg id="m-58b7ff999bbf-light" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 1236.55px; background-color: transparent;" viewBox="0 0 1236.546875 312.40679931640625" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#m-58b7ff999bbf-light{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;fill:#1c1c1f;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#m-58b7ff999bbf-light .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#m-58b7ff999bbf-light .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#m-58b7ff999bbf-light .error-icon{fill:#fee2e2;}#m-58b7ff999bbf-light .error-text{fill:#7f1d1d;stroke:#7f1d1d;}#m-58b7ff999bbf-light .edge-thickness-normal{stroke-width:1px;}#m-58b7ff999bbf-light .edge-thickness-thick{stroke-width:3.5px;}#m-58b7ff999bbf-light .edge-pattern-solid{stroke-dasharray:0;}#m-58b7ff999bbf-light .edge-thickness-invisible{stroke-width:0;fill:none;}#m-58b7ff999bbf-light .edge-pattern-dashed{stroke-dasharray:3;}#m-58b7ff999bbf-light .edge-pattern-dotted{stroke-dasharray:2;}#m-58b7ff999bbf-light .marker{fill:#5b5b62;stroke:#5b5b62;}#m-58b7ff999bbf-light .marker.cross{stroke:#5b5b62;}#m-58b7ff999bbf-light svg{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;}#m-58b7ff999bbf-light p{margin:0;}#m-58b7ff999bbf-light .label{font-family:Inter,system-ui,-apple-system,sans-serif;color:#1c1c1f;}#m-58b7ff999bbf-light .cluster-label text{fill:#1c1c1f;}#m-58b7ff999bbf-light .cluster-label span{color:#1c1c1f;}#m-58b7ff999bbf-light .cluster-label span p{background-color:transparent;}#m-58b7ff999bbf-light .label text,#m-58b7ff999bbf-light span{fill:#1c1c1f;color:#1c1c1f;}#m-58b7ff999bbf-light .node rect,#m-58b7ff999bbf-light .node circle,#m-58b7ff999bbf-light .node ellipse,#m-58b7ff999bbf-light .node polygon,#m-58b7ff999bbf-light .node path{fill:#ffffff;stroke:#c8c5bb;stroke-width:1px;}#m-58b7ff999bbf-light .rough-node .label text,#m-58b7ff999bbf-light .node .label text,#m-58b7ff999bbf-light .image-shape .label,#m-58b7ff999bbf-light .icon-shape .label{text-anchor:middle;}#m-58b7ff999bbf-light .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#m-58b7ff999bbf-light .rough-node .label,#m-58b7ff999bbf-light .node .label,#m-58b7ff999bbf-light .image-shape .label,#m-58b7ff999bbf-light .icon-shape .label{text-align:center;}#m-58b7ff999bbf-light .node.clickable{cursor:pointer;}#m-58b7ff999bbf-light .root .anchor path{fill:#5b5b62!important;stroke-width:0;stroke:#5b5b62;}#m-58b7ff999bbf-light .arrowheadPath{fill:rgba(255, 255, 255, 0);}#m-58b7ff999bbf-light .edgePath .path{stroke:#5b5b62;stroke-width:1px;}#m-58b7ff999bbf-light .flowchart-link{stroke:#5b5b62;fill:none;}#m-58b7ff999bbf-light .edgeLabel{background-color:#fafaf7;text-align:center;}#m-58b7ff999bbf-light .edgeLabel p{background-color:#fafaf7;}#m-58b7ff999bbf-light .edgeLabel rect{opacity:0.5;background-color:#fafaf7;fill:#fafaf7;}#m-58b7ff999bbf-light .labelBkg{background-color:rgba(250, 250, 247, 0.5);}#m-58b7ff999bbf-light .cluster rect{fill:#f3f1ed;stroke:#c8c5bb;stroke-width:1px;}#m-58b7ff999bbf-light .cluster text{fill:#1c1c1f;}#m-58b7ff999bbf-light .cluster span{color:#1c1c1f;}#m-58b7ff999bbf-light div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:12px;background:#fed7aa;border:1px solid #c2410c;border-radius:2px;pointer-events:none;z-index:100;}#m-58b7ff999bbf-light .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#1c1c1f;}#m-58b7ff999bbf-light rect.text{fill:none;stroke-width:0;}#m-58b7ff999bbf-light .icon-shape,#m-58b7ff999bbf-light .image-shape{background-color:#fafaf7;text-align:center;}#m-58b7ff999bbf-light .icon-shape p,#m-58b7ff999bbf-light .image-shape p{background-color:#fafaf7;padding:2px;}#m-58b7ff999bbf-light .icon-shape .label rect,#m-58b7ff999bbf-light .image-shape .label rect{opacity:0.5;background-color:#fafaf7;fill:#fafaf7;}#m-58b7ff999bbf-light .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#m-58b7ff999bbf-light .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#m-58b7ff999bbf-light .node .neo-node{stroke:#c8c5bb;}#m-58b7ff999bbf-light [data-look="neo"].node rect,#m-58b7ff999bbf-light [data-look="neo"].cluster rect,#m-58b7ff999bbf-light [data-look="neo"].node polygon{stroke:url(#m-58b7ff999bbf-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-58b7ff999bbf-light [data-look="neo"].node path{stroke:url(#m-58b7ff999bbf-light-gradient);stroke-width:1px;}#m-58b7ff999bbf-light [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-58b7ff999bbf-light [data-look="neo"].node .neo-line path{stroke:#c8c5bb;filter:none;}#m-58b7ff999bbf-light [data-look="neo"].node circle{stroke:url(#m-58b7ff999bbf-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-58b7ff999bbf-light [data-look="neo"].node circle .state-start{fill:#000000;}#m-58b7ff999bbf-light [data-look="neo"].icon-shape .icon{fill:url(#m-58b7ff999bbf-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-58b7ff999bbf-light [data-look="neo"].icon-shape .icon-neo path{stroke:url(#m-58b7ff999bbf-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-58b7ff999bbf-light :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="m-58b7ff999bbf-light_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-light_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-light_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-light_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-light_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-light_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-light_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-light_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-light_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-light_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-light_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="m-58b7ff999bbf-light_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M119.801,158.43L131.868,148.593C143.935,138.756,168.069,119.081,186.669,109.244C205.268,99.407,218.333,99.407,224.866,99.407L231.398,99.407" id="m-58b7ff999bbf-light-L_U_CDN_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_U_CDN_0" data-points="W3sieCI6MTE5LjgwMTQ1MjU4NjIxOTkxLCJ5IjoxNTguNDMwMDg4MDQzMjEyOX0seyJ4IjoxOTIuMjAzMTI1LCJ5Ijo5OS40MDY3ODQwNTc2MTcxOX0seyJ4IjoyMzUuMzk4NDM3NSwieSI6OTkuNDA2Nzg0MDU3NjE3MTl9XQ==" data-look="classic" marker-end="url(#m-58b7ff999bbf-light_flowchart-v2-pointEnd)"/><path d="M126.287,210.93L137.273,218.385C148.259,225.839,170.231,240.748,184.717,248.202C199.203,255.657,206.203,255.657,209.703,255.657L213.203,255.657" id="m-58b7ff999bbf-light-L_U_GLB_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_U_GLB_0" data-points="W3sieCI6MTI2LjI4NzM3MzA1MjA2ODUsInkiOjIxMC45MzAwODgwNDMyMTI5fSx7IngiOjE5Mi4yMDMxMjUsInkiOjI1NS42NTY3ODQwNTc2MTcyfSx7IngiOjIxNy4yMDMxMjUsInkiOjI1NS42NTY3ODQwNTc2MTcyfV0=" data-look="classic" marker-end="url(#m-58b7ff999bbf-light_flowchart-v2-pointEnd)"/><path d="M422.656,255.657L426.823,255.657C430.99,255.657,439.323,255.657,446.99,255.657C454.656,255.657,461.656,255.657,465.156,255.657L468.656,255.657" id="m-58b7ff999bbf-light-L_GLB_R_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_GLB_R_0" data-points="W3sieCI6NDIyLjY1NjI1LCJ5IjoyNTUuNjU2Nzg0MDU3NjE3Mn0seyJ4Ijo0NDcuNjU2MjUsInkiOjI1NS42NTY3ODQwNTc2MTcyfSx7IngiOjQ3Mi42NTYyNSwieSI6MjU1LjY1Njc4NDA1NzYxNzJ9XQ==" data-look="classic" marker-end="url(#m-58b7ff999bbf-light_flowchart-v2-pointEnd)"/><path d="M626.813,260.518L633.618,260.947C640.424,261.376,654.036,262.235,666.997,261.32C679.958,260.406,692.267,257.718,698.422,256.375L704.576,255.031" id="m-58b7ff999bbf-light-L_R_SS_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_R_SS_0" data-points="W3sieCI6NjI2LjgxMjUsInkiOjI2MC41MTc4Mjk2ODgyNzMyfSx7IngiOjY2Ny42NDg0Mzc1LCJ5IjoyNjMuMDkzMjA4MzEyOTg4M30seyJ4Ijo3MDguNDg0Mzc1LCJ5IjoyNTQuMTc3NTUxNDE2NTMwNjZ9XQ==" data-look="classic" marker-end="url(#m-58b7ff999bbf-light_flowchart-v2-pointEnd)"/><path d="M883.965,194.343L898.2,187.049C912.435,179.755,940.905,165.167,963.995,151.054C987.084,136.941,1004.793,123.304,1013.648,116.485L1022.503,109.666" id="m-58b7ff999bbf-light-L_SS_ES_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_SS_ES_0" data-points="W3sieCI6ODgzLjk2NTAyMDAxMTg5MTMsInkiOjE5NC4zNDMyMDgzMTI5ODgyOH0seyJ4Ijo5NjkuMzc1LCJ5IjoxNTAuNTc4MzkyMDI4ODA4Nn0seyJ4IjoxMDI1LjY3MTg3NSwieSI6MTA3LjIyNTkxOTQ4NzY0MDl9XQ==" data-look="classic" marker-end="url(#m-58b7ff999bbf-light_flowchart-v2-pointEnd)"/><path d="M913.078,237.125L922.461,237.609C931.844,238.094,950.609,239.063,971.448,239.547C992.286,240.032,1015.198,240.032,1026.654,240.032L1038.109,240.032" id="m-58b7ff999bbf-light-L_SS_RR_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_SS_RR_0" data-points="W3sieCI6OTEzLjA3ODEyNSwieSI6MjM3LjEyNTA0MTM1NzMzMTY3fSx7IngiOjk2OS4zNzUsInkiOjI0MC4wMzE3ODQwNTc2MTcyfSx7IngiOjEwNDIuMTA5Mzc1LCJ5IjoyNDAuMDMxNzg0MDU3NjE3Mn1d" data-look="classic" marker-end="url(#m-58b7ff999bbf-light_flowchart-v2-pointEnd)"/><path d="M607.898,72.453L617.857,72.453C627.815,72.453,647.732,72.453,672.1,72.453C696.469,72.453,725.289,72.453,739.699,72.453L754.109,72.453" id="m-58b7ff999bbf-light-L_PG_Q_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_PG_Q_0" data-points="W3sieCI6NjA3Ljg5ODQzNzUsInkiOjcyLjQ1MzM5MjAyODgwODZ9LHsieCI6NjY3LjY0ODQzNzUsInkiOjcyLjQ1MzM5MjAyODgwODZ9LHsieCI6NzU4LjEwOTM3NSwieSI6NzIuNDUzMzkyMDI4ODA4Nn1d" data-look="classic" marker-end="url(#m-58b7ff999bbf-light_flowchart-v2-pointEnd)"/><path d="M863.453,72.453L881.107,72.453C898.76,72.453,934.068,72.453,960.438,72.453C986.807,72.453,1004.24,72.453,1012.956,72.453L1021.672,72.453" id="m-58b7ff999bbf-light-L_Q_ES_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Q_ES_0" data-points="W3sieCI6ODYzLjQ1MzEyNSwieSI6NzIuNDUzMzkyMDI4ODA4Nn0seyJ4Ijo5NjkuMzc1LCJ5Ijo3Mi40NTMzOTIwMjg4MDg2fSx7IngiOjEwMjUuNjcxODc1LCJ5Ijo3Mi40NTMzOTIwMjg4MDg2fV0=" data-look="classic" marker-end="url(#m-58b7ff999bbf-light_flowchart-v2-pointEnd)"/><path d="M626.813,240.09L633.618,238.716C640.424,237.341,654.036,234.592,666.982,233.218C679.927,231.843,692.206,231.843,698.345,231.843L704.484,231.843" id="m-58b7ff999bbf-light-L_R_SS_2" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_R_SS_2" data-points="W3sieCI6NjI2LjgxMjUsInkiOjI0MC4wOTAzMTM2MjEyMjIyNn0seyJ4Ijo2NjcuNjQ4NDM3NSwieSI6MjMxLjg0MzIwODMxMjk4ODI4fSx7IngiOjcwOC40ODQzNzUsInkiOjIzMS44NDMyMDgzMTI5ODgyOH1d" data-look="classic" marker-end="url(#m-58b7ff999bbf-light_flowchart-v2-pointEnd)"/><path d="M721.228,194.343L712.298,190.604C703.368,186.864,685.508,179.386,656.926,175.646C628.344,171.907,589.039,171.907,552.374,171.907C515.708,171.907,481.682,171.907,443.382,171.907C405.081,171.907,362.505,171.907,319.93,171.907C277.354,171.907,234.779,171.907,209.986,172.335C185.193,172.763,178.183,173.619,174.679,174.047L171.174,174.475" id="m-58b7ff999bbf-light-L_SS_U_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_SS_U_0" data-points="W3sieCI6NzIxLjIyODM1MjMxODI3MDEsInkiOjE5NC4zNDMyMDgzMTI5ODgyOH0seyJ4Ijo2NjcuNjQ4NDM3NSwieSI6MTcxLjkwNjc4NDA1NzYxNzJ9LHsieCI6NTQ5LjczNDM3NSwieSI6MTcxLjkwNjc4NDA1NzYxNzJ9LHsieCI6NDQ3LjY1NjI1LCJ5IjoxNzEuOTA2Nzg0MDU3NjE3Mn0seyJ4IjozMTkuOTI5Njg3NSwieSI6MTcxLjkwNjc4NDA1NzYxNzJ9LHsieCI6MTkyLjIwMzEyNSwieSI6MTcxLjkwNjc4NDA1NzYxNzJ9LHsieCI6MTY3LjIwMzEyNSwieSI6MTc0Ljk1OTYzMTM3NjYwMzR9XQ==" data-look="classic" marker-end="url(#m-58b7ff999bbf-light_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_U_CDN_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_U_GLB_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_GLB_R_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(668.07871, 262.99927)"><g class="label" data-id="L_R_SS_0" transform="translate(-15.6953125, -11.25)"><foreignObject width="31.390625" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>miss</p></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_SS_ES_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_SS_RR_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(667.6484375, 72.4533920288086)"><g class="label" data-id="L_PG_Q_0" transform="translate(-15.8359375, -11.25)"><foreignObject width="31.671875" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>CDC</p></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(969.375, 72.4533920288086)"><g class="label" data-id="L_Q_ES_0" transform="translate(-31.296875, -11.25)"><foreignObject width="62.59375" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>consume</p></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_R_SS_2" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_SS_U_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="m-58b7ff999bbf-light-flowchart-U-0" data-look="classic" transform="translate(87.6015625, 184.6800880432129)"><rect class="basic label-container" style="" x="-79.6015625" y="-26.25" width="159.203125" height="52.5"/><g class="label" style="" transform="translate(-49.6015625, -11.25)"><rect/><foreignObject width="99.203125" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Пользователь</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-light-flowchart-CDN-1" data-look="classic" transform="translate(319.9296875, 99.40678405761719)"><rect class="basic label-container" style="" x="-84.53125" y="-37.5" width="169.0625" height="75"/><g class="label" style="" transform="translate(-54.53125, -22.5)"><rect/><foreignObject width="109.0625" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>CDN<br />статика, медиа</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-light-flowchart-GLB-3" data-look="classic" transform="translate(319.9296875, 255.6567840576172)"><rect class="basic label-container" style="" x="-102.7265625" y="-48.75" width="205.453125" height="97.5"/><g class="label" style="" transform="translate(-72.7265625, -33.75)"><rect/><foreignObject width="145.453125" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Global LB<br />гео-роутинг<br />в 1 активный регион</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-light-flowchart-R-5" data-look="classic" transform="translate(549.734375, 255.6567840576172)"><rect class="basic label-container" style="" x="-77.078125" y="-48.75" width="154.15625" height="97.5"/><g class="label" style="" transform="translate(-47.078125, -33.75)"><rect/><foreignObject width="94.15625" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Redis Cluster<br />top queries +<br />autocomplete</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-light-flowchart-SS-7" data-look="classic" transform="translate(810.78125, 231.84320831298828)"><rect class="basic label-container" style="" x="-102.296875" y="-37.5" width="204.59375" height="75"/><g class="label" style="" transform="translate(-72.296875, -22.5)"><rect/><foreignObject width="144.59375" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Search Service<br />app-tier, 12–20 инст.</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-light-flowchart-ES-9" data-look="classic" transform="translate(1127.109375, 72.4533920288086)"><path d="M0,15.468928707586732 a101.4375,15.468928707586732 0,0,0 202.875,0 a101.4375,15.468928707586732 0,0,0 -202.875,0 l0,97.96892870758673 a101.4375,15.468928707586732 0,0,0 202.875,0 l0,-97.96892870758673" class="basic label-container outer-path" style="" transform="translate(-101.4375, -64.4533930613801)"/><g class="label" style="" transform="translate(-93.9375, -23.75)"><rect/><foreignObject width="187.875" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Elasticsearch<br />8–12 нод, 6 primary shards<br />× 2 replicas</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-light-flowchart-RR-11" data-look="classic" transform="translate(1127.109375, 240.0317840576172)"><rect class="basic label-container" style="" x="-85" y="-37.5" width="170" height="75"/><g class="label" style="" transform="translate(-55, -22.5)"><rect/><foreignObject width="110" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Ranking Service<br />отдельный SLO</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-light-flowchart-PG-12" data-look="classic" transform="translate(549.734375, 72.4533920288086)"><path d="M0,12.050825509873746 a58.1640625,12.050825509873746 0,0,0 116.328125,0 a58.1640625,12.050825509873746 0,0,0 -116.328125,0 l0,72.05082550987375 a58.1640625,12.050825509873746 0,0,0 116.328125,0 l0,-72.05082550987375" class="basic label-container outer-path" style="" transform="translate(-58.1640625, -48.07623826481062)"/><g class="label" style="" transform="translate(-50.6640625, -12.5)"><rect/><foreignObject width="101.328125" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Postgres<br />source of truth</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-light-flowchart-Q-13" data-look="classic" transform="translate(810.78125, 72.4533920288086)"><rect class="basic label-container" style="" x="-52.671875" y="-37.5" width="105.34375" height="75"/><g class="label" style="" transform="translate(-22.671875, -22.5)"><rect/><foreignObject width="45.34375" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Kafka<br />events</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="m-58b7ff999bbf-light-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="m-58b7ff999bbf-light-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><linearGradient id="m-58b7ff999bbf-light-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#c8c5bb" stop-opacity="1"/><stop offset="100%" stop-color="#c8c5bb" stop-opacity="1"/></linearGradient></svg>
</div>
<div class="mermaid-svg mermaid-svg--dark">
<svg id="m-58b7ff999bbf-dark" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 1236.55px; background-color: transparent;" viewBox="0 0 1236.546875 312.40679931640625" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#m-58b7ff999bbf-dark{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;fill:#e8e6df;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#m-58b7ff999bbf-dark .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#m-58b7ff999bbf-dark .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#m-58b7ff999bbf-dark .error-icon{fill:#7f1d1d;}#m-58b7ff999bbf-dark .error-text{fill:#fecaca;stroke:#fecaca;}#m-58b7ff999bbf-dark .edge-thickness-normal{stroke-width:1px;}#m-58b7ff999bbf-dark .edge-thickness-thick{stroke-width:3.5px;}#m-58b7ff999bbf-dark .edge-pattern-solid{stroke-dasharray:0;}#m-58b7ff999bbf-dark .edge-thickness-invisible{stroke-width:0;fill:none;}#m-58b7ff999bbf-dark .edge-pattern-dashed{stroke-dasharray:3;}#m-58b7ff999bbf-dark .edge-pattern-dotted{stroke-dasharray:2;}#m-58b7ff999bbf-dark .marker{fill:#a8a89e;stroke:#a8a89e;}#m-58b7ff999bbf-dark .marker.cross{stroke:#a8a89e;}#m-58b7ff999bbf-dark svg{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;}#m-58b7ff999bbf-dark p{margin:0;}#m-58b7ff999bbf-dark .label{font-family:Inter,system-ui,-apple-system,sans-serif;color:#e8e6df;}#m-58b7ff999bbf-dark .cluster-label text{fill:#e8e6df;}#m-58b7ff999bbf-dark .cluster-label span{color:#e8e6df;}#m-58b7ff999bbf-dark .cluster-label span p{background-color:transparent;}#m-58b7ff999bbf-dark .label text,#m-58b7ff999bbf-dark span{fill:#e8e6df;color:#e8e6df;}#m-58b7ff999bbf-dark .node rect,#m-58b7ff999bbf-dark .node circle,#m-58b7ff999bbf-dark .node ellipse,#m-58b7ff999bbf-dark .node polygon,#m-58b7ff999bbf-dark .node path{fill:#23252a;stroke:#3f3f46;stroke-width:1px;}#m-58b7ff999bbf-dark .rough-node .label text,#m-58b7ff999bbf-dark .node .label text,#m-58b7ff999bbf-dark .image-shape .label,#m-58b7ff999bbf-dark .icon-shape .label{text-anchor:middle;}#m-58b7ff999bbf-dark .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#m-58b7ff999bbf-dark .rough-node .label,#m-58b7ff999bbf-dark .node .label,#m-58b7ff999bbf-dark .image-shape .label,#m-58b7ff999bbf-dark .icon-shape .label{text-align:center;}#m-58b7ff999bbf-dark .node.clickable{cursor:pointer;}#m-58b7ff999bbf-dark .root .anchor path{fill:#a8a89e!important;stroke-width:0;stroke:#a8a89e;}#m-58b7ff999bbf-dark .arrowheadPath{fill:rgba(255, 255, 255, 0);}#m-58b7ff999bbf-dark .edgePath .path{stroke:#a8a89e;stroke-width:1px;}#m-58b7ff999bbf-dark .flowchart-link{stroke:#a8a89e;fill:none;}#m-58b7ff999bbf-dark .edgeLabel{background-color:#1a1b1e;text-align:center;}#m-58b7ff999bbf-dark .edgeLabel p{background-color:#1a1b1e;}#m-58b7ff999bbf-dark .edgeLabel rect{opacity:0.5;background-color:#1a1b1e;fill:#1a1b1e;}#m-58b7ff999bbf-dark .labelBkg{background-color:rgba(26, 27, 30, 0.5);}#m-58b7ff999bbf-dark .cluster rect{fill:#2a2b2f;stroke:#3f3f46;stroke-width:1px;}#m-58b7ff999bbf-dark .cluster text{fill:#e8e6df;}#m-58b7ff999bbf-dark .cluster span{color:#e8e6df;}#m-58b7ff999bbf-dark div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:12px;background:#7c2d12;border:1px solid #fb923c;border-radius:2px;pointer-events:none;z-index:100;}#m-58b7ff999bbf-dark .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#e8e6df;}#m-58b7ff999bbf-dark rect.text{fill:none;stroke-width:0;}#m-58b7ff999bbf-dark .icon-shape,#m-58b7ff999bbf-dark .image-shape{background-color:#1a1b1e;text-align:center;}#m-58b7ff999bbf-dark .icon-shape p,#m-58b7ff999bbf-dark .image-shape p{background-color:#1a1b1e;padding:2px;}#m-58b7ff999bbf-dark .icon-shape .label rect,#m-58b7ff999bbf-dark .image-shape .label rect{opacity:0.5;background-color:#1a1b1e;fill:#1a1b1e;}#m-58b7ff999bbf-dark .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#m-58b7ff999bbf-dark .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#m-58b7ff999bbf-dark .node .neo-node{stroke:#3f3f46;}#m-58b7ff999bbf-dark [data-look="neo"].node rect,#m-58b7ff999bbf-dark [data-look="neo"].cluster rect,#m-58b7ff999bbf-dark [data-look="neo"].node polygon{stroke:url(#m-58b7ff999bbf-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-58b7ff999bbf-dark [data-look="neo"].node path{stroke:url(#m-58b7ff999bbf-dark-gradient);stroke-width:1px;}#m-58b7ff999bbf-dark [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-58b7ff999bbf-dark [data-look="neo"].node .neo-line path{stroke:#3f3f46;filter:none;}#m-58b7ff999bbf-dark [data-look="neo"].node circle{stroke:url(#m-58b7ff999bbf-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-58b7ff999bbf-dark [data-look="neo"].node circle .state-start{fill:#000000;}#m-58b7ff999bbf-dark [data-look="neo"].icon-shape .icon{fill:url(#m-58b7ff999bbf-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-58b7ff999bbf-dark [data-look="neo"].icon-shape .icon-neo path{stroke:url(#m-58b7ff999bbf-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-58b7ff999bbf-dark :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="m-58b7ff999bbf-dark_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-dark_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-dark_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-dark_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-dark_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-dark_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-dark_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-dark_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-dark_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-dark_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-58b7ff999bbf-dark_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="m-58b7ff999bbf-dark_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M119.801,158.43L131.868,148.593C143.935,138.756,168.069,119.081,186.669,109.244C205.268,99.407,218.333,99.407,224.866,99.407L231.398,99.407" id="m-58b7ff999bbf-dark-L_U_CDN_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_U_CDN_0" data-points="W3sieCI6MTE5LjgwMTQ1MjU4NjIxOTkxLCJ5IjoxNTguNDMwMDg4MDQzMjEyOX0seyJ4IjoxOTIuMjAzMTI1LCJ5Ijo5OS40MDY3ODQwNTc2MTcxOX0seyJ4IjoyMzUuMzk4NDM3NSwieSI6OTkuNDA2Nzg0MDU3NjE3MTl9XQ==" data-look="classic" marker-end="url(#m-58b7ff999bbf-dark_flowchart-v2-pointEnd)"/><path d="M126.287,210.93L137.273,218.385C148.259,225.839,170.231,240.748,184.717,248.202C199.203,255.657,206.203,255.657,209.703,255.657L213.203,255.657" id="m-58b7ff999bbf-dark-L_U_GLB_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_U_GLB_0" data-points="W3sieCI6MTI2LjI4NzM3MzA1MjA2ODUsInkiOjIxMC45MzAwODgwNDMyMTI5fSx7IngiOjE5Mi4yMDMxMjUsInkiOjI1NS42NTY3ODQwNTc2MTcyfSx7IngiOjIxNy4yMDMxMjUsInkiOjI1NS42NTY3ODQwNTc2MTcyfV0=" data-look="classic" marker-end="url(#m-58b7ff999bbf-dark_flowchart-v2-pointEnd)"/><path d="M422.656,255.657L426.823,255.657C430.99,255.657,439.323,255.657,446.99,255.657C454.656,255.657,461.656,255.657,465.156,255.657L468.656,255.657" id="m-58b7ff999bbf-dark-L_GLB_R_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_GLB_R_0" data-points="W3sieCI6NDIyLjY1NjI1LCJ5IjoyNTUuNjU2Nzg0MDU3NjE3Mn0seyJ4Ijo0NDcuNjU2MjUsInkiOjI1NS42NTY3ODQwNTc2MTcyfSx7IngiOjQ3Mi42NTYyNSwieSI6MjU1LjY1Njc4NDA1NzYxNzJ9XQ==" data-look="classic" marker-end="url(#m-58b7ff999bbf-dark_flowchart-v2-pointEnd)"/><path d="M626.813,260.518L633.618,260.947C640.424,261.376,654.036,262.235,666.997,261.32C679.958,260.406,692.267,257.718,698.422,256.375L704.576,255.031" id="m-58b7ff999bbf-dark-L_R_SS_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_R_SS_0" data-points="W3sieCI6NjI2LjgxMjUsInkiOjI2MC41MTc4Mjk2ODgyNzMyfSx7IngiOjY2Ny42NDg0Mzc1LCJ5IjoyNjMuMDkzMjA4MzEyOTg4M30seyJ4Ijo3MDguNDg0Mzc1LCJ5IjoyNTQuMTc3NTUxNDE2NTMwNjZ9XQ==" data-look="classic" marker-end="url(#m-58b7ff999bbf-dark_flowchart-v2-pointEnd)"/><path d="M883.965,194.343L898.2,187.049C912.435,179.755,940.905,165.167,963.995,151.054C987.084,136.941,1004.793,123.304,1013.648,116.485L1022.503,109.666" id="m-58b7ff999bbf-dark-L_SS_ES_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_SS_ES_0" data-points="W3sieCI6ODgzLjk2NTAyMDAxMTg5MTMsInkiOjE5NC4zNDMyMDgzMTI5ODgyOH0seyJ4Ijo5NjkuMzc1LCJ5IjoxNTAuNTc4MzkyMDI4ODA4Nn0seyJ4IjoxMDI1LjY3MTg3NSwieSI6MTA3LjIyNTkxOTQ4NzY0MDl9XQ==" data-look="classic" marker-end="url(#m-58b7ff999bbf-dark_flowchart-v2-pointEnd)"/><path d="M913.078,237.125L922.461,237.609C931.844,238.094,950.609,239.063,971.448,239.547C992.286,240.032,1015.198,240.032,1026.654,240.032L1038.109,240.032" id="m-58b7ff999bbf-dark-L_SS_RR_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_SS_RR_0" data-points="W3sieCI6OTEzLjA3ODEyNSwieSI6MjM3LjEyNTA0MTM1NzMzMTY3fSx7IngiOjk2OS4zNzUsInkiOjI0MC4wMzE3ODQwNTc2MTcyfSx7IngiOjEwNDIuMTA5Mzc1LCJ5IjoyNDAuMDMxNzg0MDU3NjE3Mn1d" data-look="classic" marker-end="url(#m-58b7ff999bbf-dark_flowchart-v2-pointEnd)"/><path d="M607.898,72.453L617.857,72.453C627.815,72.453,647.732,72.453,672.1,72.453C696.469,72.453,725.289,72.453,739.699,72.453L754.109,72.453" id="m-58b7ff999bbf-dark-L_PG_Q_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_PG_Q_0" data-points="W3sieCI6NjA3Ljg5ODQzNzUsInkiOjcyLjQ1MzM5MjAyODgwODZ9LHsieCI6NjY3LjY0ODQzNzUsInkiOjcyLjQ1MzM5MjAyODgwODZ9LHsieCI6NzU4LjEwOTM3NSwieSI6NzIuNDUzMzkyMDI4ODA4Nn1d" data-look="classic" marker-end="url(#m-58b7ff999bbf-dark_flowchart-v2-pointEnd)"/><path d="M863.453,72.453L881.107,72.453C898.76,72.453,934.068,72.453,960.438,72.453C986.807,72.453,1004.24,72.453,1012.956,72.453L1021.672,72.453" id="m-58b7ff999bbf-dark-L_Q_ES_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Q_ES_0" data-points="W3sieCI6ODYzLjQ1MzEyNSwieSI6NzIuNDUzMzkyMDI4ODA4Nn0seyJ4Ijo5NjkuMzc1LCJ5Ijo3Mi40NTMzOTIwMjg4MDg2fSx7IngiOjEwMjUuNjcxODc1LCJ5Ijo3Mi40NTMzOTIwMjg4MDg2fV0=" data-look="classic" marker-end="url(#m-58b7ff999bbf-dark_flowchart-v2-pointEnd)"/><path d="M626.813,240.09L633.618,238.716C640.424,237.341,654.036,234.592,666.982,233.218C679.927,231.843,692.206,231.843,698.345,231.843L704.484,231.843" id="m-58b7ff999bbf-dark-L_R_SS_2" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_R_SS_2" data-points="W3sieCI6NjI2LjgxMjUsInkiOjI0MC4wOTAzMTM2MjEyMjIyNn0seyJ4Ijo2NjcuNjQ4NDM3NSwieSI6MjMxLjg0MzIwODMxMjk4ODI4fSx7IngiOjcwOC40ODQzNzUsInkiOjIzMS44NDMyMDgzMTI5ODgyOH1d" data-look="classic" marker-end="url(#m-58b7ff999bbf-dark_flowchart-v2-pointEnd)"/><path d="M721.228,194.343L712.298,190.604C703.368,186.864,685.508,179.386,656.926,175.646C628.344,171.907,589.039,171.907,552.374,171.907C515.708,171.907,481.682,171.907,443.382,171.907C405.081,171.907,362.505,171.907,319.93,171.907C277.354,171.907,234.779,171.907,209.986,172.335C185.193,172.763,178.183,173.619,174.679,174.047L171.174,174.475" id="m-58b7ff999bbf-dark-L_SS_U_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_SS_U_0" data-points="W3sieCI6NzIxLjIyODM1MjMxODI3MDEsInkiOjE5NC4zNDMyMDgzMTI5ODgyOH0seyJ4Ijo2NjcuNjQ4NDM3NSwieSI6MTcxLjkwNjc4NDA1NzYxNzJ9LHsieCI6NTQ5LjczNDM3NSwieSI6MTcxLjkwNjc4NDA1NzYxNzJ9LHsieCI6NDQ3LjY1NjI1LCJ5IjoxNzEuOTA2Nzg0MDU3NjE3Mn0seyJ4IjozMTkuOTI5Njg3NSwieSI6MTcxLjkwNjc4NDA1NzYxNzJ9LHsieCI6MTkyLjIwMzEyNSwieSI6MTcxLjkwNjc4NDA1NzYxNzJ9LHsieCI6MTY3LjIwMzEyNSwieSI6MTc0Ljk1OTYzMTM3NjYwMzR9XQ==" data-look="classic" marker-end="url(#m-58b7ff999bbf-dark_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_U_CDN_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_U_GLB_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_GLB_R_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(668.07871, 262.99927)"><g class="label" data-id="L_R_SS_0" transform="translate(-15.6953125, -11.25)"><foreignObject width="31.390625" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>miss</p></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_SS_ES_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_SS_RR_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(667.6484375, 72.4533920288086)"><g class="label" data-id="L_PG_Q_0" transform="translate(-15.8359375, -11.25)"><foreignObject width="31.671875" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>CDC</p></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(969.375, 72.4533920288086)"><g class="label" data-id="L_Q_ES_0" transform="translate(-31.296875, -11.25)"><foreignObject width="62.59375" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>consume</p></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_R_SS_2" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_SS_U_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="m-58b7ff999bbf-dark-flowchart-U-0" data-look="classic" transform="translate(87.6015625, 184.6800880432129)"><rect class="basic label-container" style="" x="-79.6015625" y="-26.25" width="159.203125" height="52.5"/><g class="label" style="" transform="translate(-49.6015625, -11.25)"><rect/><foreignObject width="99.203125" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Пользователь</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-dark-flowchart-CDN-1" data-look="classic" transform="translate(319.9296875, 99.40678405761719)"><rect class="basic label-container" style="" x="-84.53125" y="-37.5" width="169.0625" height="75"/><g class="label" style="" transform="translate(-54.53125, -22.5)"><rect/><foreignObject width="109.0625" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>CDN<br />статика, медиа</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-dark-flowchart-GLB-3" data-look="classic" transform="translate(319.9296875, 255.6567840576172)"><rect class="basic label-container" style="" x="-102.7265625" y="-48.75" width="205.453125" height="97.5"/><g class="label" style="" transform="translate(-72.7265625, -33.75)"><rect/><foreignObject width="145.453125" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Global LB<br />гео-роутинг<br />в 1 активный регион</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-dark-flowchart-R-5" data-look="classic" transform="translate(549.734375, 255.6567840576172)"><rect class="basic label-container" style="" x="-77.078125" y="-48.75" width="154.15625" height="97.5"/><g class="label" style="" transform="translate(-47.078125, -33.75)"><rect/><foreignObject width="94.15625" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Redis Cluster<br />top queries +<br />autocomplete</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-dark-flowchart-SS-7" data-look="classic" transform="translate(810.78125, 231.84320831298828)"><rect class="basic label-container" style="" x="-102.296875" y="-37.5" width="204.59375" height="75"/><g class="label" style="" transform="translate(-72.296875, -22.5)"><rect/><foreignObject width="144.59375" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Search Service<br />app-tier, 12–20 инст.</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-dark-flowchart-ES-9" data-look="classic" transform="translate(1127.109375, 72.4533920288086)"><path d="M0,15.468928707586732 a101.4375,15.468928707586732 0,0,0 202.875,0 a101.4375,15.468928707586732 0,0,0 -202.875,0 l0,97.96892870758673 a101.4375,15.468928707586732 0,0,0 202.875,0 l0,-97.96892870758673" class="basic label-container outer-path" style="" transform="translate(-101.4375, -64.4533930613801)"/><g class="label" style="" transform="translate(-93.9375, -23.75)"><rect/><foreignObject width="187.875" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Elasticsearch<br />8–12 нод, 6 primary shards<br />× 2 replicas</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-dark-flowchart-RR-11" data-look="classic" transform="translate(1127.109375, 240.0317840576172)"><rect class="basic label-container" style="" x="-85" y="-37.5" width="170" height="75"/><g class="label" style="" transform="translate(-55, -22.5)"><rect/><foreignObject width="110" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Ranking Service<br />отдельный SLO</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-dark-flowchart-PG-12" data-look="classic" transform="translate(549.734375, 72.4533920288086)"><path d="M0,12.050825509873746 a58.1640625,12.050825509873746 0,0,0 116.328125,0 a58.1640625,12.050825509873746 0,0,0 -116.328125,0 l0,72.05082550987375 a58.1640625,12.050825509873746 0,0,0 116.328125,0 l0,-72.05082550987375" class="basic label-container outer-path" style="" transform="translate(-58.1640625, -48.07623826481062)"/><g class="label" style="" transform="translate(-50.6640625, -12.5)"><rect/><foreignObject width="101.328125" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Postgres<br />source of truth</p></span></div></foreignObject></g></g><g class="node default" id="m-58b7ff999bbf-dark-flowchart-Q-13" data-look="classic" transform="translate(810.78125, 72.4533920288086)"><rect class="basic label-container" style="" x="-52.671875" y="-37.5" width="105.34375" height="75"/><g class="label" style="" transform="translate(-22.671875, -22.5)"><rect/><foreignObject width="45.34375" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Kafka<br />events</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="m-58b7ff999bbf-dark-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="m-58b7ff999bbf-dark-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><linearGradient id="m-58b7ff999bbf-dark-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#3f3f46" stop-opacity="1"/><stop offset="100%" stop-color="#3f3f46" stop-opacity="1"/></linearGradient></svg>
</div>
</figure><p><strong>Числовые прикидки:</strong></p>
<ul>
<li><strong>Capacity.</strong> 30k RPS пика → допустимо терять ~30 запросов/сек. На Elasticsearch при 50M документов и <code>6 primary shards × 1 replica</code> (~33 GB на шард, в коридоре best-practice 30–50 GB): запрос идёт в координатор, координатор делает fan-out на 6 шардов, агрегирует. Целевая нагрузка <code>30–40k RPS</code> с запасом. На 8–12 ES-нодах (<code>64–128 GB RAM</code> каждая) держится с P99 в районе <code>300–400 ms</code> чистого ES-времени.</li>
<li><strong>Кэш Redis.</strong> Кластер на 3–6 нодах, <code>~50 GB</code> под топовые запросы и autocomplete. Hit rate <code>65–75%</code> — ключевой множитель: при 70% hit rate на ES падает только 30% от 30k RPS, то есть <code>~9k RPS</code>. Это уже посильно для умеренного ES-кластера. Прогрев после деплоя — 5–10 минут на горячих топ-1000 запросах.</li>
<li><strong>Индексирование.</strong> Postgres → Debezium / собственный CDC → Kafka → потребитель в ES. Lag индексирования: <code>15–60 секунд</code> на типовых изменениях, <code>2–5 минут</code> на массовых обновлениях цен (например, при загрузке от продавца XML-фида). Это <strong>freshness-SLI</strong> — ценник старше 60 секунд считается «плохим событием» по SLI-4.</li>
<li><strong>Структура документа и размер индекса.</strong> Каждая карточка в ES — денормализованный документ: <code>title, description, attributes (10–20 полей), price, stock, seller_rating, geo, popularity</code>. Размер ~3–5 KB на документ. <code>50M × 4 KB = ~200 GB primary</code> + 200 GB replica = 400 GB Lucene-данных. На 12 нодах ≈ ~33 GB на ноду, рабочее множество легко помещается в RAM.</li>
<li><strong>Failover.</strong> Active-passive между двумя AZ внутри региона. RTO <code>1–3 минуты</code> через автоматический promote secondary. RPO ~30 секунд через CDC.</li>
<li><strong>Алерты.</strong> Multi-window multi-burn-rate: две пары окон со своими threshold — быстрая пара <code>5 мин + 1 час</code> с burn-rate <code>14.4×</code> (срабатывает на острый инцидент за минуты, 2% бюджета за час) и медленная пара <code>30 мин + 6 часов</code> с burn-rate <code>6×</code> (ловит «тихую» деградацию, 5% бюджета за 6 часов). Это табличные значения из главы Alerting on SLOs в Google SRE Workbook. Подробно про burn-rate как множитель — в моей предыдущей статье <a href="/posts/burn-rate-is-not-speed/">«Скорость сгорания бюджета ошибок»</a>
.</li>
</ul>
<p><strong>Что добавилось по сравнению с 99.0%:</strong></p>
<ul>
<li>Отдельный поисковый индекс (ES) — потому что <code>pg_trgm</code> на 30k RPS + ranking + facets уже не вытянет с нужной P99.</li>
<li>Redis-кластер — без него ES под пиком пришлось бы масштабировать в 3–4 раза.</li>
<li>CDC + Kafka — из-за разделения source of truth и поискового индекса нужна асинхронная синхронизация. Это новый слой риска (lag, потеря событий) и новый SLO на freshness.</li>
<li>Active-passive failover — потому что 43 минуты бюджета мало для ручного переключения.</li>
<li>Burn-rate-алерты — потому что классические «5xx &gt; 1%» при 0.1% бюджета будут срабатывать слишком поздно или генерить шум.</li>
</ul>
<p><strong>Что намеренно НЕ делаем:</strong></p>
<ul>
<li>Не делаем active-active multi-region. На 99.9% это избыточно: один регион с грамотным failover между AZ покрывает бюджет с большим запасом, а active-active добавляет проблем синхронизации (split-brain, write-write конфликты, кросс-региональные чтения по сети).</li>
<li>Не делаем repair-aware кэш — на 99.9% достаточно правильного TTL и event-driven invalidation.</li>
<li>Не делаем graceful degradation на уровне UI («поиск работает, ranking упал»). Это усложнение, оправданное на <code>99.99%+</code>.</li>
</ul>
<p><strong>Стоимость:</strong> <strong>4–6× baseline</strong> в инфраструктуре, <strong>2–3× baseline</strong> в людях (нужна команда SRE с дежурствами, отдельные процессы для Kafka и ES).</p>
<h3 id="slo-9999-дорогая-надёжность-для-tier-1-сценариев">SLO 99.99%: дорогая надёжность для tier-1 сценариев</h3>
<p><strong>Бюджет:</strong> ~2.6M «плохих» запросов за 30 дней, или <strong>~1 мин 27 с</strong> полного даунтайма на пике / <strong>~4 мин 20 с</strong> при средней нагрузке. На инцидент остаются секунды-минуты — реакция должна быть <strong>автоматической</strong>. Ручной разбор перед remediation = превышение бюджета.</p>
<p><strong>Когда уместно:</strong> tier-1 пользовательские сценарии в крупном бизнесе уровня Ozon/Wildberries или сопоставимого по GMV, где минута даунтайма стоит сотни тысяч долларов и оправдывает мультипликатор инфраструктуры. Платёжные шлюзы, биржи, ключевые поисковые сценарии больших маркетплейсов.</p>
<p><strong>Read path:</strong></p>
<figure class="mermaid mermaid--prerendered" aria-label="Mermaid diagram">
<div class="mermaid-svg mermaid-svg--light">
<svg id="m-94d254942e3a-light" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 1388.78px; background-color: transparent;" viewBox="0 -35 1388.78125 476.625" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#m-94d254942e3a-light{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;fill:#1c1c1f;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#m-94d254942e3a-light .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#m-94d254942e3a-light .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#m-94d254942e3a-light .error-icon{fill:#fee2e2;}#m-94d254942e3a-light .error-text{fill:#7f1d1d;stroke:#7f1d1d;}#m-94d254942e3a-light .edge-thickness-normal{stroke-width:1px;}#m-94d254942e3a-light .edge-thickness-thick{stroke-width:3.5px;}#m-94d254942e3a-light .edge-pattern-solid{stroke-dasharray:0;}#m-94d254942e3a-light .edge-thickness-invisible{stroke-width:0;fill:none;}#m-94d254942e3a-light .edge-pattern-dashed{stroke-dasharray:3;}#m-94d254942e3a-light .edge-pattern-dotted{stroke-dasharray:2;}#m-94d254942e3a-light .marker{fill:#5b5b62;stroke:#5b5b62;}#m-94d254942e3a-light .marker.cross{stroke:#5b5b62;}#m-94d254942e3a-light svg{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;}#m-94d254942e3a-light p{margin:0;}#m-94d254942e3a-light .label{font-family:Inter,system-ui,-apple-system,sans-serif;color:#1c1c1f;}#m-94d254942e3a-light .cluster-label text{fill:#1c1c1f;}#m-94d254942e3a-light .cluster-label span{color:#1c1c1f;}#m-94d254942e3a-light .cluster-label span p{background-color:transparent;}#m-94d254942e3a-light .label text,#m-94d254942e3a-light span{fill:#1c1c1f;color:#1c1c1f;}#m-94d254942e3a-light .node rect,#m-94d254942e3a-light .node circle,#m-94d254942e3a-light .node ellipse,#m-94d254942e3a-light .node polygon,#m-94d254942e3a-light .node path{fill:#ffffff;stroke:#c8c5bb;stroke-width:1px;}#m-94d254942e3a-light .rough-node .label text,#m-94d254942e3a-light .node .label text,#m-94d254942e3a-light .image-shape .label,#m-94d254942e3a-light .icon-shape .label{text-anchor:middle;}#m-94d254942e3a-light .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#m-94d254942e3a-light .rough-node .label,#m-94d254942e3a-light .node .label,#m-94d254942e3a-light .image-shape .label,#m-94d254942e3a-light .icon-shape .label{text-align:center;}#m-94d254942e3a-light .node.clickable{cursor:pointer;}#m-94d254942e3a-light .root .anchor path{fill:#5b5b62!important;stroke-width:0;stroke:#5b5b62;}#m-94d254942e3a-light .arrowheadPath{fill:rgba(255, 255, 255, 0);}#m-94d254942e3a-light .edgePath .path{stroke:#5b5b62;stroke-width:1px;}#m-94d254942e3a-light .flowchart-link{stroke:#5b5b62;fill:none;}#m-94d254942e3a-light .edgeLabel{background-color:#fafaf7;text-align:center;}#m-94d254942e3a-light .edgeLabel p{background-color:#fafaf7;}#m-94d254942e3a-light .edgeLabel rect{opacity:0.5;background-color:#fafaf7;fill:#fafaf7;}#m-94d254942e3a-light .labelBkg{background-color:rgba(250, 250, 247, 0.5);}#m-94d254942e3a-light .cluster rect{fill:#f3f1ed;stroke:#c8c5bb;stroke-width:1px;}#m-94d254942e3a-light .cluster text{fill:#1c1c1f;}#m-94d254942e3a-light .cluster span{color:#1c1c1f;}#m-94d254942e3a-light div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:12px;background:#fed7aa;border:1px solid #c2410c;border-radius:2px;pointer-events:none;z-index:100;}#m-94d254942e3a-light .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#1c1c1f;}#m-94d254942e3a-light rect.text{fill:none;stroke-width:0;}#m-94d254942e3a-light .icon-shape,#m-94d254942e3a-light .image-shape{background-color:#fafaf7;text-align:center;}#m-94d254942e3a-light .icon-shape p,#m-94d254942e3a-light .image-shape p{background-color:#fafaf7;padding:2px;}#m-94d254942e3a-light .icon-shape .label rect,#m-94d254942e3a-light .image-shape .label rect{opacity:0.5;background-color:#fafaf7;fill:#fafaf7;}#m-94d254942e3a-light .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#m-94d254942e3a-light .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#m-94d254942e3a-light .node .neo-node{stroke:#c8c5bb;}#m-94d254942e3a-light [data-look="neo"].node rect,#m-94d254942e3a-light [data-look="neo"].cluster rect,#m-94d254942e3a-light [data-look="neo"].node polygon{stroke:url(#m-94d254942e3a-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-94d254942e3a-light [data-look="neo"].node path{stroke:url(#m-94d254942e3a-light-gradient);stroke-width:1px;}#m-94d254942e3a-light [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-94d254942e3a-light [data-look="neo"].node .neo-line path{stroke:#c8c5bb;filter:none;}#m-94d254942e3a-light [data-look="neo"].node circle{stroke:url(#m-94d254942e3a-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-94d254942e3a-light [data-look="neo"].node circle .state-start{fill:#000000;}#m-94d254942e3a-light [data-look="neo"].icon-shape .icon{fill:url(#m-94d254942e3a-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-94d254942e3a-light [data-look="neo"].icon-shape .icon-neo path{stroke:url(#m-94d254942e3a-light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-94d254942e3a-light :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="m-94d254942e3a-light_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-light_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-light_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-light_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-light_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-light_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-light_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-light_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-light_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-light_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-light_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="m-94d254942e3a-light_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M146.97,265.5L154.509,268.833C162.048,272.167,177.125,278.833,188.164,282.167C199.203,285.5,206.203,285.5,209.703,285.5L213.203,285.5" id="m-94d254942e3a-light-L_U_GA_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_U_GA_0" data-points="W3sieCI6MTQ2Ljk3MDAxNjg5MTg5MTksInkiOjI2NS41fSx7IngiOjE5Mi4yMDMxMjUsInkiOjI4NS41fSx7IngiOjIxNy4yMDMxMjUsInkiOjI4NS41fV0=" data-look="classic" marker-end="url(#m-94d254942e3a-light_flowchart-v2-pointEnd)"/><path d="M419.359,281.993L423.526,281.848C427.693,281.703,436.026,281.414,443.693,281.27C451.359,281.125,458.359,281.125,461.859,281.125L465.359,281.125" id="m-94d254942e3a-light-L_GA_RegA_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_GA_RegA_0" data-points="W3sieCI6NDE5LjM1OTM3NSwieSI6MjgxLjk5MjUxNzY2MDE4MDk3fSx7IngiOjQ0NC4zNTkzNzUsInkiOjI4MS4xMjV9LHsieCI6NDY5LjM1OTM3NSwieSI6MjgxLjEyNX1d" data-look="classic" marker-end="url(#m-94d254942e3a-light_flowchart-v2-pointEnd)"/><path d="M395.715,334.25L403.822,339.354C411.93,344.458,428.145,354.667,455.072,359.771C482,364.875,519.641,364.875,565.663,364.875C611.685,364.875,666.089,364.875,705.182,366.999C744.276,369.123,768.06,373.371,779.952,375.496L791.844,377.62" id="m-94d254942e3a-light-L_GA_RegB_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_GA_RegB_0" data-points="W3sieCI6Mzk1LjcxNTA1OTA1NTExODEsInkiOjMzNC4yNX0seyJ4Ijo0NDQuMzU5Mzc1LCJ5IjozNjQuODc1fSx7IngiOjU1Ny4yODEyNSwieSI6MzY0Ljg3NX0seyJ4Ijo3MjAuNDkyMTg3NSwieSI6MzY0Ljg3NX0seyJ4Ijo3OTUuNzgxMjUsInkiOjM3OC4zMjMwNzc2MTAwNzQxfV0=" data-look="classic" marker-end="url(#m-94d254942e3a-light_flowchart-v2-pointEnd)"/><path d="M337.949,236.75L355.684,192.792C373.419,148.833,408.889,60.917,445.445,16.958C482,-27,519.641,-27,565.663,-27C611.685,-27,666.089,-27,722.449,-27C778.81,-27,837.128,-27,898.426,-27C959.724,-27,1024.003,-27,1084.016,17.539C1144.03,62.078,1199.778,151.156,1227.652,195.695L1255.526,240.234" id="m-94d254942e3a-light-L_GA_RegC_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_GA_RegC_0" data-points="W3sieCI6MzM3Ljk0OTQzNzUsInkiOjIzNi43NX0seyJ4Ijo0NDQuMzU5Mzc1LCJ5IjotMjd9LHsieCI6NTU3LjI4MTI1LCJ5IjotMjd9LHsieCI6NzIwLjQ5MjE4NzUsInkiOi0yN30seyJ4Ijo4OTUuNDQ1MzEyNSwieSI6LTI3fSx7IngiOjEwODguMjgxMjUsInkiOi0yN30seyJ4IjoxMjU3LjY0ODMxMDcyNTE1MjIsInkiOjI0My42MjV9XQ==" data-look="classic" marker-end="url(#m-94d254942e3a-light_flowchart-v2-pointEnd)"/><path d="M626.468,329.875L642.139,340.917C657.81,351.958,689.151,374.042,716.703,385.083C744.255,396.125,768.018,396.125,779.9,396.125L791.781,396.125" id="m-94d254942e3a-light-L_RegA_RegB_0" class="edge-thickness-thick edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_RegA_RegB_0" data-points="W3sieCI6NjI2LjQ2ODQ5NTI0NDU2NTIsInkiOjMyOS44NzV9LHsieCI6NzIwLjQ5MjE4NzUsInkiOjM5Ni4xMjV9LHsieCI6Nzk1Ljc4MTI1LCJ5IjozOTYuMTI1fV0=" data-look="classic" marker-end="url(#m-94d254942e3a-light_flowchart-v2-pointEnd)"/><path d="M795.781,420.336L783.233,423.384C770.685,426.432,745.589,432.529,714.738,417.915C683.887,403.301,647.282,367.977,628.98,350.315L610.677,332.653" id="m-94d254942e3a-light-L_RegB_RegA_0" class="edge-thickness-thick edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_RegB_RegA_0" data-points="W3sieCI6Nzk1Ljc4MTI1LCJ5Ijo0MjAuMzM1NjE0NDUwMjk5Mn0seyJ4Ijo3MjAuNDkyMTg3NSwieSI6NDM4LjYyNX0seyJ4Ijo2MDcuNzk4OTIxMTMwOTUyNCwieSI6MzI5Ljg3NX1d" data-look="classic" marker-end="url(#m-94d254942e3a-light_flowchart-v2-pointEnd)"/><path d="M649.203,281.125L661.085,281.125C672.966,281.125,696.729,281.125,737.77,281.125C778.81,281.125,837.128,281.125,898.426,281.125C959.724,281.125,1024.003,281.125,1071.004,281.125C1118.005,281.125,1147.729,281.125,1162.591,281.125L1177.453,281.125" id="m-94d254942e3a-light-L_RegA_RegC_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_RegA_RegC_0" data-points="W3sieCI6NjQ1LjIwMzEyNSwieSI6MjgxLjEyNX0seyJ4Ijo3MjAuNDkyMTg3NSwieSI6MjgxLjEyNX0seyJ4Ijo4OTUuNDQ1MzEyNSwieSI6MjgxLjEyNX0seyJ4IjoxMDg4LjI4MTI1LCJ5IjoyODEuMTI1fSx7IngiOjExODEuNDUzMTI1LCJ5IjoyODEuMTI1fV0=" data-look="classic" marker-start="url(#m-94d254942e3a-light_flowchart-v2-pointStart)" marker-end="url(#m-94d254942e3a-light_flowchart-v2-pointEnd)"/><path d="M999.109,396.125L1013.971,396.125C1028.833,396.125,1058.557,396.125,1094.506,383.55C1130.454,370.975,1172.627,345.824,1193.714,333.249L1214.8,320.674" id="m-94d254942e3a-light-L_RegB_RegC_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_RegB_RegC_0" data-points="W3sieCI6OTk1LjEwOTM3NSwieSI6Mzk2LjEyNX0seyJ4IjoxMDg4LjI4MTI1LCJ5IjozOTYuMTI1fSx7IngiOjEyMTguMjM1OTAzNTMyNjA4NywieSI6MzE4LjYyNX1d" data-look="classic" marker-start="url(#m-94d254942e3a-light_flowchart-v2-pointStart)" marker-end="url(#m-94d254942e3a-light_flowchart-v2-pointEnd)"/><path d="M591.049,232.375L612.623,201.229C634.197,170.083,677.344,107.792,710.916,76.646C744.487,45.5,768.482,45.5,780.479,45.5L792.477,45.5" id="m-94d254942e3a-light-L_RegA_RAW_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_RegA_RAW_0" data-points="W3sieCI6NTkxLjA0OTAzMDE3MjQxMzgsInkiOjIzMi4zNzV9LHsieCI6NzIwLjQ5MjE4NzUsInkiOjQ1LjV9LHsieCI6Nzk2LjQ3NjU2MjUsInkiOjQ1LjV9XQ==" data-look="classic" marker-end="url(#m-94d254942e3a-light_flowchart-v2-pointEnd)"/><path d="M607.799,232.375L626.581,214.25C645.363,196.125,682.928,159.875,714.758,146.085C746.589,132.295,772.685,140.965,785.734,145.3L798.782,149.635" id="m-94d254942e3a-light-L_RegA_Deg_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_RegA_Deg_0" data-points="W3sieCI6NjA3Ljc5ODkyMTEzMDk1MjQsInkiOjIzMi4zNzV9LHsieCI6NzIwLjQ5MjE4NzUsInkiOjEyMy42MjV9LHsieCI6ODAyLjU3ODEyNSwieSI6MTUwLjg5NjU2MjY5NTM2NDgyfV0=" data-look="classic" marker-end="url(#m-94d254942e3a-light_flowchart-v2-pointEnd)"/><path d="M802.578,187.058L788.897,187.84C775.216,188.622,747.854,190.186,706.971,190.968C666.089,191.75,611.685,191.75,565.663,191.75C519.641,191.75,482,191.75,442.167,191.75C402.333,191.75,360.307,191.75,318.281,191.75C276.255,191.75,234.229,191.75,206.024,195.016C177.819,198.282,163.434,204.814,156.242,208.08L149.05,211.346" id="m-94d254942e3a-light-L_Deg_U_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Deg_U_0" data-points="W3sieCI6ODAyLjU3ODEyNSwieSI6MTg3LjA1ODExODI0NTk1ODc1fSx7IngiOjcyMC40OTIxODc1LCJ5IjoxOTEuNzV9LHsieCI6NTU3LjI4MTI1LCJ5IjoxOTEuNzV9LHsieCI6NDQ0LjM1OTM3NSwieSI6MTkxLjc1fSx7IngiOjMxOC4yODEyNSwieSI6MTkxLjc1fSx7IngiOjE5Mi4yMDMxMjUsInkiOjE5MS43NX0seyJ4IjoxNDUuNDA3Njg5MTQ0NzM2ODUsInkiOjIxM31d" data-look="classic" marker-end="url(#m-94d254942e3a-light_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_U_GA_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_GA_RegA_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_GA_RegB_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_GA_RegC_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(720.4921875, 396.125)"><g class="label" data-id="L_RegA_RegB_0" transform="translate(-50.2890625, -11.25)"><foreignObject width="100.578125" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>sync для tier-1</p></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(692.02177, 411.15079)"><g class="label" data-id="L_RegB_RegA_0" transform="translate(-50.2890625, -11.25)"><foreignObject width="100.578125" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>sync для tier-1</p></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(895.4453125, 281.125)"><g class="label" data-id="L_RegA_RegC_0" transform="translate(-68.171875, -11.25)"><foreignObject width="136.34375" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>async для каталога</p></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(1088.28125, 396.125)"><g class="label" data-id="L_RegB_RegC_0" transform="translate(-68.171875, -11.25)"><foreignObject width="136.34375" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>async для каталога</p></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_RegA_RAW_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_RegA_Deg_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Deg_U_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="m-94d254942e3a-light-flowchart-U-0" data-look="classic" transform="translate(87.6015625, 239.25)"><rect class="basic label-container" style="" x="-79.6015625" y="-26.25" width="159.203125" height="52.5"/><g class="label" style="" transform="translate(-49.6015625, -11.25)"><rect/><foreignObject width="99.203125" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Пользователь</p></span></div></foreignObject></g></g><g class="node default" id="m-94d254942e3a-light-flowchart-GA-1" data-look="classic" transform="translate(318.28125, 285.5)"><rect class="basic label-container" style="" x="-101.078125" y="-48.75" width="202.15625" height="97.5"/><g class="label" style="" transform="translate(-71.078125, -33.75)"><rect/><foreignObject width="142.15625" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Geo-Anycast<br />+ Global LB<br />health-aware routing</p></span></div></foreignObject></g></g><g class="node default" id="m-94d254942e3a-light-flowchart-RegA-3" data-look="classic" transform="translate(557.28125, 281.125)"><rect class="basic label-container" style="" x="-87.921875" y="-48.75" width="175.84375" height="97.5"/><g class="label" style="" transform="translate(-57.921875, -33.75)"><rect/><foreignObject width="115.84375" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Регион A<br />Search + Redis +<br />ES + Postgres</p></span></div></foreignObject></g></g><g class="node default" id="m-94d254942e3a-light-flowchart-RegB-5" data-look="classic" transform="translate(895.4453125, 396.125)"><rect class="basic label-container" style="" x="-99.6640625" y="-37.5" width="199.328125" height="75"/><g class="label" style="" transform="translate(-69.6640625, -22.5)"><rect/><foreignObject width="139.328125" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Регион B<br />полная копия стека</p></span></div></foreignObject></g></g><g class="node default" id="m-94d254942e3a-light-flowchart-RegC-7" data-look="classic" transform="translate(1281.1171875, 281.125)"><rect class="basic label-container" style="" x="-99.6640625" y="-37.5" width="199.328125" height="75"/><g class="label" style="" transform="translate(-69.6640625, -22.5)"><rect/><foreignObject width="139.328125" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Регион C<br />полная копия стека</p></span></div></foreignObject></g></g><g class="node default" id="m-94d254942e3a-light-flowchart-RAW-17" data-look="classic" transform="translate(895.4453125, 45.5)"><rect class="basic label-container" style="" x="-98.96875" y="-37.5" width="197.9375" height="75"/><g class="label" style="" transform="translate(-68.96875, -22.5)"><rect/><foreignObject width="137.9375" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Repair-aware Cache<br />per-region</p></span></div></foreignObject></g></g><g class="node default" id="m-94d254942e3a-light-flowchart-Deg-19" data-look="classic" transform="translate(895.4453125, 181.75)"><rect class="basic label-container" style="" x="-92.8671875" y="-48.75" width="185.734375" height="97.5"/><g class="label" style="" transform="translate(-62.8671875, -33.75)"><rect/><foreignObject width="125.734375" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Degradation Layer<br />ranking упал —<br />отдаём базовое</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="m-94d254942e3a-light-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="m-94d254942e3a-light-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><linearGradient id="m-94d254942e3a-light-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#c8c5bb" stop-opacity="1"/><stop offset="100%" stop-color="#c8c5bb" stop-opacity="1"/></linearGradient></svg>
</div>
<div class="mermaid-svg mermaid-svg--dark">
<svg id="m-94d254942e3a-dark" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 1388.78px; background-color: transparent;" viewBox="0 -35 1388.78125 476.625" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#m-94d254942e3a-dark{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;fill:#e8e6df;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#m-94d254942e3a-dark .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#m-94d254942e3a-dark .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#m-94d254942e3a-dark .error-icon{fill:#7f1d1d;}#m-94d254942e3a-dark .error-text{fill:#fecaca;stroke:#fecaca;}#m-94d254942e3a-dark .edge-thickness-normal{stroke-width:1px;}#m-94d254942e3a-dark .edge-thickness-thick{stroke-width:3.5px;}#m-94d254942e3a-dark .edge-pattern-solid{stroke-dasharray:0;}#m-94d254942e3a-dark .edge-thickness-invisible{stroke-width:0;fill:none;}#m-94d254942e3a-dark .edge-pattern-dashed{stroke-dasharray:3;}#m-94d254942e3a-dark .edge-pattern-dotted{stroke-dasharray:2;}#m-94d254942e3a-dark .marker{fill:#a8a89e;stroke:#a8a89e;}#m-94d254942e3a-dark .marker.cross{stroke:#a8a89e;}#m-94d254942e3a-dark svg{font-family:Inter,system-ui,-apple-system,sans-serif;font-size:15px;}#m-94d254942e3a-dark p{margin:0;}#m-94d254942e3a-dark .label{font-family:Inter,system-ui,-apple-system,sans-serif;color:#e8e6df;}#m-94d254942e3a-dark .cluster-label text{fill:#e8e6df;}#m-94d254942e3a-dark .cluster-label span{color:#e8e6df;}#m-94d254942e3a-dark .cluster-label span p{background-color:transparent;}#m-94d254942e3a-dark .label text,#m-94d254942e3a-dark span{fill:#e8e6df;color:#e8e6df;}#m-94d254942e3a-dark .node rect,#m-94d254942e3a-dark .node circle,#m-94d254942e3a-dark .node ellipse,#m-94d254942e3a-dark .node polygon,#m-94d254942e3a-dark .node path{fill:#23252a;stroke:#3f3f46;stroke-width:1px;}#m-94d254942e3a-dark .rough-node .label text,#m-94d254942e3a-dark .node .label text,#m-94d254942e3a-dark .image-shape .label,#m-94d254942e3a-dark .icon-shape .label{text-anchor:middle;}#m-94d254942e3a-dark .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#m-94d254942e3a-dark .rough-node .label,#m-94d254942e3a-dark .node .label,#m-94d254942e3a-dark .image-shape .label,#m-94d254942e3a-dark .icon-shape .label{text-align:center;}#m-94d254942e3a-dark .node.clickable{cursor:pointer;}#m-94d254942e3a-dark .root .anchor path{fill:#a8a89e!important;stroke-width:0;stroke:#a8a89e;}#m-94d254942e3a-dark .arrowheadPath{fill:rgba(255, 255, 255, 0);}#m-94d254942e3a-dark .edgePath .path{stroke:#a8a89e;stroke-width:1px;}#m-94d254942e3a-dark .flowchart-link{stroke:#a8a89e;fill:none;}#m-94d254942e3a-dark .edgeLabel{background-color:#1a1b1e;text-align:center;}#m-94d254942e3a-dark .edgeLabel p{background-color:#1a1b1e;}#m-94d254942e3a-dark .edgeLabel rect{opacity:0.5;background-color:#1a1b1e;fill:#1a1b1e;}#m-94d254942e3a-dark .labelBkg{background-color:rgba(26, 27, 30, 0.5);}#m-94d254942e3a-dark .cluster rect{fill:#2a2b2f;stroke:#3f3f46;stroke-width:1px;}#m-94d254942e3a-dark .cluster text{fill:#e8e6df;}#m-94d254942e3a-dark .cluster span{color:#e8e6df;}#m-94d254942e3a-dark div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:12px;background:#7c2d12;border:1px solid #fb923c;border-radius:2px;pointer-events:none;z-index:100;}#m-94d254942e3a-dark .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#e8e6df;}#m-94d254942e3a-dark rect.text{fill:none;stroke-width:0;}#m-94d254942e3a-dark .icon-shape,#m-94d254942e3a-dark .image-shape{background-color:#1a1b1e;text-align:center;}#m-94d254942e3a-dark .icon-shape p,#m-94d254942e3a-dark .image-shape p{background-color:#1a1b1e;padding:2px;}#m-94d254942e3a-dark .icon-shape .label rect,#m-94d254942e3a-dark .image-shape .label rect{opacity:0.5;background-color:#1a1b1e;fill:#1a1b1e;}#m-94d254942e3a-dark .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#m-94d254942e3a-dark .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#m-94d254942e3a-dark .node .neo-node{stroke:#3f3f46;}#m-94d254942e3a-dark [data-look="neo"].node rect,#m-94d254942e3a-dark [data-look="neo"].cluster rect,#m-94d254942e3a-dark [data-look="neo"].node polygon{stroke:url(#m-94d254942e3a-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-94d254942e3a-dark [data-look="neo"].node path{stroke:url(#m-94d254942e3a-dark-gradient);stroke-width:1px;}#m-94d254942e3a-dark [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-94d254942e3a-dark [data-look="neo"].node .neo-line path{stroke:#3f3f46;filter:none;}#m-94d254942e3a-dark [data-look="neo"].node circle{stroke:url(#m-94d254942e3a-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-94d254942e3a-dark [data-look="neo"].node circle .state-start{fill:#000000;}#m-94d254942e3a-dark [data-look="neo"].icon-shape .icon{fill:url(#m-94d254942e3a-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-94d254942e3a-dark [data-look="neo"].icon-shape .icon-neo path{stroke:url(#m-94d254942e3a-dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#m-94d254942e3a-dark :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="m-94d254942e3a-dark_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-dark_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-dark_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-dark_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-dark_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-dark_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-dark_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-dark_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-dark_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-dark_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="m-94d254942e3a-dark_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="m-94d254942e3a-dark_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M146.97,265.5L154.509,268.833C162.048,272.167,177.125,278.833,188.164,282.167C199.203,285.5,206.203,285.5,209.703,285.5L213.203,285.5" id="m-94d254942e3a-dark-L_U_GA_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_U_GA_0" data-points="W3sieCI6MTQ2Ljk3MDAxNjg5MTg5MTksInkiOjI2NS41fSx7IngiOjE5Mi4yMDMxMjUsInkiOjI4NS41fSx7IngiOjIxNy4yMDMxMjUsInkiOjI4NS41fV0=" data-look="classic" marker-end="url(#m-94d254942e3a-dark_flowchart-v2-pointEnd)"/><path d="M419.359,281.993L423.526,281.848C427.693,281.703,436.026,281.414,443.693,281.27C451.359,281.125,458.359,281.125,461.859,281.125L465.359,281.125" id="m-94d254942e3a-dark-L_GA_RegA_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_GA_RegA_0" data-points="W3sieCI6NDE5LjM1OTM3NSwieSI6MjgxLjk5MjUxNzY2MDE4MDk3fSx7IngiOjQ0NC4zNTkzNzUsInkiOjI4MS4xMjV9LHsieCI6NDY5LjM1OTM3NSwieSI6MjgxLjEyNX1d" data-look="classic" marker-end="url(#m-94d254942e3a-dark_flowchart-v2-pointEnd)"/><path d="M395.715,334.25L403.822,339.354C411.93,344.458,428.145,354.667,455.072,359.771C482,364.875,519.641,364.875,565.663,364.875C611.685,364.875,666.089,364.875,705.182,366.999C744.276,369.123,768.06,373.371,779.952,375.496L791.844,377.62" id="m-94d254942e3a-dark-L_GA_RegB_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_GA_RegB_0" data-points="W3sieCI6Mzk1LjcxNTA1OTA1NTExODEsInkiOjMzNC4yNX0seyJ4Ijo0NDQuMzU5Mzc1LCJ5IjozNjQuODc1fSx7IngiOjU1Ny4yODEyNSwieSI6MzY0Ljg3NX0seyJ4Ijo3MjAuNDkyMTg3NSwieSI6MzY0Ljg3NX0seyJ4Ijo3OTUuNzgxMjUsInkiOjM3OC4zMjMwNzc2MTAwNzQxfV0=" data-look="classic" marker-end="url(#m-94d254942e3a-dark_flowchart-v2-pointEnd)"/><path d="M337.949,236.75L355.684,192.792C373.419,148.833,408.889,60.917,445.445,16.958C482,-27,519.641,-27,565.663,-27C611.685,-27,666.089,-27,722.449,-27C778.81,-27,837.128,-27,898.426,-27C959.724,-27,1024.003,-27,1084.016,17.539C1144.03,62.078,1199.778,151.156,1227.652,195.695L1255.526,240.234" id="m-94d254942e3a-dark-L_GA_RegC_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_GA_RegC_0" data-points="W3sieCI6MzM3Ljk0OTQzNzUsInkiOjIzNi43NX0seyJ4Ijo0NDQuMzU5Mzc1LCJ5IjotMjd9LHsieCI6NTU3LjI4MTI1LCJ5IjotMjd9LHsieCI6NzIwLjQ5MjE4NzUsInkiOi0yN30seyJ4Ijo4OTUuNDQ1MzEyNSwieSI6LTI3fSx7IngiOjEwODguMjgxMjUsInkiOi0yN30seyJ4IjoxMjU3LjY0ODMxMDcyNTE1MjIsInkiOjI0My42MjV9XQ==" data-look="classic" marker-end="url(#m-94d254942e3a-dark_flowchart-v2-pointEnd)"/><path d="M626.468,329.875L642.139,340.917C657.81,351.958,689.151,374.042,716.703,385.083C744.255,396.125,768.018,396.125,779.9,396.125L791.781,396.125" id="m-94d254942e3a-dark-L_RegA_RegB_0" class="edge-thickness-thick edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_RegA_RegB_0" data-points="W3sieCI6NjI2LjQ2ODQ5NTI0NDU2NTIsInkiOjMyOS44NzV9LHsieCI6NzIwLjQ5MjE4NzUsInkiOjM5Ni4xMjV9LHsieCI6Nzk1Ljc4MTI1LCJ5IjozOTYuMTI1fV0=" data-look="classic" marker-end="url(#m-94d254942e3a-dark_flowchart-v2-pointEnd)"/><path d="M795.781,420.336L783.233,423.384C770.685,426.432,745.589,432.529,714.738,417.915C683.887,403.301,647.282,367.977,628.98,350.315L610.677,332.653" id="m-94d254942e3a-dark-L_RegB_RegA_0" class="edge-thickness-thick edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_RegB_RegA_0" data-points="W3sieCI6Nzk1Ljc4MTI1LCJ5Ijo0MjAuMzM1NjE0NDUwMjk5Mn0seyJ4Ijo3MjAuNDkyMTg3NSwieSI6NDM4LjYyNX0seyJ4Ijo2MDcuNzk4OTIxMTMwOTUyNCwieSI6MzI5Ljg3NX1d" data-look="classic" marker-end="url(#m-94d254942e3a-dark_flowchart-v2-pointEnd)"/><path d="M649.203,281.125L661.085,281.125C672.966,281.125,696.729,281.125,737.77,281.125C778.81,281.125,837.128,281.125,898.426,281.125C959.724,281.125,1024.003,281.125,1071.004,281.125C1118.005,281.125,1147.729,281.125,1162.591,281.125L1177.453,281.125" id="m-94d254942e3a-dark-L_RegA_RegC_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_RegA_RegC_0" data-points="W3sieCI6NjQ1LjIwMzEyNSwieSI6MjgxLjEyNX0seyJ4Ijo3MjAuNDkyMTg3NSwieSI6MjgxLjEyNX0seyJ4Ijo4OTUuNDQ1MzEyNSwieSI6MjgxLjEyNX0seyJ4IjoxMDg4LjI4MTI1LCJ5IjoyODEuMTI1fSx7IngiOjExODEuNDUzMTI1LCJ5IjoyODEuMTI1fV0=" data-look="classic" marker-start="url(#m-94d254942e3a-dark_flowchart-v2-pointStart)" marker-end="url(#m-94d254942e3a-dark_flowchart-v2-pointEnd)"/><path d="M999.109,396.125L1013.971,396.125C1028.833,396.125,1058.557,396.125,1094.506,383.55C1130.454,370.975,1172.627,345.824,1193.714,333.249L1214.8,320.674" id="m-94d254942e3a-dark-L_RegB_RegC_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_RegB_RegC_0" data-points="W3sieCI6OTk1LjEwOTM3NSwieSI6Mzk2LjEyNX0seyJ4IjoxMDg4LjI4MTI1LCJ5IjozOTYuMTI1fSx7IngiOjEyMTguMjM1OTAzNTMyNjA4NywieSI6MzE4LjYyNX1d" data-look="classic" marker-start="url(#m-94d254942e3a-dark_flowchart-v2-pointStart)" marker-end="url(#m-94d254942e3a-dark_flowchart-v2-pointEnd)"/><path d="M591.049,232.375L612.623,201.229C634.197,170.083,677.344,107.792,710.916,76.646C744.487,45.5,768.482,45.5,780.479,45.5L792.477,45.5" id="m-94d254942e3a-dark-L_RegA_RAW_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_RegA_RAW_0" data-points="W3sieCI6NTkxLjA0OTAzMDE3MjQxMzgsInkiOjIzMi4zNzV9LHsieCI6NzIwLjQ5MjE4NzUsInkiOjQ1LjV9LHsieCI6Nzk2LjQ3NjU2MjUsInkiOjQ1LjV9XQ==" data-look="classic" marker-end="url(#m-94d254942e3a-dark_flowchart-v2-pointEnd)"/><path d="M607.799,232.375L626.581,214.25C645.363,196.125,682.928,159.875,714.758,146.085C746.589,132.295,772.685,140.965,785.734,145.3L798.782,149.635" id="m-94d254942e3a-dark-L_RegA_Deg_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_RegA_Deg_0" data-points="W3sieCI6NjA3Ljc5ODkyMTEzMDk1MjQsInkiOjIzMi4zNzV9LHsieCI6NzIwLjQ5MjE4NzUsInkiOjEyMy42MjV9LHsieCI6ODAyLjU3ODEyNSwieSI6MTUwLjg5NjU2MjY5NTM2NDgyfV0=" data-look="classic" marker-end="url(#m-94d254942e3a-dark_flowchart-v2-pointEnd)"/><path d="M802.578,187.058L788.897,187.84C775.216,188.622,747.854,190.186,706.971,190.968C666.089,191.75,611.685,191.75,565.663,191.75C519.641,191.75,482,191.75,442.167,191.75C402.333,191.75,360.307,191.75,318.281,191.75C276.255,191.75,234.229,191.75,206.024,195.016C177.819,198.282,163.434,204.814,156.242,208.08L149.05,211.346" id="m-94d254942e3a-dark-L_Deg_U_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Deg_U_0" data-points="W3sieCI6ODAyLjU3ODEyNSwieSI6MTg3LjA1ODExODI0NTk1ODc1fSx7IngiOjcyMC40OTIxODc1LCJ5IjoxOTEuNzV9LHsieCI6NTU3LjI4MTI1LCJ5IjoxOTEuNzV9LHsieCI6NDQ0LjM1OTM3NSwieSI6MTkxLjc1fSx7IngiOjMxOC4yODEyNSwieSI6MTkxLjc1fSx7IngiOjE5Mi4yMDMxMjUsInkiOjE5MS43NX0seyJ4IjoxNDUuNDA3Njg5MTQ0NzM2ODUsInkiOjIxM31d" data-look="classic" marker-end="url(#m-94d254942e3a-dark_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_U_GA_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_GA_RegA_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_GA_RegB_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_GA_RegC_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(720.4921875, 396.125)"><g class="label" data-id="L_RegA_RegB_0" transform="translate(-50.2890625, -11.25)"><foreignObject width="100.578125" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>sync для tier-1</p></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(692.02177, 411.15079)"><g class="label" data-id="L_RegB_RegA_0" transform="translate(-50.2890625, -11.25)"><foreignObject width="100.578125" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>sync для tier-1</p></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(895.4453125, 281.125)"><g class="label" data-id="L_RegA_RegC_0" transform="translate(-68.171875, -11.25)"><foreignObject width="136.34375" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>async для каталога</p></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(1088.28125, 396.125)"><g class="label" data-id="L_RegB_RegC_0" transform="translate(-68.171875, -11.25)"><foreignObject width="136.34375" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>async для каталога</p></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_RegA_RAW_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_RegA_Deg_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Deg_U_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="m-94d254942e3a-dark-flowchart-U-0" data-look="classic" transform="translate(87.6015625, 239.25)"><rect class="basic label-container" style="" x="-79.6015625" y="-26.25" width="159.203125" height="52.5"/><g class="label" style="" transform="translate(-49.6015625, -11.25)"><rect/><foreignObject width="99.203125" height="22.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Пользователь</p></span></div></foreignObject></g></g><g class="node default" id="m-94d254942e3a-dark-flowchart-GA-1" data-look="classic" transform="translate(318.28125, 285.5)"><rect class="basic label-container" style="" x="-101.078125" y="-48.75" width="202.15625" height="97.5"/><g class="label" style="" transform="translate(-71.078125, -33.75)"><rect/><foreignObject width="142.15625" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Geo-Anycast<br />+ Global LB<br />health-aware routing</p></span></div></foreignObject></g></g><g class="node default" id="m-94d254942e3a-dark-flowchart-RegA-3" data-look="classic" transform="translate(557.28125, 281.125)"><rect class="basic label-container" style="" x="-87.921875" y="-48.75" width="175.84375" height="97.5"/><g class="label" style="" transform="translate(-57.921875, -33.75)"><rect/><foreignObject width="115.84375" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Регион A<br />Search + Redis +<br />ES + Postgres</p></span></div></foreignObject></g></g><g class="node default" id="m-94d254942e3a-dark-flowchart-RegB-5" data-look="classic" transform="translate(895.4453125, 396.125)"><rect class="basic label-container" style="" x="-99.6640625" y="-37.5" width="199.328125" height="75"/><g class="label" style="" transform="translate(-69.6640625, -22.5)"><rect/><foreignObject width="139.328125" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Регион B<br />полная копия стека</p></span></div></foreignObject></g></g><g class="node default" id="m-94d254942e3a-dark-flowchart-RegC-7" data-look="classic" transform="translate(1281.1171875, 281.125)"><rect class="basic label-container" style="" x="-99.6640625" y="-37.5" width="199.328125" height="75"/><g class="label" style="" transform="translate(-69.6640625, -22.5)"><rect/><foreignObject width="139.328125" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Регион C<br />полная копия стека</p></span></div></foreignObject></g></g><g class="node default" id="m-94d254942e3a-dark-flowchart-RAW-17" data-look="classic" transform="translate(895.4453125, 45.5)"><rect class="basic label-container" style="" x="-98.96875" y="-37.5" width="197.9375" height="75"/><g class="label" style="" transform="translate(-68.96875, -22.5)"><rect/><foreignObject width="137.9375" height="45"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Repair-aware Cache<br />per-region</p></span></div></foreignObject></g></g><g class="node default" id="m-94d254942e3a-dark-flowchart-Deg-19" data-look="classic" transform="translate(895.4453125, 181.75)"><rect class="basic label-container" style="" x="-92.8671875" y="-48.75" width="185.734375" height="97.5"/><g class="label" style="" transform="translate(-62.8671875, -33.75)"><rect/><foreignObject width="125.734375" height="67.5"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Degradation Layer<br />ranking упал —<br />отдаём базовое</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="m-94d254942e3a-dark-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="m-94d254942e3a-dark-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><linearGradient id="m-94d254942e3a-dark-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#3f3f46" stop-opacity="1"/><stop offset="100%" stop-color="#3f3f46" stop-opacity="1"/></linearGradient></svg>
</div>
</figure><p><strong>Числовые прикидки:</strong></p>
<ul>
<li><strong>Capacity.</strong> 30k RPS пика делятся между 3 регионами <code>~по 10k RPS</code> нормально. Но <strong>каждый регион должен один переварить 100% трафика</strong> при отказе двух других — то есть sized под <code>30–40k RPS</code>. Это утроение инфраструктуры по сравнению с одним регионом 99.9%, плюс запас.</li>
<li><strong>Кросс-региональная синхронизация индексов.</strong> ES → Kafka MirrorMaker (или managed cross-region streaming) → ES в каждом регионе. Lag <code>5–30 секунд</code> между регионами в нормальном режиме, <code>1–3 минуты</code> при региональной сетевой деградации. Eventually consistent модель данных — для поиска приемлемо, для цен/наличия (freshness-SLI) — узкое место, требующее отдельной стратегии (часто — fetch цены при клике в карточку из локального region-БД).</li>
<li><strong>Repair-aware кэш.</strong> Когда регион вышел из деградации и снова healthy, кэш в нём может содержать <code>«грязные»</code> ключи — данные, менявшиеся в других регионах, но не доехавшие. Решение: каждый ключ в кэше помечен суффиксом версии данных (<code>hash</code> или <code>LSN</code>); при возврате региона — проактивный прогрев топовых ключей со свежими версиями. Это отдельный сервис, обычно in-house.</li>
<li><strong>Graceful degradation.</strong> Если ranking-сервис упал — поиск отдаёт базовое ранжирование (popularity + recency) без персонализации. Если упал autocomplete — прячем подсказки, оставляя ввод. Если упал ES — отдаём кэш-результаты + предупреждение «возможно, не самые свежие». Каждый из этих режимов — отдельный код-path и отдельный SLI.</li>
<li><strong>Failover.</strong> Автоматический на уровне geo-anycast / global LB, RTO <code>5–30 секунд</code> на регион. Health-чеки агрегируют SLI критичного пути, а не пинг сервера.</li>
<li><strong>RPO.</strong> Околонулевой для критичных данных (заказы, корзина) через synchronous replication между двумя регионами + async на третий. Для каталога/индекса — <code>до 1 минуты</code>.</li>
<li><strong>Алерты.</strong> Multi-window multi-burn-rate с поджатыми окнами: быстрая пара <code>2 мин + 1 час</code> с threshold <code>36×</code> (для tier-1 порог берут агрессивнее, чем 14.4× — иначе быстрый алерт догонит инцидент уже после исчерпания бюджета) + медленная пара <code>15 мин + 3 часа</code> с threshold <code>~10×</code> для затяжной деградации. Auto-remediation для известных классов: автоматический drain региона при превышении burn-rate, автоматический rollback деплоя.</li>
</ul>
<p><strong>Что добавилось по сравнению с 99.9%:</strong></p>
<ul>
<li>Multi-region active-active — потому что 1 минута 27 секунд бюджета на пике не покрывают ни один региональный инцидент (4 мин 20 с в среднем — тоже).</li>
<li>Repair-aware кэш — потому что после возврата региона данные могут разойтись, и без проактивного прогрева накопится freshness-долг, съедающий SLI-4.</li>
<li>Graceful degradation — потому что без неё любой отказ зависимости (ranking, persona) забирает весь бюджет.</li>
<li>Auto-remediation — потому что человек физически не успевает посмотреть пейдж за 1 мин 27 с пикового бюджета, не то что разобраться.</li>
<li>Канареечный rollout с автоматическим откатом по burn-rate — каждый деплой иначе ставит весь бюджет.</li>
</ul>
<p><strong>Что намеренно НЕ делаем (и здесь это особенно важно):</strong></p>
<ul>
<li>Не идём в <code>99.999%</code> без очень сильного бизнес-обоснования. 26 секунд в месяц требуют существенно более сложной модели резервирования, чем 99.99%: multi-cloud или multi-provider, независимые DNS, частично независимые кодовые базы, подходы из telecom/aerospace. Это часто <strong>дешевле решить через UX</strong> — например, кэшированием выдачи на клиенте на минуту, чтобы из 100% даунтайма пользователь увидел только новые сессии.</li>
</ul>
<p><strong>Стоимость:</strong> <strong>15–25× baseline</strong> в инфраструктуре, <strong>8–10× baseline</strong> в людях (24/7 SRE, регулярные game days, отдельная команда reliability engineering).</p>
<h3 id="сводная-таблица-slo-как-бюджет-на-сложность">Сводная таблица: SLO как бюджет на сложность</h3>
<table>
  <thead>
      <tr>
          <th>Аспект</th>
          <th>99.0%</th>
          <th>99.9%</th>
          <th>99.99%</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Бюджет на пике (30 дней)</td>
          <td>~2 ч 24 мин</td>
          <td>~14 мин 26 с</td>
          <td>~1 мин 27 с</td>
      </tr>
      <tr>
          <td>Бюджет при средней нагрузке (30 дней)</td>
          <td>~7 ч 12 мин</td>
          <td>~43 мин</td>
          <td>~4 мин 20 с</td>
      </tr>
      <tr>
          <td>Бюджет в запросах (30 дней)</td>
          <td>~260M</td>
          <td>~26M</td>
          <td>~2.6M</td>
      </tr>
      <tr>
          <td>Регионы</td>
          <td>1</td>
          <td>1 (active-passive AZ)</td>
          <td>3+ (active-active)</td>
      </tr>
      <tr>
          <td>Поисковый индекс</td>
          <td><code>pg_trgm</code> в Postgres</td>
          <td>Elasticsearch (8–12 нод)</td>
          <td>ES per region</td>
      </tr>
      <tr>
          <td>Кэш</td>
          <td>In-memory LRU на app</td>
          <td>Redis cluster (~50 GB)</td>
          <td>Repair-aware Redis × N</td>
      </tr>
      <tr>
          <td>Индексирование</td>
          <td>Триггеры в БД</td>
          <td>CDC + Kafka</td>
          <td>Cross-region MirrorMaker</td>
      </tr>
      <tr>
          <td>Failover</td>
          <td>Ручной, RTO 30–60 мин</td>
          <td>Авто между AZ, RTO 1–3 мин</td>
          <td>Авто между регионами, RTO 5–30 с</td>
      </tr>
      <tr>
          <td>RPO</td>
          <td>~5 мин</td>
          <td>~30 с</td>
          <td>~0 для tier-1 / ~1 мин для каталога</td>
      </tr>
      <tr>
          <td>Алерты</td>
          <td>На симптомы</td>
          <td>Multi-window burn-rate</td>
          <td>+ Auto-remediation</td>
      </tr>
      <tr>
          <td>Деплои</td>
          <td>Без особых процедур</td>
          <td>Постепенный rollout</td>
          <td>Канарейка + auto-откат</td>
      </tr>
      <tr>
          <td>Graceful degradation</td>
          <td>Нет</td>
          <td>Частично</td>
          <td>Полная</td>
      </tr>
      <tr>
          <td><strong>Инфраструктура (× baseline)</strong></td>
          <td><strong>1×</strong></td>
          <td><strong>4–6×</strong></td>
          <td><strong>15–25×</strong></td>
      </tr>
      <tr>
          <td><strong>Люди (× baseline)</strong></td>
          <td><strong>1×</strong></td>
          <td><strong>2–3×</strong></td>
          <td><strong>8–10×</strong></td>
      </tr>
      <tr>
          <td>Когда оправдано</td>
          <td>Внутренние tools, MVP, не-критичные пути</td>
          <td>Production e-commerce средней руки</td>
          <td>Tier-1 в крупном бизнесе</td>
      </tr>
  </tbody>
</table>
<h3 id="главный-вывод-раздела">Главный вывод раздела</h3>
<p>Один и тот же кейс на трёх SLO — это <strong>три разные инженерные задачи</strong>. Не «та же задача с разными настройками», а с разной топологией, разными технологиями, разной операционной моделью, разной стоимостью.</p>
<p>Из этого следуют две вещи, которые часто упускают:</p>
<ol>
<li><strong>Поднять SLO задним числом — это переписать систему</strong>, а не «добавить мониторинга». Если архитектура построена под 99.0%, поднять её до 99.99% означает: добавить регионы, переписать индексирование под cross-region, ввести graceful degradation, перепроектировать кэш. Не «настройка пары флагов» — <strong>рефакторинг порядка половины кодовой базы</strong>.</li>
<li><strong>Снизить SLO задним числом</strong> освобождает бюджет, но <strong>не возвращает потраченных денег</strong>. Если ты построил под 99.99%, а реально нужно 99.9% — лишний регион уже куплен, репликация уже настроена, команда SRE уже нанята. Снижение SLO в этом случае имеет смысл только перед следующим циклом капекса.</li>
</ol>
<p>Поэтому SLO выбирается <strong>до</strong> дизайна, а не после. И выбирается <strong>с участием бизнеса</strong> — потому что цифра в нём в итоге привязана к деньгам, а не к самочувствию инженеров.</p>
<h2 id="sla-что-уходит-наружу">SLA: что уходит наружу</h2>
<p>Третий и последний термин «троицы» — <strong>SLA (Service Level Agreement)</strong>. Это контракт с пользователем (или клиентом, партнёром, регулятором), оформленный обычно юридически, с финансовыми санкциями за нарушение.</p>
<p>Принципиальное отличие от SLO:</p>
<table>
  <thead>
      <tr>
          <th></th>
          <th>SLO</th>
          <th>SLA</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Кому обещаем</td>
          <td>Самим себе (внутри команды/компании)</td>
          <td>Внешнему пользователю или клиенту</td>
      </tr>
      <tr>
          <td>Последствия нарушения</td>
          <td>Перераспределение бюджета на reliability, freeze</td>
          <td>Финансовые санкции, отток, репутация</td>
      </tr>
      <tr>
          <td>Гранулярность</td>
          <td>Может быть сколько угодно (по шагу, по сегменту)</td>
          <td>Обычно одно-два простых числа</td>
      </tr>
      <tr>
          <td>Частота пересмотра</td>
          <td>Раз в квартал</td>
          <td>Раз в год или реже</td>
      </tr>
  </tbody>
</table>
<h3 id="главное-правило-sla--slo--запас">Главное правило: SLA ≤ SLO − запас</h3>
<p>Самая частая ошибка — поставить SLA равным SLO. Например, инженеры обещают себе 99.99%, и юристы пишут пользователю «гарантируем 99.99%». В этом случае любое попадание в нижнюю границу SLO — уже автоматически нарушение SLA.</p>
<p>Правильно: между SLO и SLA должен быть <strong>запас</strong>, обычно один-два разряда <code>9</code>.</p>
<ul>
<li>SLO 99.99% → SLA 99.9% или 99.95%.</li>
<li>SLO 99.9% → SLA 99.5%.</li>
</ul>
<p>Запас не стоит ничего — это просто разница между «что мы хотим внутри» и «что мы готовы юридически защищать снаружи».</p>
<h3 id="и-ещё-одно-важное">И ещё одно важное</h3>
<p>SLA пишется не на ту же метрику, что SLO. SLA обычно — это <strong>availability в чистом виде</strong> (грубое «отвечает / не отвечает»). SLO — набор тонких индикаторов (latency, freshness, correctness). Ты внутри живёшь на сложной картине из 4–8 SLI, наружу выдаёшь одну простую цифру с запасом.</p>
<h2 id="golden-signals-red-use--какую-призму-брать-и-когда">Golden Signals, RED, USE — какую призму брать и когда</h2>
<p>Кейс выше показал три разные системы под три SLO. Прежде чем переходить к разговору про error budget как арбитр в спорах, важно понять — а каким набором метрик мы вообще смотрим на эти системы. В SRE-сообществе живут три популярных набора-призмы для метрик:</p>
<ul>
<li><strong>Golden Signals</strong> — <code>Latency, Traffic, Errors, Saturation</code>. Универсальный набор для пользовательских сервисов. Введён Rob Ewaschuk и закреплён в Google SRE Book (глава «Monitoring Distributed Systems», O&rsquo;Reilly, 2016).</li>
<li><strong>RED</strong> — <code>Rate, Errors, Duration</code>. Подмножество Golden Signals, ориентированное на запрос-ответные сервисы. Введён Tom Wilkie (Weaveworks, ныне Grafana Labs) в докладе «The RED Method» (2017).</li>
<li><strong>USE</strong> — <code>Utilization, Saturation, Errors</code>. Для ресурсов: CPU, диск, память, сеть. Введён Brendan Gregg в «Systems Performance» (2-е изд., 2020) и серии постов на brendangregg.com (2012+).</li>
</ul>
<p>Эти призмы часто валят в одну кучу и спорят, какая «правильная». Спор бессмысленный — они отвечают на <strong>разные вопросы</strong>.</p>
<h3 id="golden-signals--самая-полная-призма-для-сервиса">Golden Signals — самая полная призма для сервиса</h3>
<p>Если ты только начинаешь и не знаешь, что меряет — начни с Golden Signals на каждый твой сервис:</p>
<ul>
<li><strong>Latency.</strong> Сколько времени занял успешный запрос (отдельно — неуспешный, потому что медленный 500 искажает картину).</li>
<li><strong>Traffic.</strong> Сколько запросов обрабатываем (RPS, qps, events/sec).</li>
<li><strong>Errors.</strong> Доля «плохих» — 5xx, таймауты, протокольные ошибки, неуспешные заказы.</li>
<li><strong>Saturation.</strong> Насколько ресурс заполнен — очередь, пул соединений, утилизация worker-ов.</li>
</ul>
<p>В нашем кейсе для search-сервиса Golden Signals разворачиваются так:</p>
<ul>
<li><strong>Latency:</strong> P50/P95/P99 на эндпоинт <code>/search</code>, разбитые по типу запроса (autocomplete vs full search).</li>
<li><strong>Traffic:</strong> RPS на <code>/search</code>, отдельно по регионам.</li>
<li><strong>Errors:</strong> доля 5xx + таймаутов к ES + ошибок ranking-сервиса.</li>
<li><strong>Saturation:</strong> размер очереди в Kafka-consumer индексирования, пул коннектов в ES, hit rate Redis.</li>
</ul>
<p>Эти четыре сразу дают <strong>верхнеуровневую картину здоровья сервиса</strong>. SLI ты выбираешь из них (обычно — Latency и Errors), но мониторить нужно все четыре.</p>
<h3 id="red--тот-же-набор-проще-запомнить">RED — тот же набор, проще запомнить</h3>
<p>RED (<code>Rate, Errors, Duration</code>) — это Golden Signals минус <code>Saturation</code>. Удобный мнемоник, особенно для request/response-сервисов: каждый эндпоинт обязательно имеет три метрики и хотя бы один дашборд по ним.</p>
<p>Когда брать RED вместо Golden Signals: если ты делаешь дашборд per-endpoint в большом сервисе и не хочешь ставить четыре графика на каждый эндпоинт. Saturation — ресурсная метрика, и она часто живёт отдельно (на дашборде ресурсов или инфраструктуры), а не на дашборде эндпоинтов.</p>
<h3 id="use--призма-для-ресурсов-не-для-сервисов">USE — призма для ресурсов, не для сервисов</h3>
<p>USE (<code>Utilization, Saturation, Errors</code>) — про <strong>ресурс</strong>, не про сервис. Когда мерить:</p>
<ul>
<li><strong>CPU</strong> — utilization = % busy, saturation = run queue, errors = throttling.</li>
<li><strong>Диск</strong> — utilization = busy time, saturation = await, errors = bad sectors / IO errors.</li>
<li><strong>Сеть</strong> — utilization = bandwidth %, saturation = drops, errors = retransmits.</li>
<li><strong>Пул соединений</strong> — utilization = used/max, saturation = очередь ожидания, errors = таймауты.</li>
</ul>
<p>USE — для <strong>диагностики</strong>, не для SLO. Никогда не делай SLO на CPU utilization напрямую — это служебный сигнал. Но USE-метрики бесценны, когда burn-rate-алерт сработал и нужно быстро понять, <strong>где</strong> в стеке давит.</p>
<h3 id="когда-какую-призму-брать--простое-правило">Когда какую призму брать — простое правило</h3>
<table>
  <thead>
      <tr>
          <th>Ситуация</th>
          <th>Призма</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Дашборд верхнего уровня по сервису</td>
          <td>Golden Signals</td>
      </tr>
      <tr>
          <td>Дашборд per-endpoint в большом сервисе</td>
          <td>RED</td>
      </tr>
      <tr>
          <td>Дашборд ресурса (CPU, диск, БД-пул)</td>
          <td>USE</td>
      </tr>
      <tr>
          <td>Выбор кандидатов в SLI</td>
          <td>Golden Signals → Latency и Errors</td>
      </tr>
      <tr>
          <td>Диагностика после burn-rate-алерта</td>
          <td>USE — где жмёт по ресурсам</td>
      </tr>
  </tbody>
</table>
<h3 id="главное-смещение">Главное смещение</h3>
<p>Призмы не противоречат — они <strong>дополняют</strong>. У зрелой команды есть все три уровня дашбордов:</p>
<ul>
<li><strong>Верхний</strong> — Golden Signals + дашборд SLI/SLO с burn-rate. Заходишь и сразу видишь, всё ли в порядке с пользовательским опытом.</li>
<li><strong>Средний</strong> — RED по эндпоинтам. Заходишь, когда верхний показывает деградацию, и видишь, какой эндпоинт вносит вклад.</li>
<li><strong>Нижний</strong> — USE по ресурсам. Заходишь, когда RED показывает, какой эндпоинт болит, и нужно понять, в каком ресурсе упёрлись.</li>
</ul>
<h2 id="error-budget-как-арбитр-в-спорах-фича-vs-рефакторинг">Error budget как арбитр в спорах «фича vs рефакторинг»</h2>
<p>Самый недооценённый эффект от грамотного SLO — это не алерты и не отчёты. Это то, что бюджет ошибок становится <strong>валютой в архитектурных спорах</strong>, и решения принимаются на цифрах, а не на ощущениях.</p>
<h3 id="классический-спор-без-бюджета">Классический спор без бюджета</h3>
<p>Сценарий, знакомый каждому, кто работал в продуктовой команде дольше года:</p>
<blockquote><p><strong>Продакт:</strong> «Нам нужно срочно выкатить персонализированную выдачу до Чёрной пятницы».<br>
<strong>SRE:</strong> «Мы только что прошли через два инцидента из-за деплоя. Я хочу заморозить деплои на неделю и провести post-mortem».<br>
<strong>Продакт:</strong> «Каждая неделя задержки — это $500k недополученной выручки».<br>
<strong>SRE:</strong> «Каждый инцидент — это репутация».</p>
</blockquote><p>Без бюджета этот спор решается <strong>властью</strong>. Кто громче, выше по иерархии или ближе к CEO — тот побеждает. Решения принимаются эмоционально, обе стороны выходят с ощущением, что их аргументы недослушаны.</p>
<h3 id="тот-же-спор-с-бюджетом">Тот же спор с бюджетом</h3>
<blockquote><p><strong>Продакт:</strong> «Хочу выкатить персонализацию до BF».<br>
<strong>SRE:</strong> «Бюджет на этот месяц — 26M запросов. За последние две недели мы сожгли 22M на двух инцидентах. У нас осталось 4M на оставшиеся 16 дней. Вот burn-rate-график за неделю».<br>
<strong>Продакт:</strong> «Сколько бюджета съедает выкатка персонализации?»<br>
<strong>SRE:</strong> «По прошлым выкаткам сопоставимого риска — медианно 3–4M запросов на постепенный rollout. То есть канарейка съест от 75% до 100% оставшегося бюджета. Если что-то пойдёт не так — превышаем SLO до конца окна».<br>
<strong>Продакт:</strong> «Сколько ждать, пока бюджет восстановится?»<br>
<strong>SRE:</strong> «Окно rolling, считается на последних 30 днях — каждые сутки самые старые сутки выпадают, новые входят. Самые тяжёлые инциденты были 28 и 25 дней назад: через 2–5 дней они выпадут из окна, и мы откатимся к ~10M свободного бюджета без всяких новых усилий».<br>
<strong>Продакт:</strong> «До BF — 24 дня. Подождём 5 дней, потом выкатываем канарейку — рискуем уже на восстановленном бюджете, а не на остатках от инцидентов».</p>
</blockquote><p>Спор кончился за 5 минут, без эмоций, на цифрах. Это и есть «бюджет как валюта»: он переводит инженерное «надо подождать» и продуктовое «надо быстрее» в <strong>единицу измерения, значимую обеим сторонам</strong>.</p>
<p>Это сводится к трём операционным следствиям, которые я уже разбирал в Шаге 4 как «на что тратится бюджет»: решение «деплоить vs морозить», переключение на reliability при систематическом сгорании, осознанная трата бюджета на учения и эксперименты. Здесь добавляется только одно: каждое из этих следствий теперь становится <strong>цифровым аргументом в диалоге</strong>, а не «инженерным интуитивным решением».</p>
<h3 id="что-разрушает-бюджет-как-арбитр">Что разрушает «бюджет как арбитр»</h3>
<ul>
<li><strong>Несогласованный SLO.</strong> Если бюджет в глазах продакта — «инженерная штука», он не примет его как аргумент. SLO нужно <strong>согласовывать</strong> с продуктом, а не объявлять.</li>
<li><strong>SLO без явного оперативного следствия.</strong> Если «бюджет сгорел» не запускает freeze автоматически, это просто график на дашборде. Должна быть <strong>записанная политика</strong>, что делать.</li>
<li><strong>Слишком жёсткое SLO.</strong> Если SLO нереалистичный («99.99% на сервисе, который объективно может только 99.9%»), бюджет всё время в минусе, и команда привыкает его игнорировать. Лучше реалистичный SLO с дисциплиной, чем красивая цифра, в которую никто не верит.</li>
</ul>
<p>Бюджет — это не магический инструмент, а <strong>дисциплина</strong>. Он работает, если команда договорилась его соблюдать. Не работает — если нет.</p>
<h2 id="типичные-ошибки-выбора-slislo-и-чек-лист">Типичные ошибки выбора SLI/SLO и чек-лист</h2>
<p>Соберу в один блок самые частые ошибки, которые ломают SLO-практику. Часть из них уже разобрана в основных разделах — в этом блоке они сведены в одну строку для самопроверки. Развёрнутые контрпримеры — в соответствующих главах выше.</p>
<h3 id="ошибка-1-sli--всё-что-не-5xx">Ошибка 1. SLI = «всё, что не 5xx»</h3>
<p><strong>Правильно:</strong> SLI — это <code>success AND fast</code>, и оба критерия записаны явно. Полный разбор — в Шаге 3 (про «хорошее событие»).</p>
<h3 id="ошибка-2-slo-по-системе-вместо-slo-по-шагу-пути">Ошибка 2. SLO «по системе» вместо SLO «по шагу пути»</h3>
<p><strong>Правильно:</strong> SLO живёт на каждом шаге критичного пути, а не на сервисе в целом. Развёрнуто — в Шаге 1 (ловушка «среднего по системе»).</p>
<h3 id="ошибка-3-slo-без-error-budget-policy">Ошибка 3. SLO без error budget policy</h3>
<p>SLO написано, бюджет считается, но что делать, когда бюджет сгорел — не записано. В итоге команда живёт в режиме «дашборд красный, ну ладно, продолжаем выкатку».</p>
<p><strong>Правильно:</strong> записанная политика: при превышении burn-rate <code>X×</code> за окно <code>Y</code> минут — freeze деплоев до конца окна / привлечение reliability-команды / эскалация. Без процедуры SLO — это украшение. Развёрнуто — в разделе «Что разрушает „бюджет как арбитр“».</p>
<h3 id="ошибка-4-slo--sla">Ошибка 4. SLO = SLA</h3>
<p><strong>Правильно:</strong> между SLO и SLA — запас один-два разряда <code>9</code>. Подробнее — в разделе «SLA: что уходит наружу».</p>
<h3 id="ошибка-5-среднее-вместо-перцентилей">Ошибка 5. Среднее вместо перцентилей</h3>
<p><strong>Правильно:</strong> SLI на latency — это перцентиль (P95/P99), не среднее. Развёрнуто — в Шаге 3, блок «Что мы НЕ берём как SLI».</p>
<h3 id="ошибка-6-sli-на-cpumemory-utilization">Ошибка 6. SLI на CPU/Memory utilization</h3>
<p><strong>Правильно:</strong> SLI — на пользовательских следствиях (latency, errors). Утилизация — служебная метрика для USE-дашборда. Развёрнуто — в Шаге 3, блок «Что мы НЕ берём как SLI».</p>
<h3 id="ошибка-7-слишком-много-sli">Ошибка 7. Слишком много SLI</h3>
<p>«У нас 50 SLI на сервис» — означает, что SLI никто не читает, и алерты по ним — шум. SLI должен фокусировать внимание, а не размывать его.</p>
<p>Маленькое терминологическое уточнение, без которого пункт читается двусмысленно: <strong>«сервис» здесь — пользовательский сервис в смысле CUJ</strong>, а не каждый микросервис в твоей архитектуре. На один CUJ (поиск каталога) — 4–8 SLI; на ranking-микросервис, который обслуживает этот же CUJ, не нужно отдельно вешать ещё 4–8. Иначе «50 SLI» получаются арифметически — суммой по микросервисам, — и читать их никто не будет.</p>
<p><strong>Правильно:</strong> 4–8 SLI на пользовательский сервис (CUJ), привязанных к ключевым шагам пути. Если хочется больше — это, скорее всего, сигнал, что внутри одного «сервиса» спрятаны два CUJ, и его пора разделить. Развёрнуто — в Шаге 3, блок «Конкретные SLI для нашего кейса».</p>
<h3 id="ошибка-8-slo-выбран-копированием">Ошибка 8. SLO выбран копированием</h3>
<p>«У Google 99.99%, у нас тоже будет». Без разговора с бизнесом, без расчёта стоимости, без понимания, тянет ли архитектура.</p>
<p><strong>Правильно:</strong> SLO выбирается из двух чисел — что <strong>окупается</strong> (бизнес) и что <strong>достижимо</strong> (архитектура). Между ними может быть зазор — он отражает либо недоинвест в reliability, либо переинвест в обещания.</p>
<h3 id="ошибка-9-slo-не-пересматривается">Ошибка 9. SLO не пересматривается</h3>
<p>Поставили SLO 99.9% год назад, написали в Confluence, забыли. Бизнес-контекст изменился, нагрузка выросла в 10 раз, продукт перешёл в зрелую фазу — SLO остался прежним.</p>
<p><strong>Правильно:</strong> SLO пересматривается раз в квартал минимум, в idle-режиме — раз в полгода. Каждый пересмотр — короткий ритуал «изменилось ли что-то в бизнесе или в системе, что меняет нужное число».</p>
<h3 id="ошибка-10-slo-выбран-без-учёта-зависимостей">Ошибка 10. SLO выбран без учёта зависимостей</h3>
<p>Сервис обещает 99.99%, но критически зависит от внешнего сервиса с 99.5%. Математика: твой SLO не может быть выше произведения SLO твоих критичных зависимостей.</p>
<p><strong>Правильно:</strong> при выборе SLO учитывай <strong>dependency budget</strong>. Если у тебя 3 последовательные критичные зависимости с 99.9% каждая, твой достижимый максимум — <code>~99.7%</code>. Для опциональных или параллельных зависимостей формула мягче — но любую цепочку нужно явно проговорить.</p>
<h3 id="чек-лист-10-вопросов-до-утверждения-slo">Чек-лист: 10 вопросов до утверждения SLO</h3>
<p>Если ответ «нет» хотя бы на один — SLO ещё не готов.</p>
<ul>
<li><input disabled="" type="checkbox"> Привязан ли SLO к конкретному шагу критичного пути, а не к сервису целиком?</li>
<li><input disabled="" type="checkbox"> Прописаны ли числитель, знаменатель и окно агрегации?</li>
<li><input disabled="" type="checkbox"> Пройдён ли тест «5xx за 5 секунд = плохое событие»?</li>
<li><input disabled="" type="checkbox"> Используется ли перцентиль, а не среднее?</li>
<li><input disabled="" type="checkbox"> Есть ли error budget в абсолютных значениях для текущего объёма трафика?</li>
<li><input disabled="" type="checkbox"> Есть ли записанная error budget policy (что делать при сгорании)?</li>
<li><input disabled="" type="checkbox"> Есть ли запас между SLO и SLA (если SLA вообще обещаем)?</li>
<li><input disabled="" type="checkbox"> Согласованы ли числа с бизнесом (а не «команда придумала»)?</li>
<li><input disabled="" type="checkbox"> Учтены ли SLO критичных зависимостей в верхней границе нашего?</li>
<li><input disabled="" type="checkbox"> Назначена ли дата следующего пересмотра?</li>
</ul>
<h2 id="заключение-slo--это-мост-между-системой-и-деньгами">Заключение: SLO — это мост между системой и деньгами</h2>
<p>Я начинал статью с тезиса, что архитектура без SLO — это эстетика, не инженерия. К концу хочется его уточнить.</p>
<p>SLO — не просто <strong>constraint</strong> на архитектуру, хотя я почти всю статью акцентировал именно это. SLO — это <strong>общий язык</strong> между четырьмя ролями, которые иначе говорят на разных:</p>
<ul>
<li><strong>Продакт / аналитик</strong> говорит: конверсия, retention, GMV, NPS.</li>
<li><strong>Бэкенд</strong> говорит: P99, шарды, hit rate, репликация.</li>
<li><strong>SRE</strong> говорит: error budget, burn rate, MTTR, blast radius.</li>
<li><strong>Бизнес</strong> говорит: деньги, репутация, регуляторика.</li>
</ul>
<p>SLO — это формат, в котором все четверо могут договориться. «Поднять availability с 99.9% до 99.99% стоит 4× инфраструктуры и сэкономит N часов даунтайма в год, что на нашем GMV $X — это <code>Y</code> денег. Делаем или нет?». Этот вопрос имеет ответ, к которому пришли все четверо. Без SLO такого вопроса просто не существует — есть только предчувствия.</p>
<h3 id="что-сделать-в-понедельник">Что сделать в понедельник</h3>
<ol>
<li><strong>Возьми один пользовательский путь и разложи его на шаги.</strong> Не сервис целиком — один сценарий, шесть-семь шагов, как в нашем кейсе. На каждый шаг — кандидаты в SLI. Это упражнение делается за два часа и показывает, где ты измеряешь не то.</li>
<li><strong>Сравни свои текущие SLO с реальными зависимостями.</strong> Если твой SLO выше произведения SLO критичных зависимостей — ты обещаешь больше, чем можешь дать. Цифру лучше пересмотреть до того, как её пересмотрит пользователь.</li>
<li><strong>Напиши error budget policy на одну страницу.</strong> Что происходит при превышении burn-rate <code>X×</code> за <code>Y</code> минут? Кто принимает решение freeze? Без этого документа SLO остаётся графиком на дашборде, а не дисциплиной.</li>
</ol>
<p>Спасибо, что дочитал до конца. Эта статья — переработанная версия плана несостоявшегося доклада для <a href="https://t.me/system_design_world" rel="noopener noreferrer" target="_blank">System Design World</a>
. Если у тебя есть свой опыт работы с SLO в системе высокой нагрузки — особенно интересны истории, как менялся выбор SLO с ростом продукта или после крупного инцидента — пиши в комменты или в мой Telegram-канал «<a href="https://t.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">Мишка на сервере</a>
».</p>
<p>Чертёж — это половина дела. Как именно выглядит тот самый диалог с бизнесом, без которого SLO остаётся картинкой на дашборде, я разбираю в продолжении: <a href="/posts/reliability-is-a-conversation/">«Надёжность строится в диалоге с бизнесом»</a>
.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></content:encoded>
    </item><item>
      <title>Содержимое моей персональной базы знаний</title>
      <link>https://jtprog.ru/posts/inside-my-obsidian/</link>
      <pubDate>Fri, 08 May 2026 14:52:21 +0300</pubDate>
      <dc:creator>jtprogru</dc:creator>
      <guid isPermaLink="true">https://jtprog.ru/posts/inside-my-obsidian/</guid>
      <category>Obsidian</category>
      <category>Знания</category>
      <category>PKB</category>
      <category>PARA</category>
      <category>Personal Knowledge Management</category>
      <category>Note-Taking</category>
      <category>Дневник</category>
      <category>Second Brain</category>
      <category domain="category">Opinions</category>
      <enclosure url="https://jtprog.ru/opinions.png" type="image/jpeg" length="0" />
      <media:thumbnail url="https://jtprog.ru/opinions.png" /><description><![CDATA[<div><p>Привет, <code>%username%</code>! Какое-то время назад мне прилетал запрос (в том числе и в чате): <em>«Можно ли глянуть на вашу базу знаний? Интересны какие там темы и что вы считаете важным, что это записываете?»</em>. Попробую ответить максимально развернуто и, возможно (но это не точно), что-то покажу.</p>
<blockquote><p><strong>Кратко:</strong></p>
<ul>
<li>База знаний <strong>персональная</strong> — полностью не покажу, но опишу многое.</li>
<li>Инструмент — Obsidian с плагинами Dataview, Templater, Omnisearch, Git.</li>
<li>Структура: упрощённая PARA — Проекты / Сферы / Ресурсы / Архив / Дневник.</li>
<li>Темы: DevSecOps/SRE, Computer Science, Психология, PKB, Личное, Дневник и ещё куча всего.</li>
<li>Главное правило: сомневаешься — записывай. Удалять не нужно — есть архив.</li>
<li>Самое важное: <strong>важнее писать заметки, чем не писать их вовсе</strong>.</li>
</ul>
</blockquote><h2 id="можно-ли-глянуть">Можно ли глянуть</h2>
<p>Начну с того, что <em>персональная база знаний</em> — она в первую очередь <strong>персональная</strong>, а потом уже база знаний. Это значит, что показывать я ее точно не планирую, как минимум пока я живой. По крайней мере в полном объеме я точно не смогу показать каждую заметку, однако какие-то ее части в том или ином виде я и так показываю. Например, посты для блогов рождаются из заметок в моей базе знаний.</p>
<p>Я спокойно могу <strong>описать</strong>: как именно она устроена, какие темы я фиксирую, а также как я решаю &ldquo;записать или не записать&rdquo; (спойлер: <strong>записать</strong>). Именно об этом и будет ниже — может, что-то из этого окажется полезным и тебе.</p>
<blockquote><p><strong>Дисклеймер</strong>: всё описанное — это мой личный опыт и мои решения. Не универсальный рецепт. Бери то, что резонирует, и адаптируй под себя.</p>
</blockquote><h3 id="что-именно-публично">Что именно публично</h3>
<p>Хотя саму базу я не открываю, часть артефактов из неё так или иначе попадает в публичное пространство:</p>
<ul>
<li><strong>Посты канала</strong> — практически все посты «Мишки на сервере» рождаются из черновиков в базе.</li>
<li><strong>Слайды и выступления</strong> — например, доклад для студентов РТУ МИРЭА о PKB (<a href="https://jtprogru.github.io/pkbd/" rel="noopener noreferrer" target="_blank">слайды</a>
) целиком сделан из заметок.</li>
<li><strong><a href="https://jtprog.ru/posts/pkb-check-list/">Чек-лист для организации персональной базы знаний</a>
</strong> — публичный артефакт в блоге.</li>
<li><strong>Шаблоны</strong> — часть шаблонов я периодически описываю в постах.</li>
</ul>
<p>Что никогда не попадает публично: рабочие детали с конкретными системами и командами, личные записи про людей, дневниковые записи, заметки про инциденты.</p>
<hr>
<h2 id="начну-со-структуры">Начну со структуры</h2>
<p>Довольно часто те, кто начинает заниматься заметковедением, начинают ломаться именно тут — попытка полностью продумать идеальную структуру базы знаний ломается ещё до первой заметки. Я и сам страдал этим — у меня сейчас примерно третья или четвёртая версия структуры.</p>
<p>Если кратко о том, как она эволюционировала: сначала была плоская куча файлов по папкам «Работа», «Личное», «Разное» — быстро стало непонятно, куда класть новое. Потом попытался следовать PARA (Projects-Areas-Resources-Archives) строго — оказалось слишком жёстко и я тратил больше времени на классификацию, чем на сами заметки. Нынешняя структура — это упрощённая PARA под себя.</p>
<p>Менять структуру — это нормально и правильно. Твоя персональная база знаний живёт и развивается вместе с тобой. Ты изучаешь что-то или пробуешь новое, находишь этому применение — и вот уже стоит задача реорганизовать размещение заметок.</p>
<p>Вернусь к себе. На текущий момент, структура директорий, которая используется у меня — в первую очередь удовлетворяет именно меня. Вот так у меня выглядит верхний уровень:</p>
<ul>
<li><code>00. Входящие</code> — просто мой инбокс заметок — сюда попадают абсолютно все заметки, которые я фиксирую.</li>
<li><code>01. Проекты</code> — преимущественно личные проекты, но иногда и рабочие там тоже оказываются.</li>
<li><code>02. Сферы</code> — содержит различные сферы моей жизни.</li>
<li><code>03. Ресурсы</code> — сюда я складываю информацию о книгах, статья и видео, а также навигационные карты.</li>
<li><code>04. Архив</code> — название говорит само за себя, я удаляю заметки крайне редко и чаще всего переношу их в архив.</li>
<li><code>05. Дневник</code> — еще одно очевидное название, тут лежат ежедневные заметки.</li>
<li><code>_Система</code> — тут лежат преимущественно служебные штуки, такие как шаблоны, картинки, холсты и прочие непотребства, которые я храню отдельно от заметок.</li>
<li><code>README.md</code> — моя входная точка в базу знаний (дашборд), а имя выбрано потому что бэкапы идут в Git.</li>
<li><code>AGENTS.md</code> — универсальные инструкции для всяких агентов, которые я иногда запускаю (преимущественно Claude Code).</li>
</ul>
<p>Всё это живёт в Obsidian — на данный момент у меня там порядка ≈5400 заметок. Из ключевых плагинов использую: <strong>Dataview</strong> (динамические запросы по базе), <strong>Templater</strong> (создание заметок из шаблонов), <strong>Omnisearch</strong> (полнотекстовый поиск) и <strong>Git</strong> (автоматические бэкапы).</p>
<h3 id="ключевые-понятия-чтобы-не-было-путаницы">Ключевые понятия (чтобы не было путаницы)</h3>
<p>Я использую несколько терминов, которые у разных людей означают разное. Вот как они работают у меня:</p>
<ul>
<li><strong>Входящие</strong> — «мусоропровод», куда летит всё подряд. Необработанное, без структуры. Задача — не потерять мысль, обрабатывать сразу не нужно.</li>
<li><strong>Черновик</strong> — заметка в процессе написания. Живёт уже в тематической папке, не во входящих. Отличие: уже есть намерение сделать из неё что-то конкретное.</li>
<li><strong>Дневник</strong> — ежедневные заметки. Отдельная категория, не входящие и не ресурсы. Не предназначен для переработки в посты.</li>
<li><strong>Карта / Map-of-Content (MOC)</strong> — навигационная заметка, которая собирает ссылки по теме. Не содержит знаний сама по себе — только указатели. Думай об этом как об оглавлении книги.</li>
<li><strong>Полноценная заметка</strong> — заметка с заголовком, 1-3 ключевыми тезисами, ссылками на связанные заметки и заполненным frontmatter. Не обязательно длинная — часто это 3-5 предложений.</li>
</ul>
<h3 id="обработка-входящих">Обработка входящих</h3>
<p>После обработки заметки из входящих, она отправляется в одну из категорий:</p>
<ul>
<li>Становится полноценной заметкой.</li>
<li>Становится картой.</li>
</ul>
<blockquote><p><strong>Замечание</strong>: Заметки по статьям, видео и книгам сразу складываются в свои директории.</p>
</blockquote><h3 id="жизненный-цикл-заметки">Жизненный цикл заметки</h3>
<p>Вот как заметка проходит путь от мысли до архива:</p>
<ol>
<li><strong>Захват</strong> → любая мысль/идея/факт фиксируется во <code>00. Входящие</code> или в дневнике. Формат не важен — главное не потерять.</li>
<li><strong>Обработка</strong> → раз в несколько дней разбираю инбокс: определяю тип заметки, добавляю frontmatter, перемещаю в нужную папку.</li>
<li><strong>Размещение</strong> → заметка отправляется в <code>01-04</code>, получает структуру по шаблону.</li>
<li><strong>Связывание</strong> → расставляю ссылки на связанные заметки, обновляю MOC если нужно.</li>
<li><strong>Использование</strong> → заметка живёт, дополняется при необходимости.</li>
<li><strong>Архив</strong> → если тема устарела — переношу в <code>04. Архив</code>, не удаляю.</li>
</ol>
<p>Инбокс обрабатываю без жёсткого расписания — по ощущению «накопилось». Обычно это 15-30 минут, 2-3 раза в неделю.</p>
<h3 id="правила-именования">Правила именования</h3>
<p>Заметки называю по принципу «чтобы было понятно без открытия»:</p>
<ul>
<li>Язык названия = язык заметки (русский по умолчанию, английский для технических терминов).</li>
<li>Никаких дат в названии, кроме дневниковых заметок (<code>2024-03-15</code>).</li>
<li>Существительные или глагольные фразы: «Ведение дневника лучше чем ведение todo-листа», «Kubernetes networking», «Почему SRE ≠ DevOps».</li>
<li>Никаких префиксов вроде <code>MOC-</code>, <code>BOOK-</code>, <code>IDEA-</code> — для этого есть теги и frontmatter.</li>
</ul>
<h3 id="как-я-нахожу-нужное">Как я нахожу нужное</h3>
<p>Страх «положу и забуду» — один из самых частых аргументов против ведения базы знаний. Но у меня он не работает, и вот почему.</p>
<p>Во-первых, поиск. Штатный поиск Obsidian слабоват, но я использую плагин Omnisearch — он быстрый и ищет по всему тексту, достаточно вспомнить любое слово из заметки. Во-вторых, связи между заметками: когда пишешь новую заметку и ставишь ссылки на старые, граф знаний сам напоминает, что у тебя уже есть по теме. В-третьих, Dataview-запросы в MOC-картах автоматически собирают заметки — не надо помнить, где что лежит.</p>
<p>На практике я редко «ищу» заметку целенаправленно. Чаще всего нужное всплывает само при написании новой заметки или при просмотре дневника.</p>
<p>Конкретные примеры навигации:</p>
<ul>
<li><strong>Идеи для постов</strong> → открываю MOC «Медийность» с Dataview-запросом, который тянет все заметки с тегом <code>#content</code>. Весь бэклог в одном месте.</li>
<li><strong>Инциденты</strong> → у каждого инцидента шаблон с тегом <code>#sre</code>. Dataview в MOC по SRE собирает их все.</li>
<li><strong>Книга, которую читал год назад</strong> → ищу по названию через Omnisearch или иду в <code>03. Ресурсы / Книги</code>.</li>
</ul>
<h3 id="шаблоны">Шаблоны</h3>
<p>Шаблонов у меня довольно много, и они со временем меняются. Вот те, что использую регулярно:</p>
<ul>
<li><code>Ежегодная заметка</code> — обзор года, использую в конце года, чтобы просто порефлексировать и подвести личные итоги.</li>
<li><code>Ежедневная заметка</code> — одна из основных заметок, используется для ведения дневника.</li>
<li><code>Конспект по лекции</code> — я студент и у меня есть отдельный шаблон для лекций, которые я посещаю.</li>
<li><code>Обзор конференции</code> — обзорная заметка про конкретную конференцию, где собираются все посещенные доклады и новые люди.</li>
<li><code>Шаблон тезисов по докладу</code> — доклады, которые я посетил на конференции и которые добавляются в обзорную заметку.</li>
<li><code>Созвон или встреча</code> — говорящее название, использую в том числе и для работы.</li>
<li><code>Черновик поста</code> — черновик поста (универсальный) и этот пост также был создан из этого шаблона.</li>
<li><code>Шаблон идея</code> — самый важный шаблон, который используется для всех заметок, которые я пишу сам сохраняю во входящих.</li>
<li><code>Шаблон инцидента</code> — для инцидентов, в которых я участвую лично у меня есть отдельный шаблон, информацию из которого я потом выношу в Postmortem.</li>
<li><code>Шаблон карты</code> — навигационные заметки или Map-of-Content.</li>
<li><code>Шаблон тезисов по видео</code>, <code>Шаблон тезисов по книге</code>, <code>Шаблон тезисов по статье</code> — для видео, книги или статьи используется свой шаблон, который в бОльшей степени является навигационной заметкой.</li>
<li><code>Шаблон человека</code> — заметки о людях.</li>
</ul>
<hr>
<h2 id="теги-и-свойства">Теги и свойства</h2>
<p>Теги у меня — это дополнительный слой навигации поверх папочной структуры. Живут в frontmatter, никаких инлайн-тегов.</p>
<p>Основные теги, которые реально использую:</p>
<table>
  <thead>
      <tr>
          <th>Тег</th>
          <th>Когда ставлю</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>#content</code> / <code>#telegram</code></td>
          <td>Черновик или идея для поста/канала</td>
      </tr>
      <tr>
          <td><code>#sre</code> / <code>#devops</code> / <code>#kubernetes</code></td>
          <td>Технические заметки по профилю</td>
      </tr>
      <tr>
          <td><code>#concept</code></td>
          <td>Термин, модель, фреймворк</td>
      </tr>
      <tr>
          <td><code>#thought</code></td>
          <td>Личная атомарная мысль</td>
      </tr>
      <tr>
          <td><code>#book</code> / <code>#article</code> / <code>#video</code></td>
          <td>Тип источника</td>
      </tr>
      <tr>
          <td><code>#inbox/review</code></td>
          <td>Требует обработки — снимаю тег после разбора</td>
      </tr>
      <tr>
          <td><code>#journal/daily</code></td>
          <td>Ежедневная запись</td>
      </tr>
  </tbody>
</table>
<p>В frontmatter также регулярно использую:</p>
<ul>
<li><code>up</code> / <code>down</code> — для навигации вверх/вниз по иерархии тем</li>
<li><code>status</code> — <code>Todo</code> / <code>WIP</code> / <code>Done</code> для проектов и черновиков</li>
<li><code>confidence</code> — <code>low</code> / <code>medium</code> / <code>high</code> для концептов и тезисов</li>
<li><code>sources</code> — список источников, из которых пришла информация</li>
</ul>
<hr>
<h2 id="темы-и-тематики">Темы и тематики</h2>
<p>Опишу крупными мазками — когортами тем — что у меня лежит в базе.</p>
<h3 id="преимущественно-рабочее">Преимущественно рабочее</h3>
<ul>
<li>Профильные темы — Dev(Sec)Ops/SRE, Кибербез/Защита информации, Процессы Incident&amp;Problem Management, (S)SDLC, etc&hellip;</li>
<li>Углубление в темы или Deep Dive — Infrastructure as/from Code, K8s, CICD, Configuration Management, etc&hellip;</li>
<li>Computer Science — Программирование, Основы CS, Golang/Python, Алгоритмы, Структуры данных, Парадигмы, etc&hellip;</li>
<li>Методологии — DevOps, SRE, Agile, Scrum, Kanban, ITSM, ITIL, TBM, etc&hellip;</li>
<li>Рабочее — Компании, Команды, Проекты, Встречи, Онбординги, etc&hellip;</li>
<li>Менеджмент — Управление людьми/командами/компаниями, Тимлидство и Техлидство.</li>
<li>Блог — Темы постов и готовые посты для канала и блога.</li>
</ul>
<p>Чтобы дать ощущение масштаба — вот несколько реальных названий заметок из рабочего блока (без содержания):</p>
<ul>
<li>«Чем SRE отличается от DevOps (и почему это важно)»</li>
<li>«SLO, SLA, SLI — разбор на пальцах»</li>
<li>«Почему постмортемы не работают без blame-free культуры»</li>
<li>«Kubernetes: как работает network policy»</li>
<li>«Разница между горизонтальным и вертикальным масштабированием»</li>
</ul>
<h3 id="я-мышление-и-работа-над-собой">Я, Мышление и работа над собой</h3>
<ul>
<li>Личная база знаний — Устройство, Воркфлоу, Второй мозг, etc&hellip;</li>
<li>Саморазвитие и Образование — Курсы, Книги, Хард- и Софт-скиллы, Области роста, Конспекты, etc&hellip;</li>
<li>Психология — Личная, Командная, Коммуникация, etc&hellip;</li>
<li>Мысли и принципы жизни — Разрозненные умозаключения и идеи, Проектирование себя, etc&hellip;</li>
<li>Личное — Семья, Финансы, Здоровье, Люди, etc&hellip;</li>
</ul>
<p>Примеры названий из этого блока:</p>
<ul>
<li>«Ведение дневника лучше чем ведение todo-листа»</li>
<li>«Как я принимаю сложные решения»</li>
<li>«Почему я перестал делать списки задач на день»</li>
<li>«Привязанность vs зависимость в отношениях»</li>
</ul>
<h3 id="разное">Разное</h3>
<p>Тут прям все подряд без списка: Философия, Право, Социология, Публичные выступления, Работа мозга, Драматургия.</p>
<h3 id="дневник">Дневник</h3>
<p>Это прям отдельная тема, которую я считаю крайне важной — дневник и ежедневные заметки, в которых фиксируется абсолютно всё, как в личном блокноте.</p>
<p>Когда-то подсмотрел у Рустама Агамалиева подтверждение того, что у меня чисто интуитивно вызывало комфорт: ведение дневника лучше, чем ведение todo-листа. В свободной форме пишу то, что необходимо сделать или уже сделано. О том, как я веду свой дневник, можно прочитать у меня в отдельном <a href="https://t.me/jtprogru_channel/4265" rel="noopener noreferrer" target="_blank">посте</a>
.</p>
<hr>
<h2 id="записывать-или-не-записывать">Записывать или не записывать</h2>
<p>Буквально, как в монологе Гамлета — &ldquo;Быть или не быть&hellip;&rdquo; очередной заметке. И тут, как и везде — <em>все максимально индивидуально</em>. Именно поэтому я просто попытаюсь описать, чем именно я руководствуюсь, когда создаю очередную заметку.</p>
<h3 id="пригодится-или-справочная-информация">Пригодится или Справочная информация</h3>
<p>Заметка, как какой-то справочный материал, который мне может пригодиться в будущем. Для разных &ldquo;штук&rdquo;, которые бывает дольше гуглить и вспоминать, поэтому проще сохранить в виде заметки:</p>
<ul>
<li>разделение настроек для консольного git-клиента</li>
<li>возвращение режима модема на айфонах</li>
<li>расположение файлов библиотеки приложения Apple Books</li>
</ul>
<p>Проще говоря, это такие заметки, которые я первым делом пойду гуглить — какие-то инструкции, которые мне бывают не часто нужны и которые я не могу должным образом автоматизировать.</p>
<p>В эту же категорию относятся и заметки о каких-то людях. Будь то научный деятель, блогер, философ или &ldquo;крутой чувак&rdquo; с которым я познакомился на конференции.</p>
<h3 id="очередная-гениальная-идея">Очередная гениальная идея</h3>
<p>Не важно, когда она ко мне пришла в голову — в процессе чтения книги/статьи/видоса, либо во время выполнения рабочей задачи или даже во время созвона кем-то. Я запишу эту мысль, чем бы она ни была — связана она с текущим контекстом или деятельностью или нет.</p>
<p>Чаще всего такие мысли фиксируются в ежедневной заметке, а оттуда в ближайшее время извлекаются в отдельную заметку и попадают во входящие на дальнейшую обработку.</p>
<p>Тут могут быть и идеи по личной или рабочей автоматизации, и какие-то околофилософские мыслезлоключения, и идеи доработок чего-либо (особенно рабочее или в пет-проектах). Проще говоря — что-то, что не хочется забыть.</p>
<h3 id="рефлексия">Рефлексия</h3>
<p>Кто-то в рамках ежедневных заметок ведет полноценное планирование и управление проектами, а также через свойства отмечает сколько часов поспал и количество выпитой воды с настроением. Но это точно не я — мне такое пока не очень интересно отслеживать в своей базе знаний.</p>
<p>Я уже не однократно упоминал то, что я веду дневник и веду я его с 2021 года (самая первая дата — 2021-08-05). И вот именно дневник мне начал приносить ощутимую пользу — дневник позволяет ковыряться в собственных мозгах так, словно ты наблюдаешь со стороны.</p>
<p>Была куча разных приложений перепробована, но все они довольно быстро надоедают. А потребность в том, чтобы научиться разбираться в себе — была всегда и будет со мной всегда. Даже в работе с психологами дневник очень хорошо помогает мне.</p>
<h3 id="конспекты-и-обучение">Конспекты и обучение</h3>
<p>Книга, видео, лекция, статья — всё, из чего я что-то усвоил или хочу усвоить, попадает в базу. Не пересказ, а именно то, что меня зацепило: конкретная мысль, тезис, пример, который хочу вернуть потом.</p>
<p>Для каждого типа источника у меня отдельный шаблон (книга / видео / статья / доклад), потому что у них разная структура и разный контекст. Главное правило тут — <strong>не стараться законспектировать всё</strong>. Записываю только то, что хочу переосмыслить или применить.</p>
<h3 id="что-я-намеренно-не-записываю">Что я намеренно НЕ записываю</h3>
<p>Несколько категорий, которые осознанно остаются вне базы знаний:</p>
<ul>
<li><strong>Пароли и секреты</strong> — для этого есть парольный менеджер. В базу знаний принципиально не попадают.</li>
<li><strong>Персональные данные других людей</strong> — контакты храню минимально, без чувствительных деталей. Заметка о человеке — это профессиональный контекст, не личное досье.</li>
<li><strong>Рабочие секреты</strong> — архитектура клиентских систем, внутренние имена, конфигурации. Если что-то рабочее попадает в заметку — сразу обезличивается.</li>
<li><strong>Эмоции в моменте без контекста</strong> — «я злой», «всё плохо» без объяснения почему. Дневник — место для рефлексии, а не для фиксации сырого состояния без смысла.</li>
<li><strong>Задачи и todo-листы</strong> — для задач есть трекер. База знаний — не таск-менеджер.</li>
</ul>
<hr>
<h2 id="приватность-и-безопасность">Приватность и безопасность</h2>
<p>Раз уж я сказал «не покажу пока живой» — логично объяснить, как именно сделано так, чтобы случайно не утекло.</p>
<ul>
<li><strong>Шифрование диска</strong> — база хранится локально, диск зашифрован.</li>
<li><strong>iCloud</strong> — синхронизация между устройствами. Не идеально с точки зрения параноика, но для меня приемлемо.</li>
<li><strong>Git-бэкап</strong> — автоматический бэкап в приватный репозиторий. В <code>.gitignore</code> исключены чувствительные файлы.</li>
<li><strong>Нет публичных ссылок</strong> — никакого Obsidian Publish или аналогов. Если что-то публикую — делаю это руками, отдельным постом.</li>
</ul>
<h2 id="пересмотр-и-актуальность">Пересмотр и актуальность</h2>
<p>База знаний — это не музей. Заметки устаревают, взгляды меняются, какие-то темы перестают быть актуальными.</p>
<p>Как я с этим работаю:</p>
<ul>
<li><strong>Periodic review — по факту, не по расписанию</strong>. Нет жёсткого «раз в неделю смотрю базу». Пересматриваю заметки, когда возвращаюсь к теме по делу.</li>
<li><strong>Статус <code>WIP</code> как маркер</strong>. Если заметка давно в <code>WIP</code> и к ней нет желания возвращаться — это сигнал либо закрыть (→ <code>Done</code>), либо заархивировать.</li>
<li><strong>Дневник как встроенный review</strong>. Ежегодные и ежемесячные заметки — там я естественным образом возвращаюсь к тому, что было важно.</li>
<li><strong>Архив вместо удаления</strong>. Почти никогда не удаляю заметки. Если информация устарела — переношу в <code>04. Архив</code>. Потом можно найти и посмотреть, как думал раньше.</li>
</ul>
<hr>
<h2 id="итоги-и-полезности">Итоги и полезности</h2>
<p>У меня есть в блоге <a href="https://jtprog.ru/posts/pkb-check-list/">Чек-лист для организации персональной базы знаний</a>
 — если хочешь начать, это хорошая отправная точка. Также было небольшое выступление перед студентами РТУ МИРЭА про знакомство с личной базой знаний (<a href="https://jtprogru.github.io/pkbd/" rel="noopener noreferrer" target="_blank">слайды</a>
 есть, а видео нет).</p>
<p>Если вынести одну мысль из всего этого — <strong>важнее писать заметки, чем не писать их вовсе</strong>. Не нужна идеальная структура с первого дня. Не нужно читать все книги по PKB и Zettelkasten. Нужно просто начать фиксировать то, что кажется важным — и постепенно система сама начнёт складываться под тебя.</p>
<p><strong>Кому такой подход подойдёт:</strong></p>
<ul>
<li>Тем, кто работает со знаниями профессионально и хочет не забывать то, что узнаёт.</li>
<li>Тем, кто хочет думать более структурированно и видеть связи между идеями.</li>
<li>Тем, кому важно иметь «свой» инструмент, а не чужую систему.</li>
</ul>
<p><strong>Кому, скорее всего, не подойдёт:</strong></p>
<ul>
<li>Тем, кто хочет быстрый результат — первые месяцы база знаний больше потребляет времени, чем отдаёт.</li>
<li>Тем, кто не готов периодически разбирать инбокс — без обработки это просто свалка.</li>
</ul>
<p><strong>С чего начать новичку:</strong></p>
<ol>
<li>Выбери инструмент (Obsidian, Notion, Logseq — не важно, главное начать).</li>
<li>Заведи один шаблон для «идеи» — просто заголовок + 2-3 строки.</li>
<li>Первую неделю пиши всё подряд без структуры.</li>
<li>На второй неделе посмотри, что накопилось, и попробуй сгруппировать.</li>
<li>Структура появится сама — из того, что реально накапливается.</li>
</ol>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></description>
      <content:encoded><![CDATA[<style>/* Inline-CSS, который тема вкладывает в <description> каждого item'а
   RSS-фида (layouts/index.rss.xml). RSS-ридеры (Feedly, Inoreader,
   NetNewsWire) уважают <style> внутри description с переменной
   степенью энтузиазма — это базовый fallback, достаточный для читаемой
   типографики, не более.

   Цвета продублированы из 00-vars.css (light-палитра) — поправь
   синхронно при изменении --bg / --text / --accent / --border. */

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  line-height: 1.6;
  color: #1c1c1f;
  max-width: 720px;
  margin: 0 auto;
  padding: 1em;
}
h1, h2, h3 { line-height: 1.25; margin-top: 1.4em; }
a { color: #c2410c; }
pre {
  background: #1e1e24;
  color: #e8e6df;
  padding: 1em;
  border-radius: 6px;
  overflow-x: auto;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.9em;
}
code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  background: #f3f1ed;
  padding: 0.1em 0.4em;
  border-radius: 4px;
}
pre code { background: transparent; padding: 0; }
blockquote {
  border-left: 3px solid #c2410c;
  padding-left: 1em;
  color: #5b5b62;
  font-style: italic;
  margin-left: 0;
}
img { max-width: 100%; height: auto; border-radius: 6px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #e5e3dc; padding: 6px 10px; text-align: left; }
</style><div><p>Привет, <code>%username%</code>! Какое-то время назад мне прилетал запрос (в том числе и в чате): <em>«Можно ли глянуть на вашу базу знаний? Интересны какие там темы и что вы считаете важным, что это записываете?»</em>. Попробую ответить максимально развернуто и, возможно (но это не точно), что-то покажу.</p>
<blockquote><p><strong>Кратко:</strong></p>
<ul>
<li>База знаний <strong>персональная</strong> — полностью не покажу, но опишу многое.</li>
<li>Инструмент — Obsidian с плагинами Dataview, Templater, Omnisearch, Git.</li>
<li>Структура: упрощённая PARA — Проекты / Сферы / Ресурсы / Архив / Дневник.</li>
<li>Темы: DevSecOps/SRE, Computer Science, Психология, PKB, Личное, Дневник и ещё куча всего.</li>
<li>Главное правило: сомневаешься — записывай. Удалять не нужно — есть архив.</li>
<li>Самое важное: <strong>важнее писать заметки, чем не писать их вовсе</strong>.</li>
</ul>
</blockquote><h2 id="можно-ли-глянуть">Можно ли глянуть</h2>
<p>Начну с того, что <em>персональная база знаний</em> — она в первую очередь <strong>персональная</strong>, а потом уже база знаний. Это значит, что показывать я ее точно не планирую, как минимум пока я живой. По крайней мере в полном объеме я точно не смогу показать каждую заметку, однако какие-то ее части в том или ином виде я и так показываю. Например, посты для блогов рождаются из заметок в моей базе знаний.</p>
<p>Я спокойно могу <strong>описать</strong>: как именно она устроена, какие темы я фиксирую, а также как я решаю &ldquo;записать или не записать&rdquo; (спойлер: <strong>записать</strong>). Именно об этом и будет ниже — может, что-то из этого окажется полезным и тебе.</p>
<blockquote><p><strong>Дисклеймер</strong>: всё описанное — это мой личный опыт и мои решения. Не универсальный рецепт. Бери то, что резонирует, и адаптируй под себя.</p>
</blockquote><h3 id="что-именно-публично">Что именно публично</h3>
<p>Хотя саму базу я не открываю, часть артефактов из неё так или иначе попадает в публичное пространство:</p>
<ul>
<li><strong>Посты канала</strong> — практически все посты «Мишки на сервере» рождаются из черновиков в базе.</li>
<li><strong>Слайды и выступления</strong> — например, доклад для студентов РТУ МИРЭА о PKB (<a href="https://jtprogru.github.io/pkbd/" rel="noopener noreferrer" target="_blank">слайды</a>
) целиком сделан из заметок.</li>
<li><strong><a href="https://jtprog.ru/posts/pkb-check-list/">Чек-лист для организации персональной базы знаний</a>
</strong> — публичный артефакт в блоге.</li>
<li><strong>Шаблоны</strong> — часть шаблонов я периодически описываю в постах.</li>
</ul>
<p>Что никогда не попадает публично: рабочие детали с конкретными системами и командами, личные записи про людей, дневниковые записи, заметки про инциденты.</p>
<hr>
<h2 id="начну-со-структуры">Начну со структуры</h2>
<p>Довольно часто те, кто начинает заниматься заметковедением, начинают ломаться именно тут — попытка полностью продумать идеальную структуру базы знаний ломается ещё до первой заметки. Я и сам страдал этим — у меня сейчас примерно третья или четвёртая версия структуры.</p>
<p>Если кратко о том, как она эволюционировала: сначала была плоская куча файлов по папкам «Работа», «Личное», «Разное» — быстро стало непонятно, куда класть новое. Потом попытался следовать PARA (Projects-Areas-Resources-Archives) строго — оказалось слишком жёстко и я тратил больше времени на классификацию, чем на сами заметки. Нынешняя структура — это упрощённая PARA под себя.</p>
<p>Менять структуру — это нормально и правильно. Твоя персональная база знаний живёт и развивается вместе с тобой. Ты изучаешь что-то или пробуешь новое, находишь этому применение — и вот уже стоит задача реорганизовать размещение заметок.</p>
<p>Вернусь к себе. На текущий момент, структура директорий, которая используется у меня — в первую очередь удовлетворяет именно меня. Вот так у меня выглядит верхний уровень:</p>
<ul>
<li><code>00. Входящие</code> — просто мой инбокс заметок — сюда попадают абсолютно все заметки, которые я фиксирую.</li>
<li><code>01. Проекты</code> — преимущественно личные проекты, но иногда и рабочие там тоже оказываются.</li>
<li><code>02. Сферы</code> — содержит различные сферы моей жизни.</li>
<li><code>03. Ресурсы</code> — сюда я складываю информацию о книгах, статья и видео, а также навигационные карты.</li>
<li><code>04. Архив</code> — название говорит само за себя, я удаляю заметки крайне редко и чаще всего переношу их в архив.</li>
<li><code>05. Дневник</code> — еще одно очевидное название, тут лежат ежедневные заметки.</li>
<li><code>_Система</code> — тут лежат преимущественно служебные штуки, такие как шаблоны, картинки, холсты и прочие непотребства, которые я храню отдельно от заметок.</li>
<li><code>README.md</code> — моя входная точка в базу знаний (дашборд), а имя выбрано потому что бэкапы идут в Git.</li>
<li><code>AGENTS.md</code> — универсальные инструкции для всяких агентов, которые я иногда запускаю (преимущественно Claude Code).</li>
</ul>
<p>Всё это живёт в Obsidian — на данный момент у меня там порядка ≈5400 заметок. Из ключевых плагинов использую: <strong>Dataview</strong> (динамические запросы по базе), <strong>Templater</strong> (создание заметок из шаблонов), <strong>Omnisearch</strong> (полнотекстовый поиск) и <strong>Git</strong> (автоматические бэкапы).</p>
<h3 id="ключевые-понятия-чтобы-не-было-путаницы">Ключевые понятия (чтобы не было путаницы)</h3>
<p>Я использую несколько терминов, которые у разных людей означают разное. Вот как они работают у меня:</p>
<ul>
<li><strong>Входящие</strong> — «мусоропровод», куда летит всё подряд. Необработанное, без структуры. Задача — не потерять мысль, обрабатывать сразу не нужно.</li>
<li><strong>Черновик</strong> — заметка в процессе написания. Живёт уже в тематической папке, не во входящих. Отличие: уже есть намерение сделать из неё что-то конкретное.</li>
<li><strong>Дневник</strong> — ежедневные заметки. Отдельная категория, не входящие и не ресурсы. Не предназначен для переработки в посты.</li>
<li><strong>Карта / Map-of-Content (MOC)</strong> — навигационная заметка, которая собирает ссылки по теме. Не содержит знаний сама по себе — только указатели. Думай об этом как об оглавлении книги.</li>
<li><strong>Полноценная заметка</strong> — заметка с заголовком, 1-3 ключевыми тезисами, ссылками на связанные заметки и заполненным frontmatter. Не обязательно длинная — часто это 3-5 предложений.</li>
</ul>
<h3 id="обработка-входящих">Обработка входящих</h3>
<p>После обработки заметки из входящих, она отправляется в одну из категорий:</p>
<ul>
<li>Становится полноценной заметкой.</li>
<li>Становится картой.</li>
</ul>
<blockquote><p><strong>Замечание</strong>: Заметки по статьям, видео и книгам сразу складываются в свои директории.</p>
</blockquote><h3 id="жизненный-цикл-заметки">Жизненный цикл заметки</h3>
<p>Вот как заметка проходит путь от мысли до архива:</p>
<ol>
<li><strong>Захват</strong> → любая мысль/идея/факт фиксируется во <code>00. Входящие</code> или в дневнике. Формат не важен — главное не потерять.</li>
<li><strong>Обработка</strong> → раз в несколько дней разбираю инбокс: определяю тип заметки, добавляю frontmatter, перемещаю в нужную папку.</li>
<li><strong>Размещение</strong> → заметка отправляется в <code>01-04</code>, получает структуру по шаблону.</li>
<li><strong>Связывание</strong> → расставляю ссылки на связанные заметки, обновляю MOC если нужно.</li>
<li><strong>Использование</strong> → заметка живёт, дополняется при необходимости.</li>
<li><strong>Архив</strong> → если тема устарела — переношу в <code>04. Архив</code>, не удаляю.</li>
</ol>
<p>Инбокс обрабатываю без жёсткого расписания — по ощущению «накопилось». Обычно это 15-30 минут, 2-3 раза в неделю.</p>
<h3 id="правила-именования">Правила именования</h3>
<p>Заметки называю по принципу «чтобы было понятно без открытия»:</p>
<ul>
<li>Язык названия = язык заметки (русский по умолчанию, английский для технических терминов).</li>
<li>Никаких дат в названии, кроме дневниковых заметок (<code>2024-03-15</code>).</li>
<li>Существительные или глагольные фразы: «Ведение дневника лучше чем ведение todo-листа», «Kubernetes networking», «Почему SRE ≠ DevOps».</li>
<li>Никаких префиксов вроде <code>MOC-</code>, <code>BOOK-</code>, <code>IDEA-</code> — для этого есть теги и frontmatter.</li>
</ul>
<h3 id="как-я-нахожу-нужное">Как я нахожу нужное</h3>
<p>Страх «положу и забуду» — один из самых частых аргументов против ведения базы знаний. Но у меня он не работает, и вот почему.</p>
<p>Во-первых, поиск. Штатный поиск Obsidian слабоват, но я использую плагин Omnisearch — он быстрый и ищет по всему тексту, достаточно вспомнить любое слово из заметки. Во-вторых, связи между заметками: когда пишешь новую заметку и ставишь ссылки на старые, граф знаний сам напоминает, что у тебя уже есть по теме. В-третьих, Dataview-запросы в MOC-картах автоматически собирают заметки — не надо помнить, где что лежит.</p>
<p>На практике я редко «ищу» заметку целенаправленно. Чаще всего нужное всплывает само при написании новой заметки или при просмотре дневника.</p>
<p>Конкретные примеры навигации:</p>
<ul>
<li><strong>Идеи для постов</strong> → открываю MOC «Медийность» с Dataview-запросом, который тянет все заметки с тегом <code>#content</code>. Весь бэклог в одном месте.</li>
<li><strong>Инциденты</strong> → у каждого инцидента шаблон с тегом <code>#sre</code>. Dataview в MOC по SRE собирает их все.</li>
<li><strong>Книга, которую читал год назад</strong> → ищу по названию через Omnisearch или иду в <code>03. Ресурсы / Книги</code>.</li>
</ul>
<h3 id="шаблоны">Шаблоны</h3>
<p>Шаблонов у меня довольно много, и они со временем меняются. Вот те, что использую регулярно:</p>
<ul>
<li><code>Ежегодная заметка</code> — обзор года, использую в конце года, чтобы просто порефлексировать и подвести личные итоги.</li>
<li><code>Ежедневная заметка</code> — одна из основных заметок, используется для ведения дневника.</li>
<li><code>Конспект по лекции</code> — я студент и у меня есть отдельный шаблон для лекций, которые я посещаю.</li>
<li><code>Обзор конференции</code> — обзорная заметка про конкретную конференцию, где собираются все посещенные доклады и новые люди.</li>
<li><code>Шаблон тезисов по докладу</code> — доклады, которые я посетил на конференции и которые добавляются в обзорную заметку.</li>
<li><code>Созвон или встреча</code> — говорящее название, использую в том числе и для работы.</li>
<li><code>Черновик поста</code> — черновик поста (универсальный) и этот пост также был создан из этого шаблона.</li>
<li><code>Шаблон идея</code> — самый важный шаблон, который используется для всех заметок, которые я пишу сам сохраняю во входящих.</li>
<li><code>Шаблон инцидента</code> — для инцидентов, в которых я участвую лично у меня есть отдельный шаблон, информацию из которого я потом выношу в Postmortem.</li>
<li><code>Шаблон карты</code> — навигационные заметки или Map-of-Content.</li>
<li><code>Шаблон тезисов по видео</code>, <code>Шаблон тезисов по книге</code>, <code>Шаблон тезисов по статье</code> — для видео, книги или статьи используется свой шаблон, который в бОльшей степени является навигационной заметкой.</li>
<li><code>Шаблон человека</code> — заметки о людях.</li>
</ul>
<hr>
<h2 id="теги-и-свойства">Теги и свойства</h2>
<p>Теги у меня — это дополнительный слой навигации поверх папочной структуры. Живут в frontmatter, никаких инлайн-тегов.</p>
<p>Основные теги, которые реально использую:</p>
<table>
  <thead>
      <tr>
          <th>Тег</th>
          <th>Когда ставлю</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>#content</code> / <code>#telegram</code></td>
          <td>Черновик или идея для поста/канала</td>
      </tr>
      <tr>
          <td><code>#sre</code> / <code>#devops</code> / <code>#kubernetes</code></td>
          <td>Технические заметки по профилю</td>
      </tr>
      <tr>
          <td><code>#concept</code></td>
          <td>Термин, модель, фреймворк</td>
      </tr>
      <tr>
          <td><code>#thought</code></td>
          <td>Личная атомарная мысль</td>
      </tr>
      <tr>
          <td><code>#book</code> / <code>#article</code> / <code>#video</code></td>
          <td>Тип источника</td>
      </tr>
      <tr>
          <td><code>#inbox/review</code></td>
          <td>Требует обработки — снимаю тег после разбора</td>
      </tr>
      <tr>
          <td><code>#journal/daily</code></td>
          <td>Ежедневная запись</td>
      </tr>
  </tbody>
</table>
<p>В frontmatter также регулярно использую:</p>
<ul>
<li><code>up</code> / <code>down</code> — для навигации вверх/вниз по иерархии тем</li>
<li><code>status</code> — <code>Todo</code> / <code>WIP</code> / <code>Done</code> для проектов и черновиков</li>
<li><code>confidence</code> — <code>low</code> / <code>medium</code> / <code>high</code> для концептов и тезисов</li>
<li><code>sources</code> — список источников, из которых пришла информация</li>
</ul>
<hr>
<h2 id="темы-и-тематики">Темы и тематики</h2>
<p>Опишу крупными мазками — когортами тем — что у меня лежит в базе.</p>
<h3 id="преимущественно-рабочее">Преимущественно рабочее</h3>
<ul>
<li>Профильные темы — Dev(Sec)Ops/SRE, Кибербез/Защита информации, Процессы Incident&amp;Problem Management, (S)SDLC, etc&hellip;</li>
<li>Углубление в темы или Deep Dive — Infrastructure as/from Code, K8s, CICD, Configuration Management, etc&hellip;</li>
<li>Computer Science — Программирование, Основы CS, Golang/Python, Алгоритмы, Структуры данных, Парадигмы, etc&hellip;</li>
<li>Методологии — DevOps, SRE, Agile, Scrum, Kanban, ITSM, ITIL, TBM, etc&hellip;</li>
<li>Рабочее — Компании, Команды, Проекты, Встречи, Онбординги, etc&hellip;</li>
<li>Менеджмент — Управление людьми/командами/компаниями, Тимлидство и Техлидство.</li>
<li>Блог — Темы постов и готовые посты для канала и блога.</li>
</ul>
<p>Чтобы дать ощущение масштаба — вот несколько реальных названий заметок из рабочего блока (без содержания):</p>
<ul>
<li>«Чем SRE отличается от DevOps (и почему это важно)»</li>
<li>«SLO, SLA, SLI — разбор на пальцах»</li>
<li>«Почему постмортемы не работают без blame-free культуры»</li>
<li>«Kubernetes: как работает network policy»</li>
<li>«Разница между горизонтальным и вертикальным масштабированием»</li>
</ul>
<h3 id="я-мышление-и-работа-над-собой">Я, Мышление и работа над собой</h3>
<ul>
<li>Личная база знаний — Устройство, Воркфлоу, Второй мозг, etc&hellip;</li>
<li>Саморазвитие и Образование — Курсы, Книги, Хард- и Софт-скиллы, Области роста, Конспекты, etc&hellip;</li>
<li>Психология — Личная, Командная, Коммуникация, etc&hellip;</li>
<li>Мысли и принципы жизни — Разрозненные умозаключения и идеи, Проектирование себя, etc&hellip;</li>
<li>Личное — Семья, Финансы, Здоровье, Люди, etc&hellip;</li>
</ul>
<p>Примеры названий из этого блока:</p>
<ul>
<li>«Ведение дневника лучше чем ведение todo-листа»</li>
<li>«Как я принимаю сложные решения»</li>
<li>«Почему я перестал делать списки задач на день»</li>
<li>«Привязанность vs зависимость в отношениях»</li>
</ul>
<h3 id="разное">Разное</h3>
<p>Тут прям все подряд без списка: Философия, Право, Социология, Публичные выступления, Работа мозга, Драматургия.</p>
<h3 id="дневник">Дневник</h3>
<p>Это прям отдельная тема, которую я считаю крайне важной — дневник и ежедневные заметки, в которых фиксируется абсолютно всё, как в личном блокноте.</p>
<p>Когда-то подсмотрел у Рустама Агамалиева подтверждение того, что у меня чисто интуитивно вызывало комфорт: ведение дневника лучше, чем ведение todo-листа. В свободной форме пишу то, что необходимо сделать или уже сделано. О том, как я веду свой дневник, можно прочитать у меня в отдельном <a href="https://t.me/jtprogru_channel/4265" rel="noopener noreferrer" target="_blank">посте</a>
.</p>
<hr>
<h2 id="записывать-или-не-записывать">Записывать или не записывать</h2>
<p>Буквально, как в монологе Гамлета — &ldquo;Быть или не быть&hellip;&rdquo; очередной заметке. И тут, как и везде — <em>все максимально индивидуально</em>. Именно поэтому я просто попытаюсь описать, чем именно я руководствуюсь, когда создаю очередную заметку.</p>
<h3 id="пригодится-или-справочная-информация">Пригодится или Справочная информация</h3>
<p>Заметка, как какой-то справочный материал, который мне может пригодиться в будущем. Для разных &ldquo;штук&rdquo;, которые бывает дольше гуглить и вспоминать, поэтому проще сохранить в виде заметки:</p>
<ul>
<li>разделение настроек для консольного git-клиента</li>
<li>возвращение режима модема на айфонах</li>
<li>расположение файлов библиотеки приложения Apple Books</li>
</ul>
<p>Проще говоря, это такие заметки, которые я первым делом пойду гуглить — какие-то инструкции, которые мне бывают не часто нужны и которые я не могу должным образом автоматизировать.</p>
<p>В эту же категорию относятся и заметки о каких-то людях. Будь то научный деятель, блогер, философ или &ldquo;крутой чувак&rdquo; с которым я познакомился на конференции.</p>
<h3 id="очередная-гениальная-идея">Очередная гениальная идея</h3>
<p>Не важно, когда она ко мне пришла в голову — в процессе чтения книги/статьи/видоса, либо во время выполнения рабочей задачи или даже во время созвона кем-то. Я запишу эту мысль, чем бы она ни была — связана она с текущим контекстом или деятельностью или нет.</p>
<p>Чаще всего такие мысли фиксируются в ежедневной заметке, а оттуда в ближайшее время извлекаются в отдельную заметку и попадают во входящие на дальнейшую обработку.</p>
<p>Тут могут быть и идеи по личной или рабочей автоматизации, и какие-то околофилософские мыслезлоключения, и идеи доработок чего-либо (особенно рабочее или в пет-проектах). Проще говоря — что-то, что не хочется забыть.</p>
<h3 id="рефлексия">Рефлексия</h3>
<p>Кто-то в рамках ежедневных заметок ведет полноценное планирование и управление проектами, а также через свойства отмечает сколько часов поспал и количество выпитой воды с настроением. Но это точно не я — мне такое пока не очень интересно отслеживать в своей базе знаний.</p>
<p>Я уже не однократно упоминал то, что я веду дневник и веду я его с 2021 года (самая первая дата — 2021-08-05). И вот именно дневник мне начал приносить ощутимую пользу — дневник позволяет ковыряться в собственных мозгах так, словно ты наблюдаешь со стороны.</p>
<p>Была куча разных приложений перепробована, но все они довольно быстро надоедают. А потребность в том, чтобы научиться разбираться в себе — была всегда и будет со мной всегда. Даже в работе с психологами дневник очень хорошо помогает мне.</p>
<h3 id="конспекты-и-обучение">Конспекты и обучение</h3>
<p>Книга, видео, лекция, статья — всё, из чего я что-то усвоил или хочу усвоить, попадает в базу. Не пересказ, а именно то, что меня зацепило: конкретная мысль, тезис, пример, который хочу вернуть потом.</p>
<p>Для каждого типа источника у меня отдельный шаблон (книга / видео / статья / доклад), потому что у них разная структура и разный контекст. Главное правило тут — <strong>не стараться законспектировать всё</strong>. Записываю только то, что хочу переосмыслить или применить.</p>
<h3 id="что-я-намеренно-не-записываю">Что я намеренно НЕ записываю</h3>
<p>Несколько категорий, которые осознанно остаются вне базы знаний:</p>
<ul>
<li><strong>Пароли и секреты</strong> — для этого есть парольный менеджер. В базу знаний принципиально не попадают.</li>
<li><strong>Персональные данные других людей</strong> — контакты храню минимально, без чувствительных деталей. Заметка о человеке — это профессиональный контекст, не личное досье.</li>
<li><strong>Рабочие секреты</strong> — архитектура клиентских систем, внутренние имена, конфигурации. Если что-то рабочее попадает в заметку — сразу обезличивается.</li>
<li><strong>Эмоции в моменте без контекста</strong> — «я злой», «всё плохо» без объяснения почему. Дневник — место для рефлексии, а не для фиксации сырого состояния без смысла.</li>
<li><strong>Задачи и todo-листы</strong> — для задач есть трекер. База знаний — не таск-менеджер.</li>
</ul>
<hr>
<h2 id="приватность-и-безопасность">Приватность и безопасность</h2>
<p>Раз уж я сказал «не покажу пока живой» — логично объяснить, как именно сделано так, чтобы случайно не утекло.</p>
<ul>
<li><strong>Шифрование диска</strong> — база хранится локально, диск зашифрован.</li>
<li><strong>iCloud</strong> — синхронизация между устройствами. Не идеально с точки зрения параноика, но для меня приемлемо.</li>
<li><strong>Git-бэкап</strong> — автоматический бэкап в приватный репозиторий. В <code>.gitignore</code> исключены чувствительные файлы.</li>
<li><strong>Нет публичных ссылок</strong> — никакого Obsidian Publish или аналогов. Если что-то публикую — делаю это руками, отдельным постом.</li>
</ul>
<h2 id="пересмотр-и-актуальность">Пересмотр и актуальность</h2>
<p>База знаний — это не музей. Заметки устаревают, взгляды меняются, какие-то темы перестают быть актуальными.</p>
<p>Как я с этим работаю:</p>
<ul>
<li><strong>Periodic review — по факту, не по расписанию</strong>. Нет жёсткого «раз в неделю смотрю базу». Пересматриваю заметки, когда возвращаюсь к теме по делу.</li>
<li><strong>Статус <code>WIP</code> как маркер</strong>. Если заметка давно в <code>WIP</code> и к ней нет желания возвращаться — это сигнал либо закрыть (→ <code>Done</code>), либо заархивировать.</li>
<li><strong>Дневник как встроенный review</strong>. Ежегодные и ежемесячные заметки — там я естественным образом возвращаюсь к тому, что было важно.</li>
<li><strong>Архив вместо удаления</strong>. Почти никогда не удаляю заметки. Если информация устарела — переношу в <code>04. Архив</code>. Потом можно найти и посмотреть, как думал раньше.</li>
</ul>
<hr>
<h2 id="итоги-и-полезности">Итоги и полезности</h2>
<p>У меня есть в блоге <a href="https://jtprog.ru/posts/pkb-check-list/">Чек-лист для организации персональной базы знаний</a>
 — если хочешь начать, это хорошая отправная точка. Также было небольшое выступление перед студентами РТУ МИРЭА про знакомство с личной базой знаний (<a href="https://jtprogru.github.io/pkbd/" rel="noopener noreferrer" target="_blank">слайды</a>
 есть, а видео нет).</p>
<p>Если вынести одну мысль из всего этого — <strong>важнее писать заметки, чем не писать их вовсе</strong>. Не нужна идеальная структура с первого дня. Не нужно читать все книги по PKB и Zettelkasten. Нужно просто начать фиксировать то, что кажется важным — и постепенно система сама начнёт складываться под тебя.</p>
<p><strong>Кому такой подход подойдёт:</strong></p>
<ul>
<li>Тем, кто работает со знаниями профессионально и хочет не забывать то, что узнаёт.</li>
<li>Тем, кто хочет думать более структурированно и видеть связи между идеями.</li>
<li>Тем, кому важно иметь «свой» инструмент, а не чужую систему.</li>
</ul>
<p><strong>Кому, скорее всего, не подойдёт:</strong></p>
<ul>
<li>Тем, кто хочет быстрый результат — первые месяцы база знаний больше потребляет времени, чем отдаёт.</li>
<li>Тем, кто не готов периодически разбирать инбокс — без обработки это просто свалка.</li>
</ul>
<p><strong>С чего начать новичку:</strong></p>
<ol>
<li>Выбери инструмент (Obsidian, Notion, Logseq — не важно, главное начать).</li>
<li>Заведи один шаблон для «идеи» — просто заголовок + 2-3 строки.</li>
<li>Первую неделю пиши всё подряд без структуры.</li>
<li>На второй неделе посмотри, что накопилось, и попробуй сгруппировать.</li>
<li>Структура появится сама — из того, что реально накапливается.</li>
</ol>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></content:encoded>
    </item><item>
      <title>Как выглядит MBR</title>
      <link>https://jtprog.ru/posts/what-is-mbr/</link>
      <pubDate>Tue, 05 May 2026 20:36:08 +0300</pubDate>
      <dc:creator>jtprogru</dc:creator>
      <guid isPermaLink="true">https://jtprog.ru/posts/what-is-mbr/</guid>
      <category>MBR</category>
      <category>BIOS</category>
      <category>Разметка Диска</category>
      <category>Linux</category>
      <category>Администрирование</category>
      <category domain="category">OS</category>
      <enclosure url="https://jtprog.ru/OS.png" type="image/jpeg" length="0" />
      <media:thumbnail url="https://jtprog.ru/OS.png" /><description><![CDATA[<div><p>Привет, <code>%username%</code>! Сегодня MBR воспринимается как что-то из музея — на новых машинах давно <a href="/posts/what-is-gpt/">GPT</a>
 и UEFI, а слово «активный раздел» молодёжь слышит впервые в жизни. Но MBR никуда не делся: он живёт на старых ноутбуках, флешках, виртуалках с BIOS-загрузкой и в виде Protective MBR на тех самых GPT-дисках. И когда что-то «перестало грузиться», понимать, что лежит в первых 512 байтах диска, всё ещё бывает очень полезно.</p>
<p>В этой шпаргалке разберём по байтам, что такое MBR, как устроены его четыре записи о разделах, зачем нужны extended/logical партиции через EBR и какие архитектурные ограничения в итоге привели к появлению GPT.</p>
<h2 id="что-такое-mbr">Что такое MBR</h2>
<p><strong>MBR (Master Boot Record)</strong> — самый первый сектор диска (LBA 0, 512 байт), в котором одновременно живут две вещи: маленький загрузочный код для BIOS и таблица из четырёх записей о разделах. Появился в 1983 году вместе с PC DOS 2.0 и больше тридцати лет был стандартом разметки x86-машин, пока его наконец не вытеснил <a href="/posts/what-is-gpt/">GPT</a>
.</p>
<p>Главная идея простая до неприличия: BIOS после POST читает первый сектор первого устройства, проверяет, что он заканчивается сигнатурой <code>0x55AA</code>, и передаёт управление в самое начало этого сектора как обычному 16-битному коду. Дальше уже сам код решает, какой раздел грузить. Никаких CRC, никаких backup-копий, никакой защиты — затёр сектор и привет.</p>
<h2 id="карта-сектора-512-байт">Карта сектора (512 байт)</h2>
<div class="codeblock"><button class="codeblock__copy" type="button" data-copy aria-label="Скопировать" title="Скопировать"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button><pre tabindex="0"><code>Offset  Size   Назначение
------  ----   ----------
0x000   440    Bootstrap code (загрузчик, stage 1)
0x1B8   4      Disk Signature (NT Disk Signature / MBR ID)
0x1BC   2      Reserved (обычно 0x0000)
0x1BE   16     Partition Entry #1
0x1CE   16     Partition Entry #2
0x1DE   16     Partition Entry #3
0x1EE   16     Partition Entry #4
0x1FE   2      Boot Signature (0x55 0xAA)</code></pre>
</div>
<p>Итого: 440 + 4 + 2 + 64 + 2 = <strong>512 байт</strong> ровно. Именно столько было в одном секторе у дисков 80-х, и именно эта цифра до сих пор определяет всё устройство MBR.</p>
<h2 id="bootstrap-code-0x0000x1b7">Bootstrap code (<code>0x000–0x1B7</code>)</h2>
<p>440 байт машинного кода в реальном режиме x86. Что туда обычно кладут:</p>
<ul>
<li>Минимальный загрузчик, который ищет «активный» раздел (с флагом <code>0x80</code>)</li>
<li>Читает с него первый сектор (VBR — Volume Boot Record) и передаёт ему управление</li>
<li>Либо это <strong>stage 1 GRUB / LILO / syslinux</strong>, который читает stage 1.5 / stage 2 с заранее известных секторов</li>
</ul>
<p>В 440 байт нельзя засунуть драйвер файловой системы — поэтому stage 1 GRUB хранит в себе блок-лист (LBA-адреса) первых секторов stage 1.5 в т. н. «post-MBR gap» (секторы 1–62, до начала первого раздела). Если переразметил диск так, что эти сектора съехали — система не грузится, и это самая частая причина «всё работало, потом подвинул раздел и сломалось».</p>
<h2 id="disk-signature-0x1b80x1bb">Disk Signature (<code>0x1B8–0x1BB</code>)</h2>
<p>4 байта — уникальный идентификатор диска, который Windows называет <strong>NT Disk Signature</strong>. По нему ОС привязывает диск к буквам в <code>BCD</code> и реестре. Если склонировать диск побайтово на другой — Windows увидит два диска с одинаковой подписью и одну из них автоматически переведёт в offline. Лечится через <code>diskpart → uniqueid disk id=...</code>, но узнать про эту весёлую особенность обычно успеваешь уже после нескольких часов поиска «почему второй диск не виден».</p>
<p>В Linux эта же подпись видна через <code>fdisk -l</code>, поле <code>Disk identifier: 0x...</code>.</p>
<h2 id="partition-entry-16-байт">Partition Entry (16 байт)</h2>
<p>Главная структура разметки. Четыре штуки, фиксированно, на любом MBR-диске в мире:</p>
<table>
  <thead>
      <tr>
          <th style="text-align: right">Offset</th>
          <th style="text-align: right">Size</th>
          <th>Поле</th>
          <th>Описание</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: right">0</td>
          <td style="text-align: right">1</td>
          <td><code>Boot indicator</code></td>
          <td><code>0x80</code> — активный (бутабельный), <code>0x00</code> — нет, прочее — invalid</td>
      </tr>
      <tr>
          <td style="text-align: right">1</td>
          <td style="text-align: right">3</td>
          <td><code>Starting CHS</code></td>
          <td>Cylinder/Head/Sector начала раздела (legacy)</td>
      </tr>
      <tr>
          <td style="text-align: right">4</td>
          <td style="text-align: right">1</td>
          <td><code>Partition Type</code></td>
          <td>Тип раздела (см. ниже)</td>
      </tr>
      <tr>
          <td style="text-align: right">5</td>
          <td style="text-align: right">3</td>
          <td><code>Ending CHS</code></td>
          <td>CHS конца раздела (legacy)</td>
      </tr>
      <tr>
          <td style="text-align: right">8</td>
          <td style="text-align: right">4</td>
          <td><code>Starting LBA</code></td>
          <td>LBA первого сектора раздела (little-endian)</td>
      </tr>
      <tr>
          <td style="text-align: right">12</td>
          <td style="text-align: right">4</td>
          <td><code>Size in LBA</code></td>
          <td>Длина раздела в секторах</td>
      </tr>
  </tbody>
</table>
<p>Из этих 16 байт реально работают только последние 8: <code>Starting LBA</code> + <code>Size in LBA</code>. Поля CHS остались для совместимости с BIOS-ами 80-х; современные ОС их игнорируют, но для надёжности туда обычно пишут <code>0xFFFFFF</code>, если раздел выходит за пределы CHS-адресации (а это всё, что больше ~8 ГБ — то есть фактически любой диск, который ты держал в руках за последние двадцать лет).</p>
<h3 id="лимиты-которые-отсюда-растут">Лимиты, которые отсюда растут</h3>
<ul>
<li><code>Starting LBA</code> и <code>Size in LBA</code> — 32-битные → максимум <strong>2³² × 512 байт = 2 ТиБ</strong>. Дальше адрес физически не лезет, и MBR на 4-терабайтнике увидит ровно половину диска. Если столкнулся — это знак, что пора на GPT</li>
<li>Записей всего 4 → максимум <strong>4 первичных раздела</strong>. Чтобы обойти этот лимит, придумали extended-партиции</li>
</ul>
<h2 id="partition-type-известные-коды">Partition Type (известные коды)</h2>
<table>
  <thead>
      <tr>
          <th>Код</th>
          <th>Тип</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>0x00</code></td>
          <td>Пусто</td>
      </tr>
      <tr>
          <td><code>0x05</code></td>
          <td>Extended (CHS)</td>
      </tr>
      <tr>
          <td><code>0x07</code></td>
          <td>NTFS / exFAT / HPFS</td>
      </tr>
      <tr>
          <td><code>0x0B</code></td>
          <td>FAT32 (CHS)</td>
      </tr>
      <tr>
          <td><code>0x0C</code></td>
          <td>FAT32 (LBA)</td>
      </tr>
      <tr>
          <td><code>0x0E</code></td>
          <td>FAT16 (LBA)</td>
      </tr>
      <tr>
          <td><code>0x0F</code></td>
          <td>Extended (LBA)</td>
      </tr>
      <tr>
          <td><code>0x82</code></td>
          <td>Linux swap</td>
      </tr>
      <tr>
          <td><code>0x83</code></td>
          <td>Linux filesystem</td>
      </tr>
      <tr>
          <td><code>0x8E</code></td>
          <td>Linux LVM</td>
      </tr>
      <tr>
          <td><code>0xA5</code></td>
          <td>FreeBSD</td>
      </tr>
      <tr>
          <td><code>0xAF</code></td>
          <td>Apple HFS / HFS+</td>
      </tr>
      <tr>
          <td><code>0xEE</code></td>
          <td>GPT Protective MBR</td>
      </tr>
      <tr>
          <td><code>0xEF</code></td>
          <td>EFI System (на MBR-диске)</td>
      </tr>
      <tr>
          <td><code>0xFD</code></td>
          <td>Linux RAID auto-detect</td>
      </tr>
  </tbody>
</table>
<p>Тип — это просто метка-подсказка для ОС, что внутри. Сам диск от смены типа не «форматируется», но Windows может перестать видеть раздел, если поставить «чужой» код. Кстати, никакого центрального реестра этих кодов нет — список держится на честном слове и Wikipedia, поэтому для разных ОС одинаковые байты иногда означают разное. Привет, GPT с его GUID-ами.</p>
<h2 id="extended-и-logical-partitions">Extended и logical partitions</h2>
<p>Чтобы сделать больше четырёх разделов, одну из четырёх записей объявляют <strong>extended</strong> (тип <code>0x05</code> или <code>0x0F</code>). Внутри extended-области строится <strong>связный список</strong> через дополнительные структуры — <strong>EBR (Extended Boot Record)</strong>.</p>
<p>Каждый EBR — это сектор с такой же таблицей из 4 записей, но реально используются только две:</p>
<ul>
<li><strong>Запись 1</strong> — описывает logical-раздел, лежащий сразу за этим EBR</li>
<li><strong>Запись 2</strong> — указывает на следующий EBR в цепочке (тип <code>0x05</code>/<code>0x0F</code>); смещения здесь относительные</li>
</ul>
<p>Цепочка обрывается, когда вторая запись пустая. В Linux logical-разделы нумеруются с <code>5</code> (<code>/dev/sda5</code>, <code>/dev/sda6</code>, …) — независимо от того, сколько было primary-разделов. Лимит на количество — обычно 60 logical в Linux, ограничение драйвера ядра.</p>
<p>Минусы конструкции:</p>
<ul>
<li>Список последовательный → удалил logical посередине, и нумерация поехала, фрагментация в полный рост</li>
<li>Затёр EBR — потерял всю цепочку дальше; backup-копии нет</li>
<li>Активным может быть только primary; нельзя загрузиться напрямую с logical, нужен посредник</li>
</ul>
<p>Это всё, очевидно, костыль. И именно поэтому на серверах с пятнадцатью разделами под логи, БД, /var и прочее переход на GPT воспринимается как глоток свежего воздуха.</p>
<h2 id="boot-signature-0x1fe0x1ff">Boot Signature (<code>0x1FE–0x1FF</code>)</h2>
<p>Два байта: <code>0x55 0xAA</code>. Если их нет — BIOS считает диск незагрузочным и идёт к следующему. Это самая частая жертва «битого MBR»: код есть, таблица есть, а сигнатуру кто-то затёр. Внешне выглядит как «диск пропал», хотя на самом деле там всего два байта надо вернуть на место.</p>
<h2 id="что-с-этим-делать-на-практике">Что с этим делать на практике</h2>
<ul>
<li><strong>Посмотреть таблицу</strong>: <code>fdisk -l /dev/sda</code>, <code>sfdisk -d /dev/sda</code>, <code>parted /dev/sda print</code></li>
<li><strong>Сырой дамп</strong>: <code>dd if=/dev/sda bs=512 count=1 | hexdump -C</code> — увидишь bootstrap, таблицу разделов и <code>55 AA</code> в самом конце</li>
<li><strong>Бэкап MBR целиком</strong>: <code>dd if=/dev/sda of=mbr.bin bs=512 count=1</code>. Только таблица без бутстрапа: <code>dd if=/dev/sda of=ptable.bin bs=1 skip=446 count=64</code></li>
<li><strong>Восстановить bootloader</strong>: <code>grub-install /dev/sda</code> (Linux), <code>bootrec /fixmbr</code> (Windows)</li>
<li><strong>Сменить тип раздела</strong>: <code>fdisk</code> → <code>t</code> → код. Не форматирует, только меняет байт</li>
<li><strong>Активировать раздел</strong>: <code>fdisk</code> → <code>a</code>. Помним: <code>0x80</code> должен стоять только у одного раздела</li>
</ul>
<h2 id="чем-плох-mbr-и-зачем-родился-gpt">Чем плох MBR (и зачем родился GPT)</h2>
<ul>
<li>Потолок 2 ТиБ — на современных дисках это ровно половина</li>
<li>Только 4 первичных раздела, остальное — через костыль с EBR</li>
<li>Нет контрольных сумм — один битфлип в нужном месте, и таблица «уехала», а ОС об этом не узнает</li>
<li>Нет резервной копии — затёртый сектор 0 равняется диску-«кирпичу» для BIOS</li>
<li>Тип раздела — 1 байт без пространства имён, поэтому коды конфликтуют между ОС и существуют по сути «по договорённости»</li>
</ul>
<p>Подробнее про преемника — в <a href="/posts/what-is-gpt/">Как выглядит GPT</a>
.</p>
<h2 id="тонкие-места-на-которых-легко-споткнуться">Тонкие места, на которых легко споткнуться</h2>
<ul>
<li><strong>CHS vs LBA</strong>: до сих пор встречаются прошивки, которые читают именно CHS. Если поставить туда «битые» значения, BIOS может отказаться грузиться даже при корректном LBA. Утилиты обычно сами пишут <code>0xFFFFFF</code> в CHS, но если правил руками — проверь</li>
<li><strong>Активный раздел</strong>: <code>0x80</code> должен быть <strong>только у одного</strong> раздела. Несколько активных — поведение зависит от загрузчика, и бывает классическое «грузится не то, что ожидал»</li>
<li><strong>MBR на USB</strong>: некоторые BIOS грузятся только если на флешке <code>0x80</code> стоит и тип — <code>0x0C</code>/<code>0x0B</code>. Нарезал через <code>dd</code> ISO-образ, а флешка не грузится — проверь именно это</li>
<li><strong>Hybrid MBR на GPT-дисках</strong>: записи в Protective MBR подменяют на «настоящие», чтобы BIOS-only ОС увидели разделы. Жуткий хак, рассинхрон с GPT ломает всё разом — лучше не использовать, но если унаследовал — знай, что оно есть</li>
<li><strong>NT Disk Signature и клонирование</strong>: после <code>dd</code> диска побайтово обязательно меняй подпись, иначе Windows унесёт один из дисков в offline. На Linux-only стенде проблемы нет, но как только подключишь к Windows — словишь весёлый сюрприз</li>
</ul>
<p>На этом всё. MBR — простая структура из эпохи, когда диски измерялись в мегабайтах, а 4 разделов хватало всем. Сегодня его удел — старые системы и роль Protective MBR на GPT-дисках, но базу знать всё ещё полезно: на боевой железке в 3 часа ночи хочется понимать, что именно ты сейчас правишь в <code>dd</code> и <code>hexdump</code>.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></description>
      <content:encoded><![CDATA[<style>/* Inline-CSS, который тема вкладывает в <description> каждого item'а
   RSS-фида (layouts/index.rss.xml). RSS-ридеры (Feedly, Inoreader,
   NetNewsWire) уважают <style> внутри description с переменной
   степенью энтузиазма — это базовый fallback, достаточный для читаемой
   типографики, не более.

   Цвета продублированы из 00-vars.css (light-палитра) — поправь
   синхронно при изменении --bg / --text / --accent / --border. */

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  line-height: 1.6;
  color: #1c1c1f;
  max-width: 720px;
  margin: 0 auto;
  padding: 1em;
}
h1, h2, h3 { line-height: 1.25; margin-top: 1.4em; }
a { color: #c2410c; }
pre {
  background: #1e1e24;
  color: #e8e6df;
  padding: 1em;
  border-radius: 6px;
  overflow-x: auto;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.9em;
}
code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  background: #f3f1ed;
  padding: 0.1em 0.4em;
  border-radius: 4px;
}
pre code { background: transparent; padding: 0; }
blockquote {
  border-left: 3px solid #c2410c;
  padding-left: 1em;
  color: #5b5b62;
  font-style: italic;
  margin-left: 0;
}
img { max-width: 100%; height: auto; border-radius: 6px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #e5e3dc; padding: 6px 10px; text-align: left; }
</style><div><p>Привет, <code>%username%</code>! Сегодня MBR воспринимается как что-то из музея — на новых машинах давно <a href="/posts/what-is-gpt/">GPT</a>
 и UEFI, а слово «активный раздел» молодёжь слышит впервые в жизни. Но MBR никуда не делся: он живёт на старых ноутбуках, флешках, виртуалках с BIOS-загрузкой и в виде Protective MBR на тех самых GPT-дисках. И когда что-то «перестало грузиться», понимать, что лежит в первых 512 байтах диска, всё ещё бывает очень полезно.</p>
<p>В этой шпаргалке разберём по байтам, что такое MBR, как устроены его четыре записи о разделах, зачем нужны extended/logical партиции через EBR и какие архитектурные ограничения в итоге привели к появлению GPT.</p>
<h2 id="что-такое-mbr">Что такое MBR</h2>
<p><strong>MBR (Master Boot Record)</strong> — самый первый сектор диска (LBA 0, 512 байт), в котором одновременно живут две вещи: маленький загрузочный код для BIOS и таблица из четырёх записей о разделах. Появился в 1983 году вместе с PC DOS 2.0 и больше тридцати лет был стандартом разметки x86-машин, пока его наконец не вытеснил <a href="/posts/what-is-gpt/">GPT</a>
.</p>
<p>Главная идея простая до неприличия: BIOS после POST читает первый сектор первого устройства, проверяет, что он заканчивается сигнатурой <code>0x55AA</code>, и передаёт управление в самое начало этого сектора как обычному 16-битному коду. Дальше уже сам код решает, какой раздел грузить. Никаких CRC, никаких backup-копий, никакой защиты — затёр сектор и привет.</p>
<h2 id="карта-сектора-512-байт">Карта сектора (512 байт)</h2>
<div class="codeblock"><button class="codeblock__copy" type="button" data-copy aria-label="Скопировать" title="Скопировать"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button><pre tabindex="0"><code>Offset  Size   Назначение
------  ----   ----------
0x000   440    Bootstrap code (загрузчик, stage 1)
0x1B8   4      Disk Signature (NT Disk Signature / MBR ID)
0x1BC   2      Reserved (обычно 0x0000)
0x1BE   16     Partition Entry #1
0x1CE   16     Partition Entry #2
0x1DE   16     Partition Entry #3
0x1EE   16     Partition Entry #4
0x1FE   2      Boot Signature (0x55 0xAA)</code></pre>
</div>
<p>Итого: 440 + 4 + 2 + 64 + 2 = <strong>512 байт</strong> ровно. Именно столько было в одном секторе у дисков 80-х, и именно эта цифра до сих пор определяет всё устройство MBR.</p>
<h2 id="bootstrap-code-0x0000x1b7">Bootstrap code (<code>0x000–0x1B7</code>)</h2>
<p>440 байт машинного кода в реальном режиме x86. Что туда обычно кладут:</p>
<ul>
<li>Минимальный загрузчик, который ищет «активный» раздел (с флагом <code>0x80</code>)</li>
<li>Читает с него первый сектор (VBR — Volume Boot Record) и передаёт ему управление</li>
<li>Либо это <strong>stage 1 GRUB / LILO / syslinux</strong>, который читает stage 1.5 / stage 2 с заранее известных секторов</li>
</ul>
<p>В 440 байт нельзя засунуть драйвер файловой системы — поэтому stage 1 GRUB хранит в себе блок-лист (LBA-адреса) первых секторов stage 1.5 в т. н. «post-MBR gap» (секторы 1–62, до начала первого раздела). Если переразметил диск так, что эти сектора съехали — система не грузится, и это самая частая причина «всё работало, потом подвинул раздел и сломалось».</p>
<h2 id="disk-signature-0x1b80x1bb">Disk Signature (<code>0x1B8–0x1BB</code>)</h2>
<p>4 байта — уникальный идентификатор диска, который Windows называет <strong>NT Disk Signature</strong>. По нему ОС привязывает диск к буквам в <code>BCD</code> и реестре. Если склонировать диск побайтово на другой — Windows увидит два диска с одинаковой подписью и одну из них автоматически переведёт в offline. Лечится через <code>diskpart → uniqueid disk id=...</code>, но узнать про эту весёлую особенность обычно успеваешь уже после нескольких часов поиска «почему второй диск не виден».</p>
<p>В Linux эта же подпись видна через <code>fdisk -l</code>, поле <code>Disk identifier: 0x...</code>.</p>
<h2 id="partition-entry-16-байт">Partition Entry (16 байт)</h2>
<p>Главная структура разметки. Четыре штуки, фиксированно, на любом MBR-диске в мире:</p>
<table>
  <thead>
      <tr>
          <th style="text-align: right">Offset</th>
          <th style="text-align: right">Size</th>
          <th>Поле</th>
          <th>Описание</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: right">0</td>
          <td style="text-align: right">1</td>
          <td><code>Boot indicator</code></td>
          <td><code>0x80</code> — активный (бутабельный), <code>0x00</code> — нет, прочее — invalid</td>
      </tr>
      <tr>
          <td style="text-align: right">1</td>
          <td style="text-align: right">3</td>
          <td><code>Starting CHS</code></td>
          <td>Cylinder/Head/Sector начала раздела (legacy)</td>
      </tr>
      <tr>
          <td style="text-align: right">4</td>
          <td style="text-align: right">1</td>
          <td><code>Partition Type</code></td>
          <td>Тип раздела (см. ниже)</td>
      </tr>
      <tr>
          <td style="text-align: right">5</td>
          <td style="text-align: right">3</td>
          <td><code>Ending CHS</code></td>
          <td>CHS конца раздела (legacy)</td>
      </tr>
      <tr>
          <td style="text-align: right">8</td>
          <td style="text-align: right">4</td>
          <td><code>Starting LBA</code></td>
          <td>LBA первого сектора раздела (little-endian)</td>
      </tr>
      <tr>
          <td style="text-align: right">12</td>
          <td style="text-align: right">4</td>
          <td><code>Size in LBA</code></td>
          <td>Длина раздела в секторах</td>
      </tr>
  </tbody>
</table>
<p>Из этих 16 байт реально работают только последние 8: <code>Starting LBA</code> + <code>Size in LBA</code>. Поля CHS остались для совместимости с BIOS-ами 80-х; современные ОС их игнорируют, но для надёжности туда обычно пишут <code>0xFFFFFF</code>, если раздел выходит за пределы CHS-адресации (а это всё, что больше ~8 ГБ — то есть фактически любой диск, который ты держал в руках за последние двадцать лет).</p>
<h3 id="лимиты-которые-отсюда-растут">Лимиты, которые отсюда растут</h3>
<ul>
<li><code>Starting LBA</code> и <code>Size in LBA</code> — 32-битные → максимум <strong>2³² × 512 байт = 2 ТиБ</strong>. Дальше адрес физически не лезет, и MBR на 4-терабайтнике увидит ровно половину диска. Если столкнулся — это знак, что пора на GPT</li>
<li>Записей всего 4 → максимум <strong>4 первичных раздела</strong>. Чтобы обойти этот лимит, придумали extended-партиции</li>
</ul>
<h2 id="partition-type-известные-коды">Partition Type (известные коды)</h2>
<table>
  <thead>
      <tr>
          <th>Код</th>
          <th>Тип</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>0x00</code></td>
          <td>Пусто</td>
      </tr>
      <tr>
          <td><code>0x05</code></td>
          <td>Extended (CHS)</td>
      </tr>
      <tr>
          <td><code>0x07</code></td>
          <td>NTFS / exFAT / HPFS</td>
      </tr>
      <tr>
          <td><code>0x0B</code></td>
          <td>FAT32 (CHS)</td>
      </tr>
      <tr>
          <td><code>0x0C</code></td>
          <td>FAT32 (LBA)</td>
      </tr>
      <tr>
          <td><code>0x0E</code></td>
          <td>FAT16 (LBA)</td>
      </tr>
      <tr>
          <td><code>0x0F</code></td>
          <td>Extended (LBA)</td>
      </tr>
      <tr>
          <td><code>0x82</code></td>
          <td>Linux swap</td>
      </tr>
      <tr>
          <td><code>0x83</code></td>
          <td>Linux filesystem</td>
      </tr>
      <tr>
          <td><code>0x8E</code></td>
          <td>Linux LVM</td>
      </tr>
      <tr>
          <td><code>0xA5</code></td>
          <td>FreeBSD</td>
      </tr>
      <tr>
          <td><code>0xAF</code></td>
          <td>Apple HFS / HFS+</td>
      </tr>
      <tr>
          <td><code>0xEE</code></td>
          <td>GPT Protective MBR</td>
      </tr>
      <tr>
          <td><code>0xEF</code></td>
          <td>EFI System (на MBR-диске)</td>
      </tr>
      <tr>
          <td><code>0xFD</code></td>
          <td>Linux RAID auto-detect</td>
      </tr>
  </tbody>
</table>
<p>Тип — это просто метка-подсказка для ОС, что внутри. Сам диск от смены типа не «форматируется», но Windows может перестать видеть раздел, если поставить «чужой» код. Кстати, никакого центрального реестра этих кодов нет — список держится на честном слове и Wikipedia, поэтому для разных ОС одинаковые байты иногда означают разное. Привет, GPT с его GUID-ами.</p>
<h2 id="extended-и-logical-partitions">Extended и logical partitions</h2>
<p>Чтобы сделать больше четырёх разделов, одну из четырёх записей объявляют <strong>extended</strong> (тип <code>0x05</code> или <code>0x0F</code>). Внутри extended-области строится <strong>связный список</strong> через дополнительные структуры — <strong>EBR (Extended Boot Record)</strong>.</p>
<p>Каждый EBR — это сектор с такой же таблицей из 4 записей, но реально используются только две:</p>
<ul>
<li><strong>Запись 1</strong> — описывает logical-раздел, лежащий сразу за этим EBR</li>
<li><strong>Запись 2</strong> — указывает на следующий EBR в цепочке (тип <code>0x05</code>/<code>0x0F</code>); смещения здесь относительные</li>
</ul>
<p>Цепочка обрывается, когда вторая запись пустая. В Linux logical-разделы нумеруются с <code>5</code> (<code>/dev/sda5</code>, <code>/dev/sda6</code>, …) — независимо от того, сколько было primary-разделов. Лимит на количество — обычно 60 logical в Linux, ограничение драйвера ядра.</p>
<p>Минусы конструкции:</p>
<ul>
<li>Список последовательный → удалил logical посередине, и нумерация поехала, фрагментация в полный рост</li>
<li>Затёр EBR — потерял всю цепочку дальше; backup-копии нет</li>
<li>Активным может быть только primary; нельзя загрузиться напрямую с logical, нужен посредник</li>
</ul>
<p>Это всё, очевидно, костыль. И именно поэтому на серверах с пятнадцатью разделами под логи, БД, /var и прочее переход на GPT воспринимается как глоток свежего воздуха.</p>
<h2 id="boot-signature-0x1fe0x1ff">Boot Signature (<code>0x1FE–0x1FF</code>)</h2>
<p>Два байта: <code>0x55 0xAA</code>. Если их нет — BIOS считает диск незагрузочным и идёт к следующему. Это самая частая жертва «битого MBR»: код есть, таблица есть, а сигнатуру кто-то затёр. Внешне выглядит как «диск пропал», хотя на самом деле там всего два байта надо вернуть на место.</p>
<h2 id="что-с-этим-делать-на-практике">Что с этим делать на практике</h2>
<ul>
<li><strong>Посмотреть таблицу</strong>: <code>fdisk -l /dev/sda</code>, <code>sfdisk -d /dev/sda</code>, <code>parted /dev/sda print</code></li>
<li><strong>Сырой дамп</strong>: <code>dd if=/dev/sda bs=512 count=1 | hexdump -C</code> — увидишь bootstrap, таблицу разделов и <code>55 AA</code> в самом конце</li>
<li><strong>Бэкап MBR целиком</strong>: <code>dd if=/dev/sda of=mbr.bin bs=512 count=1</code>. Только таблица без бутстрапа: <code>dd if=/dev/sda of=ptable.bin bs=1 skip=446 count=64</code></li>
<li><strong>Восстановить bootloader</strong>: <code>grub-install /dev/sda</code> (Linux), <code>bootrec /fixmbr</code> (Windows)</li>
<li><strong>Сменить тип раздела</strong>: <code>fdisk</code> → <code>t</code> → код. Не форматирует, только меняет байт</li>
<li><strong>Активировать раздел</strong>: <code>fdisk</code> → <code>a</code>. Помним: <code>0x80</code> должен стоять только у одного раздела</li>
</ul>
<h2 id="чем-плох-mbr-и-зачем-родился-gpt">Чем плох MBR (и зачем родился GPT)</h2>
<ul>
<li>Потолок 2 ТиБ — на современных дисках это ровно половина</li>
<li>Только 4 первичных раздела, остальное — через костыль с EBR</li>
<li>Нет контрольных сумм — один битфлип в нужном месте, и таблица «уехала», а ОС об этом не узнает</li>
<li>Нет резервной копии — затёртый сектор 0 равняется диску-«кирпичу» для BIOS</li>
<li>Тип раздела — 1 байт без пространства имён, поэтому коды конфликтуют между ОС и существуют по сути «по договорённости»</li>
</ul>
<p>Подробнее про преемника — в <a href="/posts/what-is-gpt/">Как выглядит GPT</a>
.</p>
<h2 id="тонкие-места-на-которых-легко-споткнуться">Тонкие места, на которых легко споткнуться</h2>
<ul>
<li><strong>CHS vs LBA</strong>: до сих пор встречаются прошивки, которые читают именно CHS. Если поставить туда «битые» значения, BIOS может отказаться грузиться даже при корректном LBA. Утилиты обычно сами пишут <code>0xFFFFFF</code> в CHS, но если правил руками — проверь</li>
<li><strong>Активный раздел</strong>: <code>0x80</code> должен быть <strong>только у одного</strong> раздела. Несколько активных — поведение зависит от загрузчика, и бывает классическое «грузится не то, что ожидал»</li>
<li><strong>MBR на USB</strong>: некоторые BIOS грузятся только если на флешке <code>0x80</code> стоит и тип — <code>0x0C</code>/<code>0x0B</code>. Нарезал через <code>dd</code> ISO-образ, а флешка не грузится — проверь именно это</li>
<li><strong>Hybrid MBR на GPT-дисках</strong>: записи в Protective MBR подменяют на «настоящие», чтобы BIOS-only ОС увидели разделы. Жуткий хак, рассинхрон с GPT ломает всё разом — лучше не использовать, но если унаследовал — знай, что оно есть</li>
<li><strong>NT Disk Signature и клонирование</strong>: после <code>dd</code> диска побайтово обязательно меняй подпись, иначе Windows унесёт один из дисков в offline. На Linux-only стенде проблемы нет, но как только подключишь к Windows — словишь весёлый сюрприз</li>
</ul>
<p>На этом всё. MBR — простая структура из эпохи, когда диски измерялись в мегабайтах, а 4 разделов хватало всем. Сегодня его удел — старые системы и роль Protective MBR на GPT-дисках, но базу знать всё ещё полезно: на боевой железке в 3 часа ночи хочется понимать, что именно ты сейчас правишь в <code>dd</code> и <code>hexdump</code>.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></content:encoded>
    </item><item>
      <title>Как выглядит GPT</title>
      <link>https://jtprog.ru/posts/what-is-gpt/</link>
      <pubDate>Tue, 05 May 2026 20:36:01 +0300</pubDate>
      <dc:creator>jtprogru</dc:creator>
      <guid isPermaLink="true">https://jtprog.ru/posts/what-is-gpt/</guid>
      <category>GPT</category>
      <category>UEFI</category>
      <category>Разметка Диска</category>
      <category>Linux</category>
      <category>Администрирование</category>
      <category domain="category">OS</category>
      <enclosure url="https://jtprog.ru/OS.png" type="image/jpeg" length="0" />
      <media:thumbnail url="https://jtprog.ru/OS.png" /><description><![CDATA[<div><p>Привет, <code>%username%</code>! Когда ты говоришь «разбить диск на разделы», за этим стоит вполне конкретная структура в нулевых секторах накопителя — и в современных машинах это почти всегда GPT, а не его легендарный предок <a href="/posts/what-is-mbr/">MBR</a>
. Снаружи видны только <code>/dev/sda1</code>, <code>/dev/nvme0n1p3</code> и буквы дисков, но если заглянуть внутрь — там аккуратный заголовок, таблица записей по 128 байт и вторая копия в самом хвосте диска «на случай чего».</p>
<p>В этой шпаргалке разберём по байтам, как устроен GPT-диск: какие поля где лежат, зачем нужны Protective MBR и backup-копия, и что со всем этим можно делать руками, когда «оно вдруг не грузится».</p>
<h2 id="что-такое-gpt-и-зачем-он-появился">Что такое GPT и зачем он появился</h2>
<p><strong>GPT (GUID Partition Table)</strong> — современная схема разметки диска, часть спецификации <strong>UEFI</strong>. Пришла на смену <a href="/posts/what-is-mbr/">MBR</a>
, у которого было два бесивших ограничения: максимум 4 первичных раздела и потолок в 2 ТБ из-за 32-битной адресации LBA. GPT сносит оба разом: 64-битная адресация (теоретически — до 9.4 ZB, на практике — сколько у тебя денег на диски) и 128 разделов «из коробки».</p>
<p>Ключевая идея GPT — <strong>избыточность и самопроверка</strong>. Заголовок и таблица разделов хранятся в двух копиях: одна в начале диска, вторая — в самом конце. Всё защищено CRC32. Первая копия побилась? Система спокойно прочитает вторую и пойдёт дальше, как будто ничего и не было.</p>
<h2 id="карта-диска">Карта диска</h2>
<p>Если смотреть «сверху вниз», GPT-диск выглядит так:</p>
<div class="codeblock"><button class="codeblock__copy" type="button" data-copy aria-label="Скопировать" title="Скопировать"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button><pre tabindex="0"><code>LBA 0          : Protective MBR              (1 сектор)
LBA 1          : Primary GPT Header          (1 сектор)
LBA 2..33      : Primary Partition Entries   (32 сектора, 128 записей × 128 байт)
LBA 34..N-34   : Сами разделы (данные)
LBA N-33..N-1  : Backup Partition Entries    (32 сектора)
LBA N          : Backup GPT Header           (последний сектор диска)</code></pre>
</div>
<p><code>N</code> — последний LBA на диске. Размер сектора — обычно 512 байт, на современных «Advanced Format / 4Kn» дисках — 4096. Это важно: вся арифметика смещений считается в секторах, и на 4Kn-диске массив записей займёт уже не 32 сектора, а 8.</p>
<h2 id="protective-mbr-lba-0">Protective MBR (LBA 0)</h2>
<p>Первый сектор — фейковый MBR. Нужен ровно для одного: чтобы старые утилиты, не знающие про GPT, увидели «занятый» диск с одним разделом типа <code>0xEE</code> на весь объём и не предложили его «отформатировать как пустой». По сути это табличка «здесь уже что-то есть, не лезь».</p>
<p>Внутри — стандартная структура MBR, но с единственной осмысленной записью:</p>
<ul>
<li><code>Boot indicator</code>: <code>0x00</code></li>
<li><code>Starting CHS</code>: <code>0x000200</code></li>
<li><code>OS type</code>: <code>0xEE</code> (GPT Protective)</li>
<li><code>Ending CHS</code>: <code>0xFFFFFF</code></li>
<li><code>Starting LBA</code>: <code>0x00000001</code></li>
<li><code>Size in LBA</code>: <code>0xFFFFFFFF</code> или фактический размер диска (если он меньше 2 ТиБ)</li>
</ul>
<h2 id="primary-gpt-header-lba-1">Primary GPT Header (LBA 1)</h2>
<p>Это сердце разметки. Размер — 92 байта (остальное в секторе — нули). Структура:</p>
<table>
  <thead>
      <tr>
          <th style="text-align: right">Offset</th>
          <th style="text-align: right">Size</th>
          <th>Поле</th>
          <th>Описание</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: right">0</td>
          <td style="text-align: right">8</td>
          <td><code>Signature</code></td>
          <td>Магия <code>EFI PART</code> (<code>0x5452415020494645</code>)</td>
      </tr>
      <tr>
          <td style="text-align: right">8</td>
          <td style="text-align: right">4</td>
          <td><code>Revision</code></td>
          <td>Версия, обычно <code>0x00010000</code> (1.0)</td>
      </tr>
      <tr>
          <td style="text-align: right">12</td>
          <td style="text-align: right">4</td>
          <td><code>HeaderSize</code></td>
          <td>Размер заголовка в байтах, обычно 92</td>
      </tr>
      <tr>
          <td style="text-align: right">16</td>
          <td style="text-align: right">4</td>
          <td><code>HeaderCRC32</code></td>
          <td>CRC32 самого заголовка (с обнулённым этим полем при расчёте)</td>
      </tr>
      <tr>
          <td style="text-align: right">20</td>
          <td style="text-align: right">4</td>
          <td><code>Reserved</code></td>
          <td>Должно быть 0</td>
      </tr>
      <tr>
          <td style="text-align: right">24</td>
          <td style="text-align: right">8</td>
          <td><code>MyLBA</code></td>
          <td>LBA, где лежит этот заголовок (1 для primary)</td>
      </tr>
      <tr>
          <td style="text-align: right">32</td>
          <td style="text-align: right">8</td>
          <td><code>AlternateLBA</code></td>
          <td>LBA резервного заголовка (последний сектор)</td>
      </tr>
      <tr>
          <td style="text-align: right">40</td>
          <td style="text-align: right">8</td>
          <td><code>FirstUsableLBA</code></td>
          <td>Первый LBA, доступный для разделов (обычно 34)</td>
      </tr>
      <tr>
          <td style="text-align: right">48</td>
          <td style="text-align: right">8</td>
          <td><code>LastUsableLBA</code></td>
          <td>Последний LBA для разделов (N − 34)</td>
      </tr>
      <tr>
          <td style="text-align: right">56</td>
          <td style="text-align: right">16</td>
          <td><code>DiskGUID</code></td>
          <td>Уникальный идентификатор диска</td>
      </tr>
      <tr>
          <td style="text-align: right">72</td>
          <td style="text-align: right">8</td>
          <td><code>PartitionEntryLBA</code></td>
          <td>LBA, с которого начинается таблица записей (2)</td>
      </tr>
      <tr>
          <td style="text-align: right">80</td>
          <td style="text-align: right">4</td>
          <td><code>NumberOfPartitionEntries</code></td>
          <td>Сколько записей выделено (обычно 128)</td>
      </tr>
      <tr>
          <td style="text-align: right">84</td>
          <td style="text-align: right">4</td>
          <td><code>SizeOfPartitionEntry</code></td>
          <td>Размер одной записи (обычно 128)</td>
      </tr>
      <tr>
          <td style="text-align: right">88</td>
          <td style="text-align: right">4</td>
          <td><code>PartitionEntryArrayCRC32</code></td>
          <td>CRC32 всего массива записей</td>
      </tr>
  </tbody>
</table>
<p>Два CRC — отдельная проверка для самого заголовка и отдельная для массива записей. Если хоть один не сходится — UEFI идёт за резервной копией. Никаких «оно как-то загрузилось со сбойной таблицей» — либо всё чисто, либо берём backup.</p>
<h2 id="partition-entry-запись-о-разделе">Partition Entry (запись о разделе)</h2>
<p>Каждая запись занимает 128 байт. По умолчанию таблица содержит 128 записей → 16 КБ на массив. Это и есть тот самый «лимит в 128 разделов из коробки» — чисто административное ограничение, в спеке его можно поднять.</p>
<table>
  <thead>
      <tr>
          <th style="text-align: right">Offset</th>
          <th style="text-align: right">Size</th>
          <th>Поле</th>
          <th>Описание</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: right">0</td>
          <td style="text-align: right">16</td>
          <td><code>PartitionTypeGUID</code></td>
          <td>Тип раздела (например, EFI System, Linux filesystem, Microsoft Basic Data)</td>
      </tr>
      <tr>
          <td style="text-align: right">16</td>
          <td style="text-align: right">16</td>
          <td><code>UniquePartitionGUID</code></td>
          <td>Уникальный GUID конкретного раздела</td>
      </tr>
      <tr>
          <td style="text-align: right">32</td>
          <td style="text-align: right">8</td>
          <td><code>StartingLBA</code></td>
          <td>Первый LBA раздела</td>
      </tr>
      <tr>
          <td style="text-align: right">40</td>
          <td style="text-align: right">8</td>
          <td><code>EndingLBA</code></td>
          <td>Последний LBA раздела (включительно)</td>
      </tr>
      <tr>
          <td style="text-align: right">48</td>
          <td style="text-align: right">8</td>
          <td><code>Attributes</code></td>
          <td>Битовые атрибуты (см. ниже)</td>
      </tr>
      <tr>
          <td style="text-align: right">56</td>
          <td style="text-align: right">72</td>
          <td><code>PartitionName</code></td>
          <td>UTF-16LE имя раздела, до 36 символов</td>
      </tr>
  </tbody>
</table>
<p>Если запись «пустая» — <code>PartitionTypeGUID</code> равен нулям. Никаких флажков «эта запись валидна» — нули в типе и есть «меня нет».</p>
<h3 id="известные-partitiontypeguid">Известные <code>PartitionTypeGUID</code></h3>
<p>Запоминать их наизусть смысла нет, но в <code>/etc/fstab</code> или в выводе <code>gdisk</code> они мелькают регулярно:</p>
<ul>
<li><code>C12A7328-F81F-11D2-BA4B-00A0C93EC93B</code> — EFI System Partition (ESP), та самая, с которой грузится UEFI</li>
<li><code>0FC63DAF-8483-4772-8E79-3D69D8477DE4</code> — Linux filesystem</li>
<li><code>E6D6D379-F507-44C2-A23C-238F2A3DF928</code> — Linux LVM</li>
<li><code>0657FD6D-A4AB-43C4-84E5-0933C84B4F4F</code> — Linux swap</li>
<li><code>EBD0A0A2-B9E5-4433-87C0-68B6B72699C7</code> — Microsoft Basic Data (под этим GUID живут и NTFS, и exFAT, и FAT32 — ОС определяет уже по сигнатуре ФС)</li>
<li><code>48465300-0000-11AA-AA11-00306543ECAC</code> — Apple HFS+</li>
<li><code>7C3457EF-0000-11AA-AA11-00306543ECAC</code> — Apple APFS</li>
</ul>
<h3 id="атрибуты-биты">Атрибуты (биты)</h3>
<ul>
<li><strong>Bit 0</strong> — <code>Required Partition</code>. Системный раздел платформы, руками не трогаем</li>
<li><strong>Bit 1</strong> — <code>No Block IO Protocol</code>. UEFI не выдаёт обработчик блочного I/O</li>
<li><strong>Bit 2</strong> — <code>Legacy BIOS Bootable</code>. Рудимент для совместимости</li>
<li><strong>Биты 48–63</strong> — определяются конкретным типом раздела. Например, для Microsoft Basic Data: 60 — read-only, 62 — hidden, 63 — no drive letter (тот самый трюк, которым Windows прячет свой recovery-раздел)</li>
</ul>
<h2 id="backup-gpt-хвост-диска">Backup GPT (хвост диска)</h2>
<p>В последних 33 секторах диска лежат <strong>те же</strong> структуры, но в обратном порядке: сначала backup partition entries, потом backup header. У backup header <code>MyLBA</code> указывает на последний сектор, <code>AlternateLBA</code> — обратно на 1.</p>
<p>Это спасает в классической ситуации «кто-то умный сделал <code>dd if=/dev/zero of=/dev/sda bs=512 count=1</code> и пошёл пить чай». Primary улетел, диск превратился в кирпич — но <code>gdisk</code> спокойно увидит backup в конце и предложит восстановить начало. С MBR такой фокус не пройдёт: там единственная копия, и затёртый сектор 0 = всё, грузиться нечем.</p>
<h2 id="что-с-этим-делать-на-практике">Что с этим делать на практике</h2>
<ul>
<li><strong>Посмотреть разметку</strong>: <code>gdisk -l /dev/sda</code>, <code>parted /dev/sda print</code>, <code>lsblk -o NAME,PARTUUID,PARTLABEL,PARTTYPE</code></li>
<li><strong>Сырой дамп заголовка</strong>: <code>dd if=/dev/sda bs=512 count=1 skip=1 | hexdump -C</code> — увидишь <code>EFI PART</code> в первых байтах, дальше поля по таблице выше</li>
<li><strong>PARTUUID vs UUID</strong> — частая путаница. <code>PARTUUID</code> — это <code>UniquePartitionGUID</code> из GPT-записи, живёт в самой разметке. <code>UUID</code> — внутри файловой системы. В <code>/etc/fstab</code> для смонтированных ФС обычно используют <code>UUID</code>, а для raw-разделов или swap иногда удобнее <code>PARTUUID</code> (он не меняется при <code>mkfs</code>)</li>
<li><strong>Восстановить primary из backup</strong>: <code>sgdisk --backup=...</code> / <code>sgdisk --load-backup=...</code>, или интерактивно <code>gdisk</code> → <code>recovery and transformation options</code> → дальше по подсказкам</li>
</ul>
<h2 id="чем-gpt-лучше-mbr">Чем GPT лучше MBR</h2>
<ul>
<li>64-битные LBA → разделы и диски больше 2 ТиБ</li>
<li>128 разделов «из коробки», без всех этих primary/extended/logical костылей</li>
<li>CRC32 на заголовок и таблицу → повреждение детектируется, а не «молча работает с битой таблицей»</li>
<li>Резервная копия в конце диска — спасение в 90% случаев «затёр начало»</li>
<li>У каждого раздела есть свой GUID и читаемое имя. Можно ссылаться по <code>PARTUUID</code>/<code>PARTLABEL</code>, а не по <code>/dev/sdaX</code>, который меняется при перетыкании дисков и переименовании контроллера</li>
<li>Часть UEFI-стека: ESP с типом <code>C12A7328-...</code> — стандартный способ грузиться, без танцев с активным разделом</li>
</ul>
<h2 id="тонкие-места-на-которых-легко-споткнуться">Тонкие места, на которых легко споткнуться</h2>
<ul>
<li><strong>Гибридные MBR</strong> (например, старые Mac с Boot Camp) — это хак: внутри Protective MBR сделали реальные записи, дублирующие GPT. Опасно ровно тем, что рассинхрон между двумя таблицами ломает загрузчик. По возможности — не использовать</li>
<li><strong>4Kn-диски</strong>: ещё раз напомню, что вся арифметика в секторах. На 4Kn таблица записей занимает 8 секторов вместо 32. Утилиты обычно справляются сами, но если правишь руками — проверь размер сектора через <code>blockdev --getss /dev/sda</code></li>
<li><strong>CRC ≠ подпись</strong>: GPT защищает от случайных битфлипов, но не от целенаправленной модификации. Кто угодно может пересчитать CRC после правки — это не криптография</li>
<li><strong><code>sgdisk -Z</code></strong> обнуляет обе копии разом. Если потом окажется, что данные ещё были нужны — восстановления через backup уже нет, придётся идти к <code>testdisk</code> и молиться</li>
<li><strong>Resize и <code>LastUsableLBA</code></strong>: после <code>dd</code>-клона на больший диск backup останется на старом месте, а <code>LastUsableLBA</code> будет указывать в середину нового диска. <code>sgdisk -e /dev/sda</code> переносит backup в конец и обновляет поля</li>
</ul>
<p>На этом всё. Ничего магического в GPT нет — обычная структура данных, которую можно прочитать <code>dd | hexdump</code>. Зато когда снова придётся вытаскивать систему из «оно не грузится», понимать, что именно лежит в первых 33 секторах диска, очень помогает.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></description>
      <content:encoded><![CDATA[<style>/* Inline-CSS, который тема вкладывает в <description> каждого item'а
   RSS-фида (layouts/index.rss.xml). RSS-ридеры (Feedly, Inoreader,
   NetNewsWire) уважают <style> внутри description с переменной
   степенью энтузиазма — это базовый fallback, достаточный для читаемой
   типографики, не более.

   Цвета продублированы из 00-vars.css (light-палитра) — поправь
   синхронно при изменении --bg / --text / --accent / --border. */

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  line-height: 1.6;
  color: #1c1c1f;
  max-width: 720px;
  margin: 0 auto;
  padding: 1em;
}
h1, h2, h3 { line-height: 1.25; margin-top: 1.4em; }
a { color: #c2410c; }
pre {
  background: #1e1e24;
  color: #e8e6df;
  padding: 1em;
  border-radius: 6px;
  overflow-x: auto;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.9em;
}
code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  background: #f3f1ed;
  padding: 0.1em 0.4em;
  border-radius: 4px;
}
pre code { background: transparent; padding: 0; }
blockquote {
  border-left: 3px solid #c2410c;
  padding-left: 1em;
  color: #5b5b62;
  font-style: italic;
  margin-left: 0;
}
img { max-width: 100%; height: auto; border-radius: 6px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #e5e3dc; padding: 6px 10px; text-align: left; }
</style><div><p>Привет, <code>%username%</code>! Когда ты говоришь «разбить диск на разделы», за этим стоит вполне конкретная структура в нулевых секторах накопителя — и в современных машинах это почти всегда GPT, а не его легендарный предок <a href="/posts/what-is-mbr/">MBR</a>
. Снаружи видны только <code>/dev/sda1</code>, <code>/dev/nvme0n1p3</code> и буквы дисков, но если заглянуть внутрь — там аккуратный заголовок, таблица записей по 128 байт и вторая копия в самом хвосте диска «на случай чего».</p>
<p>В этой шпаргалке разберём по байтам, как устроен GPT-диск: какие поля где лежат, зачем нужны Protective MBR и backup-копия, и что со всем этим можно делать руками, когда «оно вдруг не грузится».</p>
<h2 id="что-такое-gpt-и-зачем-он-появился">Что такое GPT и зачем он появился</h2>
<p><strong>GPT (GUID Partition Table)</strong> — современная схема разметки диска, часть спецификации <strong>UEFI</strong>. Пришла на смену <a href="/posts/what-is-mbr/">MBR</a>
, у которого было два бесивших ограничения: максимум 4 первичных раздела и потолок в 2 ТБ из-за 32-битной адресации LBA. GPT сносит оба разом: 64-битная адресация (теоретически — до 9.4 ZB, на практике — сколько у тебя денег на диски) и 128 разделов «из коробки».</p>
<p>Ключевая идея GPT — <strong>избыточность и самопроверка</strong>. Заголовок и таблица разделов хранятся в двух копиях: одна в начале диска, вторая — в самом конце. Всё защищено CRC32. Первая копия побилась? Система спокойно прочитает вторую и пойдёт дальше, как будто ничего и не было.</p>
<h2 id="карта-диска">Карта диска</h2>
<p>Если смотреть «сверху вниз», GPT-диск выглядит так:</p>
<div class="codeblock"><button class="codeblock__copy" type="button" data-copy aria-label="Скопировать" title="Скопировать"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button><pre tabindex="0"><code>LBA 0          : Protective MBR              (1 сектор)
LBA 1          : Primary GPT Header          (1 сектор)
LBA 2..33      : Primary Partition Entries   (32 сектора, 128 записей × 128 байт)
LBA 34..N-34   : Сами разделы (данные)
LBA N-33..N-1  : Backup Partition Entries    (32 сектора)
LBA N          : Backup GPT Header           (последний сектор диска)</code></pre>
</div>
<p><code>N</code> — последний LBA на диске. Размер сектора — обычно 512 байт, на современных «Advanced Format / 4Kn» дисках — 4096. Это важно: вся арифметика смещений считается в секторах, и на 4Kn-диске массив записей займёт уже не 32 сектора, а 8.</p>
<h2 id="protective-mbr-lba-0">Protective MBR (LBA 0)</h2>
<p>Первый сектор — фейковый MBR. Нужен ровно для одного: чтобы старые утилиты, не знающие про GPT, увидели «занятый» диск с одним разделом типа <code>0xEE</code> на весь объём и не предложили его «отформатировать как пустой». По сути это табличка «здесь уже что-то есть, не лезь».</p>
<p>Внутри — стандартная структура MBR, но с единственной осмысленной записью:</p>
<ul>
<li><code>Boot indicator</code>: <code>0x00</code></li>
<li><code>Starting CHS</code>: <code>0x000200</code></li>
<li><code>OS type</code>: <code>0xEE</code> (GPT Protective)</li>
<li><code>Ending CHS</code>: <code>0xFFFFFF</code></li>
<li><code>Starting LBA</code>: <code>0x00000001</code></li>
<li><code>Size in LBA</code>: <code>0xFFFFFFFF</code> или фактический размер диска (если он меньше 2 ТиБ)</li>
</ul>
<h2 id="primary-gpt-header-lba-1">Primary GPT Header (LBA 1)</h2>
<p>Это сердце разметки. Размер — 92 байта (остальное в секторе — нули). Структура:</p>
<table>
  <thead>
      <tr>
          <th style="text-align: right">Offset</th>
          <th style="text-align: right">Size</th>
          <th>Поле</th>
          <th>Описание</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: right">0</td>
          <td style="text-align: right">8</td>
          <td><code>Signature</code></td>
          <td>Магия <code>EFI PART</code> (<code>0x5452415020494645</code>)</td>
      </tr>
      <tr>
          <td style="text-align: right">8</td>
          <td style="text-align: right">4</td>
          <td><code>Revision</code></td>
          <td>Версия, обычно <code>0x00010000</code> (1.0)</td>
      </tr>
      <tr>
          <td style="text-align: right">12</td>
          <td style="text-align: right">4</td>
          <td><code>HeaderSize</code></td>
          <td>Размер заголовка в байтах, обычно 92</td>
      </tr>
      <tr>
          <td style="text-align: right">16</td>
          <td style="text-align: right">4</td>
          <td><code>HeaderCRC32</code></td>
          <td>CRC32 самого заголовка (с обнулённым этим полем при расчёте)</td>
      </tr>
      <tr>
          <td style="text-align: right">20</td>
          <td style="text-align: right">4</td>
          <td><code>Reserved</code></td>
          <td>Должно быть 0</td>
      </tr>
      <tr>
          <td style="text-align: right">24</td>
          <td style="text-align: right">8</td>
          <td><code>MyLBA</code></td>
          <td>LBA, где лежит этот заголовок (1 для primary)</td>
      </tr>
      <tr>
          <td style="text-align: right">32</td>
          <td style="text-align: right">8</td>
          <td><code>AlternateLBA</code></td>
          <td>LBA резервного заголовка (последний сектор)</td>
      </tr>
      <tr>
          <td style="text-align: right">40</td>
          <td style="text-align: right">8</td>
          <td><code>FirstUsableLBA</code></td>
          <td>Первый LBA, доступный для разделов (обычно 34)</td>
      </tr>
      <tr>
          <td style="text-align: right">48</td>
          <td style="text-align: right">8</td>
          <td><code>LastUsableLBA</code></td>
          <td>Последний LBA для разделов (N − 34)</td>
      </tr>
      <tr>
          <td style="text-align: right">56</td>
          <td style="text-align: right">16</td>
          <td><code>DiskGUID</code></td>
          <td>Уникальный идентификатор диска</td>
      </tr>
      <tr>
          <td style="text-align: right">72</td>
          <td style="text-align: right">8</td>
          <td><code>PartitionEntryLBA</code></td>
          <td>LBA, с которого начинается таблица записей (2)</td>
      </tr>
      <tr>
          <td style="text-align: right">80</td>
          <td style="text-align: right">4</td>
          <td><code>NumberOfPartitionEntries</code></td>
          <td>Сколько записей выделено (обычно 128)</td>
      </tr>
      <tr>
          <td style="text-align: right">84</td>
          <td style="text-align: right">4</td>
          <td><code>SizeOfPartitionEntry</code></td>
          <td>Размер одной записи (обычно 128)</td>
      </tr>
      <tr>
          <td style="text-align: right">88</td>
          <td style="text-align: right">4</td>
          <td><code>PartitionEntryArrayCRC32</code></td>
          <td>CRC32 всего массива записей</td>
      </tr>
  </tbody>
</table>
<p>Два CRC — отдельная проверка для самого заголовка и отдельная для массива записей. Если хоть один не сходится — UEFI идёт за резервной копией. Никаких «оно как-то загрузилось со сбойной таблицей» — либо всё чисто, либо берём backup.</p>
<h2 id="partition-entry-запись-о-разделе">Partition Entry (запись о разделе)</h2>
<p>Каждая запись занимает 128 байт. По умолчанию таблица содержит 128 записей → 16 КБ на массив. Это и есть тот самый «лимит в 128 разделов из коробки» — чисто административное ограничение, в спеке его можно поднять.</p>
<table>
  <thead>
      <tr>
          <th style="text-align: right">Offset</th>
          <th style="text-align: right">Size</th>
          <th>Поле</th>
          <th>Описание</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: right">0</td>
          <td style="text-align: right">16</td>
          <td><code>PartitionTypeGUID</code></td>
          <td>Тип раздела (например, EFI System, Linux filesystem, Microsoft Basic Data)</td>
      </tr>
      <tr>
          <td style="text-align: right">16</td>
          <td style="text-align: right">16</td>
          <td><code>UniquePartitionGUID</code></td>
          <td>Уникальный GUID конкретного раздела</td>
      </tr>
      <tr>
          <td style="text-align: right">32</td>
          <td style="text-align: right">8</td>
          <td><code>StartingLBA</code></td>
          <td>Первый LBA раздела</td>
      </tr>
      <tr>
          <td style="text-align: right">40</td>
          <td style="text-align: right">8</td>
          <td><code>EndingLBA</code></td>
          <td>Последний LBA раздела (включительно)</td>
      </tr>
      <tr>
          <td style="text-align: right">48</td>
          <td style="text-align: right">8</td>
          <td><code>Attributes</code></td>
          <td>Битовые атрибуты (см. ниже)</td>
      </tr>
      <tr>
          <td style="text-align: right">56</td>
          <td style="text-align: right">72</td>
          <td><code>PartitionName</code></td>
          <td>UTF-16LE имя раздела, до 36 символов</td>
      </tr>
  </tbody>
</table>
<p>Если запись «пустая» — <code>PartitionTypeGUID</code> равен нулям. Никаких флажков «эта запись валидна» — нули в типе и есть «меня нет».</p>
<h3 id="известные-partitiontypeguid">Известные <code>PartitionTypeGUID</code></h3>
<p>Запоминать их наизусть смысла нет, но в <code>/etc/fstab</code> или в выводе <code>gdisk</code> они мелькают регулярно:</p>
<ul>
<li><code>C12A7328-F81F-11D2-BA4B-00A0C93EC93B</code> — EFI System Partition (ESP), та самая, с которой грузится UEFI</li>
<li><code>0FC63DAF-8483-4772-8E79-3D69D8477DE4</code> — Linux filesystem</li>
<li><code>E6D6D379-F507-44C2-A23C-238F2A3DF928</code> — Linux LVM</li>
<li><code>0657FD6D-A4AB-43C4-84E5-0933C84B4F4F</code> — Linux swap</li>
<li><code>EBD0A0A2-B9E5-4433-87C0-68B6B72699C7</code> — Microsoft Basic Data (под этим GUID живут и NTFS, и exFAT, и FAT32 — ОС определяет уже по сигнатуре ФС)</li>
<li><code>48465300-0000-11AA-AA11-00306543ECAC</code> — Apple HFS+</li>
<li><code>7C3457EF-0000-11AA-AA11-00306543ECAC</code> — Apple APFS</li>
</ul>
<h3 id="атрибуты-биты">Атрибуты (биты)</h3>
<ul>
<li><strong>Bit 0</strong> — <code>Required Partition</code>. Системный раздел платформы, руками не трогаем</li>
<li><strong>Bit 1</strong> — <code>No Block IO Protocol</code>. UEFI не выдаёт обработчик блочного I/O</li>
<li><strong>Bit 2</strong> — <code>Legacy BIOS Bootable</code>. Рудимент для совместимости</li>
<li><strong>Биты 48–63</strong> — определяются конкретным типом раздела. Например, для Microsoft Basic Data: 60 — read-only, 62 — hidden, 63 — no drive letter (тот самый трюк, которым Windows прячет свой recovery-раздел)</li>
</ul>
<h2 id="backup-gpt-хвост-диска">Backup GPT (хвост диска)</h2>
<p>В последних 33 секторах диска лежат <strong>те же</strong> структуры, но в обратном порядке: сначала backup partition entries, потом backup header. У backup header <code>MyLBA</code> указывает на последний сектор, <code>AlternateLBA</code> — обратно на 1.</p>
<p>Это спасает в классической ситуации «кто-то умный сделал <code>dd if=/dev/zero of=/dev/sda bs=512 count=1</code> и пошёл пить чай». Primary улетел, диск превратился в кирпич — но <code>gdisk</code> спокойно увидит backup в конце и предложит восстановить начало. С MBR такой фокус не пройдёт: там единственная копия, и затёртый сектор 0 = всё, грузиться нечем.</p>
<h2 id="что-с-этим-делать-на-практике">Что с этим делать на практике</h2>
<ul>
<li><strong>Посмотреть разметку</strong>: <code>gdisk -l /dev/sda</code>, <code>parted /dev/sda print</code>, <code>lsblk -o NAME,PARTUUID,PARTLABEL,PARTTYPE</code></li>
<li><strong>Сырой дамп заголовка</strong>: <code>dd if=/dev/sda bs=512 count=1 skip=1 | hexdump -C</code> — увидишь <code>EFI PART</code> в первых байтах, дальше поля по таблице выше</li>
<li><strong>PARTUUID vs UUID</strong> — частая путаница. <code>PARTUUID</code> — это <code>UniquePartitionGUID</code> из GPT-записи, живёт в самой разметке. <code>UUID</code> — внутри файловой системы. В <code>/etc/fstab</code> для смонтированных ФС обычно используют <code>UUID</code>, а для raw-разделов или swap иногда удобнее <code>PARTUUID</code> (он не меняется при <code>mkfs</code>)</li>
<li><strong>Восстановить primary из backup</strong>: <code>sgdisk --backup=...</code> / <code>sgdisk --load-backup=...</code>, или интерактивно <code>gdisk</code> → <code>recovery and transformation options</code> → дальше по подсказкам</li>
</ul>
<h2 id="чем-gpt-лучше-mbr">Чем GPT лучше MBR</h2>
<ul>
<li>64-битные LBA → разделы и диски больше 2 ТиБ</li>
<li>128 разделов «из коробки», без всех этих primary/extended/logical костылей</li>
<li>CRC32 на заголовок и таблицу → повреждение детектируется, а не «молча работает с битой таблицей»</li>
<li>Резервная копия в конце диска — спасение в 90% случаев «затёр начало»</li>
<li>У каждого раздела есть свой GUID и читаемое имя. Можно ссылаться по <code>PARTUUID</code>/<code>PARTLABEL</code>, а не по <code>/dev/sdaX</code>, который меняется при перетыкании дисков и переименовании контроллера</li>
<li>Часть UEFI-стека: ESP с типом <code>C12A7328-...</code> — стандартный способ грузиться, без танцев с активным разделом</li>
</ul>
<h2 id="тонкие-места-на-которых-легко-споткнуться">Тонкие места, на которых легко споткнуться</h2>
<ul>
<li><strong>Гибридные MBR</strong> (например, старые Mac с Boot Camp) — это хак: внутри Protective MBR сделали реальные записи, дублирующие GPT. Опасно ровно тем, что рассинхрон между двумя таблицами ломает загрузчик. По возможности — не использовать</li>
<li><strong>4Kn-диски</strong>: ещё раз напомню, что вся арифметика в секторах. На 4Kn таблица записей занимает 8 секторов вместо 32. Утилиты обычно справляются сами, но если правишь руками — проверь размер сектора через <code>blockdev --getss /dev/sda</code></li>
<li><strong>CRC ≠ подпись</strong>: GPT защищает от случайных битфлипов, но не от целенаправленной модификации. Кто угодно может пересчитать CRC после правки — это не криптография</li>
<li><strong><code>sgdisk -Z</code></strong> обнуляет обе копии разом. Если потом окажется, что данные ещё были нужны — восстановления через backup уже нет, придётся идти к <code>testdisk</code> и молиться</li>
<li><strong>Resize и <code>LastUsableLBA</code></strong>: после <code>dd</code>-клона на больший диск backup останется на старом месте, а <code>LastUsableLBA</code> будет указывать в середину нового диска. <code>sgdisk -e /dev/sda</code> переносит backup в конец и обновляет поля</li>
</ul>
<p>На этом всё. Ничего магического в GPT нет — обычная структура данных, которую можно прочитать <code>dd | hexdump</code>. Зато когда снова придётся вытаскивать систему из «оно не грузится», понимать, что именно лежит в первых 33 секторах диска, очень помогает.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></content:encoded>
    </item><item>
      <title>Скорость сгорания бюджета ошибок — что тут не так?</title>
      <link>https://jtprog.ru/posts/burn-rate-is-not-speed/</link>
      <pubDate>Sun, 26 Apr 2026 20:43:02 +0300</pubDate>
      <dc:creator>jtprogru</dc:creator>
      <guid isPermaLink="true">https://jtprog.ru/posts/burn-rate-is-not-speed/</guid>
      <category>SRE</category>
      <category>Error Budget</category>
      <category>Burn Rate</category>
      <category>Надежность</category>
      <category>Мониторинг</category>
      <category domain="category">SRE</category>
      <enclosure url="https://jtprog.ru/devops.png" type="image/jpeg" length="0" />
      <media:thumbnail url="https://jtprog.ru/devops.png" /><description><![CDATA[<div><p>Привет, <code>%username%</code>! В индустрии прижился термин «скорость сгорания бюджета ошибок» (Error Budget Burn Rate). Однако слово «скорость» здесь часто вводит в заблуждение, заставляя мозг искать привычные физические размерности там, где их нет.</p>
<p>Разберемся, почему Burn Rate — это в первую очередь <strong>безразмерный коэффициент</strong>, и как это влияет на наше понимание надежности.</p>
<h2 id="начнем-с-математики">Начнем с математики</h2>
<p>Представим сервис со стабильной нагрузкой в <strong>1000 запросов в минуту</strong> (req/min).</p>
<p>Мы установили <strong>SLO = 99.99%</strong>.</p>
<ol>
<li><strong>Определяем бюджет ошибок:</strong> $\text{Error Budget} = 1 - \text{SLO} = 0.01%$ (или $0.0001$ в долях).</li>
<li><strong>Считаем бюджет в абсолютных величинах:</strong>
<ul>
<li>За 30-дневное окно общее количество запросов составит: $30 \text{ дней} \times 24 \text{ часа} \times 60 \text{ минут} \times 1000 \text{ req/min} = 43,200,000 \text{ запросов}$.</li>
<li>Допустимое количество ошибок: $43,200,000 \times 0.0001 = \mathbf{4320 \text{ ошибок}}$.</li>
</ul>
</li>
</ol>
<p>Это наш исчерпаемый ресурс на 30 дней.</p>
<h3 id="как-можно-тратить-этот-бюджет">Как можно тратить этот бюджет?</h3>
<p>Мы можем распределить эти 4320 ошибок равномерно по всему месяцу. Чтобы понять «нормальную» интенсивность ошибок, разделим бюджет на время:</p>
$$\frac{4320 \text{ ошибок}}{43200 \text{ минут}} = 0.1 \text{ ошибки в минуту}$$<p><em>(Или 1 ошибка каждые 10 минут)</em>.</p>
<p>Это — <strong>Absolute Rate</strong> (абсолютный показатель). У него есть размерность (ошибки/мин). Но это всё еще не Burn Rate.</p>
<h2 id="два-понятия-которые-часто-путают">Два понятия, которые часто путают</h2>
<p>Чтобы не возникало путаницы, важно разделять интенсивность процесса и коэффициент потребления ресурса.</p>
<table>
  <thead>
      <tr>
          <th><strong>Характеристика</strong></th>
          <th><strong>Absolute Error Rate (Абсолютный показатель)</strong></th>
          <th><strong>Burn Rate (Коэффициент сгорания)</strong></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>Что измеряет</strong></td>
          <td>Фактическую интенсивность ошибок «здесь и сейчас».</td>
          <td>Во сколько раз текущее потребление превышает норму.</td>
      </tr>
      <tr>
          <td><strong>Размерность</strong></td>
          <td>Имеет единицы измерения (ошибок/сек, % ошибок).</td>
          <td><strong>Безразмерный множитель</strong> ($1\times, 14.4\times, 50\times$).</td>
      </tr>
      <tr>
          <td><strong>Вопрос</strong></td>
          <td>«Сколько ошибок произошло за последнюю минуту?»</td>
          <td>«Если такая интенсивность сохранится, уложимся ли мы в бюджет?»</td>
      </tr>
      <tr>
          <td><strong>Интерпретация</strong></td>
          <td>Зависит от объема трафика в данный момент.</td>
          <td>Универсальна: $&gt;1$ — бюджет тает слишком быстро, $1$ — норма.</td>
      </tr>
  </tbody>
</table>
<h2 id="почему-скорость--плохое-слово">Почему «скорость» — плохое слово?</h2>
<p>В физике скорость ($v = s/t$) всегда привязана к единицам времени (км/ч, м/с). Когда мы называем Burn Rate скоростью, мы подсознательно ищем время в знаменателе.</p>
<p>На самом деле <strong>Burn Rate — это моментальный снимок соотношения</strong>, а не процесс, растянутый во времени.</p>
<ul>
<li><strong>Burn Rate = 1</strong>: Мы тратим бюджет ровно с той интенсивностью, которая позволит исчерпать его в последнюю секунду периода (при условии, что такая интенсивность сохранится).</li>
<li><strong>Burn Rate = 14.4</strong>: Мы тратим бюджет в 14.4 раза быстрее плана. При такой нагрузке месячный бюджет сгорит всего за 2 дня ($30 / 14.4 \approx 2.08$).</li>
</ul>
<blockquote><p><strong>Главный аргумент:</strong> Burn rate — это не про то, «как быстро» что-то движется, а про то, «во сколько раз» мы отклонились от нормы потребления.</p>
</blockquote><h2 id="формулы">Формулы</h2>
<p>Универсальный расчет коэффициента сгорания:</p>
$$\text{Burn Rate} = \frac{\text{Фактическая доля ошибок (за интервал)}}{\text{Допустимая доля ошибок (по SLO)}}$$<p><em>Пример: Если за последние 5 минут у нас 2% ошибок при SLO 99.9% (допустимо 0.1%):</em></p>
$$\text{Burn Rate} = \frac{0.02}{0.001} = 20\times$$<h2 id="важные-нюансы">Важные нюансы</h2>
<h3 id="1-burn-rate-возможен-только-при-наличии-бюджета">1. Burn Rate возможен только при наличии бюджета</h3>
<p>Безразмерность — необходимое, но не достаточное условие. Для Burn Rate нужен <strong>исчерпаемый ресурс</strong>.</p>
<ul>
<li>Сравнение $\text{Latency p99} / \text{SLA threshold}$ — это просто относительный коэффициент. Он не показывает сгорание ресурса, так как «время ожидания» само по себе не накапливается и не восстанавливается.</li>
<li>Однако, если SLO определен как <em>«% запросов быстрее 200 мс»</em>, то каждый медленный запрос — это «трата» из бюджета ошибок. В этом случае расчет через доли запросов превращает метрику в настоящий Burn Rate.</li>
</ul>
<h3 id="2-скользящее-окно-и-восстановление-бюджета">2. Скользящее окно и «восстановление» бюджета</h3>
<p>В отличие от денег на счету, бюджет ошибок в SRE обычно считается на <strong>скользящем окне</strong> (например, последние 30 дней). Это значит, что бюджет не просто сгорает, но и восстанавливается: когда старые инциденты (31-дневной давности) выходят за пределы окна, ваш доступный бюджет снова увеличивается.</p>
<h3 id="3-проблема-малого-трафика">3. Проблема малого трафика</h3>
<p>Burn Rate плохо работает на сервисах с низкой нагрузкой. Если у вас 1 запрос в час, то одна случайная ошибка даст Burn Rate в тысячи единиц, что приведет к ложному алерту. Для таких систем используют другие подходы (например, агрегацию за очень большие промежутки времени).</p>
<h2 id="практический-вывод">Практический вывод</h2>
<p>Правильная терминология формирует правильное мышление:</p>
<ul>
<li>Не используйте «скорость», если хотите подчеркнуть кратность превышения нормы.</li>
<li>Называйте это <strong>коэффициентом сгорания</strong> или <strong>множителем</strong>.</li>
<li>Помните, что Burn Rate универсален: значение $14.4\times$ одинаково критично и для сервиса с миллионом RPS, и для сервиса с сотней RPS, что делает его идеальной метрикой для настройки умных алертов.</li>
</ul>
<p>А как этот безразмерный множитель превращается в язык разговора с бизнесом про деньги — в статье <a href="/posts/reliability-is-a-conversation/">«Надёжность строится в диалоге с бизнесом»</a>
.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></description>
      <content:encoded><![CDATA[<style>/* Inline-CSS, который тема вкладывает в <description> каждого item'а
   RSS-фида (layouts/index.rss.xml). RSS-ридеры (Feedly, Inoreader,
   NetNewsWire) уважают <style> внутри description с переменной
   степенью энтузиазма — это базовый fallback, достаточный для читаемой
   типографики, не более.

   Цвета продублированы из 00-vars.css (light-палитра) — поправь
   синхронно при изменении --bg / --text / --accent / --border. */

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  line-height: 1.6;
  color: #1c1c1f;
  max-width: 720px;
  margin: 0 auto;
  padding: 1em;
}
h1, h2, h3 { line-height: 1.25; margin-top: 1.4em; }
a { color: #c2410c; }
pre {
  background: #1e1e24;
  color: #e8e6df;
  padding: 1em;
  border-radius: 6px;
  overflow-x: auto;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.9em;
}
code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  background: #f3f1ed;
  padding: 0.1em 0.4em;
  border-radius: 4px;
}
pre code { background: transparent; padding: 0; }
blockquote {
  border-left: 3px solid #c2410c;
  padding-left: 1em;
  color: #5b5b62;
  font-style: italic;
  margin-left: 0;
}
img { max-width: 100%; height: auto; border-radius: 6px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #e5e3dc; padding: 6px 10px; text-align: left; }
</style><div><p>Привет, <code>%username%</code>! В индустрии прижился термин «скорость сгорания бюджета ошибок» (Error Budget Burn Rate). Однако слово «скорость» здесь часто вводит в заблуждение, заставляя мозг искать привычные физические размерности там, где их нет.</p>
<p>Разберемся, почему Burn Rate — это в первую очередь <strong>безразмерный коэффициент</strong>, и как это влияет на наше понимание надежности.</p>
<h2 id="начнем-с-математики">Начнем с математики</h2>
<p>Представим сервис со стабильной нагрузкой в <strong>1000 запросов в минуту</strong> (req/min).</p>
<p>Мы установили <strong>SLO = 99.99%</strong>.</p>
<ol>
<li><strong>Определяем бюджет ошибок:</strong> $\text{Error Budget} = 1 - \text{SLO} = 0.01%$ (или $0.0001$ в долях).</li>
<li><strong>Считаем бюджет в абсолютных величинах:</strong>
<ul>
<li>За 30-дневное окно общее количество запросов составит: $30 \text{ дней} \times 24 \text{ часа} \times 60 \text{ минут} \times 1000 \text{ req/min} = 43,200,000 \text{ запросов}$.</li>
<li>Допустимое количество ошибок: $43,200,000 \times 0.0001 = \mathbf{4320 \text{ ошибок}}$.</li>
</ul>
</li>
</ol>
<p>Это наш исчерпаемый ресурс на 30 дней.</p>
<h3 id="как-можно-тратить-этот-бюджет">Как можно тратить этот бюджет?</h3>
<p>Мы можем распределить эти 4320 ошибок равномерно по всему месяцу. Чтобы понять «нормальную» интенсивность ошибок, разделим бюджет на время:</p>
$$\frac{4320 \text{ ошибок}}{43200 \text{ минут}} = 0.1 \text{ ошибки в минуту}$$<p><em>(Или 1 ошибка каждые 10 минут)</em>.</p>
<p>Это — <strong>Absolute Rate</strong> (абсолютный показатель). У него есть размерность (ошибки/мин). Но это всё еще не Burn Rate.</p>
<h2 id="два-понятия-которые-часто-путают">Два понятия, которые часто путают</h2>
<p>Чтобы не возникало путаницы, важно разделять интенсивность процесса и коэффициент потребления ресурса.</p>
<table>
  <thead>
      <tr>
          <th><strong>Характеристика</strong></th>
          <th><strong>Absolute Error Rate (Абсолютный показатель)</strong></th>
          <th><strong>Burn Rate (Коэффициент сгорания)</strong></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>Что измеряет</strong></td>
          <td>Фактическую интенсивность ошибок «здесь и сейчас».</td>
          <td>Во сколько раз текущее потребление превышает норму.</td>
      </tr>
      <tr>
          <td><strong>Размерность</strong></td>
          <td>Имеет единицы измерения (ошибок/сек, % ошибок).</td>
          <td><strong>Безразмерный множитель</strong> ($1\times, 14.4\times, 50\times$).</td>
      </tr>
      <tr>
          <td><strong>Вопрос</strong></td>
          <td>«Сколько ошибок произошло за последнюю минуту?»</td>
          <td>«Если такая интенсивность сохранится, уложимся ли мы в бюджет?»</td>
      </tr>
      <tr>
          <td><strong>Интерпретация</strong></td>
          <td>Зависит от объема трафика в данный момент.</td>
          <td>Универсальна: $&gt;1$ — бюджет тает слишком быстро, $1$ — норма.</td>
      </tr>
  </tbody>
</table>
<h2 id="почему-скорость--плохое-слово">Почему «скорость» — плохое слово?</h2>
<p>В физике скорость ($v = s/t$) всегда привязана к единицам времени (км/ч, м/с). Когда мы называем Burn Rate скоростью, мы подсознательно ищем время в знаменателе.</p>
<p>На самом деле <strong>Burn Rate — это моментальный снимок соотношения</strong>, а не процесс, растянутый во времени.</p>
<ul>
<li><strong>Burn Rate = 1</strong>: Мы тратим бюджет ровно с той интенсивностью, которая позволит исчерпать его в последнюю секунду периода (при условии, что такая интенсивность сохранится).</li>
<li><strong>Burn Rate = 14.4</strong>: Мы тратим бюджет в 14.4 раза быстрее плана. При такой нагрузке месячный бюджет сгорит всего за 2 дня ($30 / 14.4 \approx 2.08$).</li>
</ul>
<blockquote><p><strong>Главный аргумент:</strong> Burn rate — это не про то, «как быстро» что-то движется, а про то, «во сколько раз» мы отклонились от нормы потребления.</p>
</blockquote><h2 id="формулы">Формулы</h2>
<p>Универсальный расчет коэффициента сгорания:</p>
$$\text{Burn Rate} = \frac{\text{Фактическая доля ошибок (за интервал)}}{\text{Допустимая доля ошибок (по SLO)}}$$<p><em>Пример: Если за последние 5 минут у нас 2% ошибок при SLO 99.9% (допустимо 0.1%):</em></p>
$$\text{Burn Rate} = \frac{0.02}{0.001} = 20\times$$<h2 id="важные-нюансы">Важные нюансы</h2>
<h3 id="1-burn-rate-возможен-только-при-наличии-бюджета">1. Burn Rate возможен только при наличии бюджета</h3>
<p>Безразмерность — необходимое, но не достаточное условие. Для Burn Rate нужен <strong>исчерпаемый ресурс</strong>.</p>
<ul>
<li>Сравнение $\text{Latency p99} / \text{SLA threshold}$ — это просто относительный коэффициент. Он не показывает сгорание ресурса, так как «время ожидания» само по себе не накапливается и не восстанавливается.</li>
<li>Однако, если SLO определен как <em>«% запросов быстрее 200 мс»</em>, то каждый медленный запрос — это «трата» из бюджета ошибок. В этом случае расчет через доли запросов превращает метрику в настоящий Burn Rate.</li>
</ul>
<h3 id="2-скользящее-окно-и-восстановление-бюджета">2. Скользящее окно и «восстановление» бюджета</h3>
<p>В отличие от денег на счету, бюджет ошибок в SRE обычно считается на <strong>скользящем окне</strong> (например, последние 30 дней). Это значит, что бюджет не просто сгорает, но и восстанавливается: когда старые инциденты (31-дневной давности) выходят за пределы окна, ваш доступный бюджет снова увеличивается.</p>
<h3 id="3-проблема-малого-трафика">3. Проблема малого трафика</h3>
<p>Burn Rate плохо работает на сервисах с низкой нагрузкой. Если у вас 1 запрос в час, то одна случайная ошибка даст Burn Rate в тысячи единиц, что приведет к ложному алерту. Для таких систем используют другие подходы (например, агрегацию за очень большие промежутки времени).</p>
<h2 id="практический-вывод">Практический вывод</h2>
<p>Правильная терминология формирует правильное мышление:</p>
<ul>
<li>Не используйте «скорость», если хотите подчеркнуть кратность превышения нормы.</li>
<li>Называйте это <strong>коэффициентом сгорания</strong> или <strong>множителем</strong>.</li>
<li>Помните, что Burn Rate универсален: значение $14.4\times$ одинаково критично и для сервиса с миллионом RPS, и для сервиса с сотней RPS, что делает его идеальной метрикой для настройки умных алертов.</li>
</ul>
<p>А как этот безразмерный множитель превращается в язык разговора с бизнесом про деньги — в статье <a href="/posts/reliability-is-a-conversation/">«Надёжность строится в диалоге с бизнесом»</a>
.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></content:encoded>
    </item><item>
      <title>Как не сойти с ума, чиня прод – практические заметки SRE</title>
      <link>https://jtprog.ru/posts/sre-recipes-summary/</link>
      <pubDate>Sat, 14 Feb 2026 11:29:21 +0300</pubDate>
      <dc:creator>jtprogru</dc:creator>
      <guid isPermaLink="true">https://jtprog.ru/posts/sre-recipes-summary/</guid>
      <category>SRE</category>
      <category>Reliability</category>
      <category>Monitoring</category>
      <category>Graceful-Degradation</category>
      <category>GitOps</category>
      <category>Chaos-Engineering</category>
      <category>DevOps</category>
      <category>Production</category>
      <category>Incident-Management</category>
      <category domain="category">Opinions</category>
      <enclosure url="https://jtprog.ru/opinions.png" type="image/jpeg" length="0" />
      <media:thumbnail url="https://jtprog.ru/opinions.png" /><description><![CDATA[<div><p>Привет, <code>%username%</code>! Иногда кажется, что про надежность уже сказано всё: SLO, error budget, postmortem’ы, Chaos Engineering и вот это всё. Но потом ты открываешь очередной инцидент в проде — и понимаешь, что падает не «абстрактная система», а вполне конкретная «штука», которую ты вчера трогал руками. И вот ты сидишь, смотришь в логи и графики, и главный вопрос звучит примерно так: «А можно было сделать так, чтобы сегодня я спал?»</p>
<p>На написание этой статьи меня сподвигла книга &ldquo;<a href="https://www.litres.ru/book/natalya-savenkova/sre-recepty-vyzhivaniya-v-prodakshene-dlya-inzhenera-po-70232503/" rel="noopener noreferrer" target="_blank">SRE. Рецепты выживания в продакшне для инженера по надежности</a>
&rdquo; за авторством <a href="https://www.litres.ru/author/natalya-savenkova/" rel="noopener noreferrer" target="_blank">Натальи Савенковой</a>
. Эта статья — попытка собрать в одном месте практические тезисы, которые помогают не просто «чинить прод», а строить такую эксплуатацию, где падения становятся реже, а восстановление — проще и спокойнее.</p>
<h2 id="принципы-вместо-героизма">Принципы вместо героизма</h2>
<p>Все начинается не с Grafana и не с Kubernetes, а с принципов команды: что мы считаем нормой, что считаем неприемлемым и как вообще привыкли работать.</p>
<ul>
<li>Надежность <strong>начинается</strong> с того, как команда договаривается работать: что считаем ок, а что считаем нарушением здравого смысла.</li>
<li>Если надежность сервиса нельзя управлять, измерять и регулировать — у тебя нет сервиса, у тебя набор случайно работающих скриптов.</li>
<li>Принцип «если страшно — делай чаще» отлично работает и для процедур (релизы, переключения, учения) — чем больше повторов, тем ближе автомация и тем меньше шансов, что «руки дрогнут».</li>
</ul>
<p>Характерная мысль: надежность — это не героические ночные починки, а заранее сформулированные правила, по которым команда принимает решения, особенно неприятные.</p>
<h2 id="иммунитет-системы-dis-gd-fallback">Иммунитет системы: DIS, GD, fallback</h2>
<p>Крутая метафора — иммунитет продукта: система рождается с каким‑то базовым «здоровьем», но дальше его нужно постоянно тренировать учебными встрясками и интеграцией опыта прошлых инцидентов.</p>
<ul>
<li>Всё, что с системой случается, должно попадать в общую память: DIS (<a href="/2026-01-30-digital-immune-system/">Digital Immune System</a>
, назови как хочешь) — не украшение, а база для эволюции.</li>
<li>Если смежный сервис начал чаще отвечать ошибками — это не только про ретраи, это триггер к запуску graceful degradation (GD) или fallback именно на этом участке.</li>
<li>Exponential backoff — не про «красивые алгоритмы», а про то, чтобы ретраи не продлевали агонию инцидента, а давали системе шанс «встать с колен».</li>
</ul>
<p>Идеальная связка: DIS аккумулирует историю ошибок, GD даёт «план Б», fallback закрывает совсем плохие сценарии, чтобы пользователю не прилетал унылый «502 Bad Gateway».</p>
<h2 id="graceful-degradation-всегда-отвечать-но-не-всегда-всем">Graceful Degradation: всегда отвечать, но не всегда всем</h2>
<p>Если в голове GD = «мы иногда отваливаемся по лёгкому», то ничего хорошего не выйдет.</p>
<ul>
<li>Правильная GD — это когда сервис <strong>всегда отвечает</strong>, но не всегда полной функциональностью.</li>
<li>Нужны <strong>уровни</strong> деградации: от выключения «сопутствующих товаров» до отдачи статики «техработы, вот наши лучшие предложения».</li>
<li>Кэширование и заглушки — такие же инструменты GD: лучше показать «Топ‑5» или дефолтный вариант, чем ничего.</li>
</ul>
<p>Очень важный момент — GD надо согласовывать с продактом заранее: какие блоки отключаем сначала, какие — потом, что для бизнеса критично, а что можно отрубить без слёз.</p>
<h2 id="fallback-когда-даже-gd-не-спасает">Fallback: когда даже GD не спасает</h2>
<p>Fallback — это не «ещё одна страница с ошибкой», это реальный последний шанс дать пользователю хоть какую‑то ценность.</p>
<ul>
<li>Fallback лучше любого 5xx: даже тетрис или одна страница с лучшим товаром лучше, чем пустой 502.</li>
<li>Важно мониторить, <strong>как часто</strong> показывается fallback: это отдельный сигнал о классах запросов, которые система не может обработать корректно.</li>
<li>Fallback и GD — не взаимоисключающие штуки: GD работает «по пути» запроса, fallback — когда пути уже не осталось.</li>
</ul>
<p>По сути, GD и fallback — это про уважение к пользователю: либо ты честно пытаешься дать хотя бы что‑то, либо молча падаешь в 5xx и надеешься, что он когда-нибудь вернётся.</p>
<h2 id="мониторинг-который-действительно-помогает">Мониторинг, который действительно помогает</h2>
<p>Мониторинг «чтобы был» только создает иллюзию контроля. Полезный мониторинг строится из нескольких идей.</p>
<h3 id="абсолютные-значения-и-тренды">Абсолютные значения и тренды</h3>
<ul>
<li>Контролируй трафик по <strong>абсолютным значениям</strong> сверху и снизу — чтобы видеть и внезапные всплески, и подозрительные провалы.</li>
<li>Используй <strong>тренды</strong>, чтобы ловить аномалии в поведении (типичное для дня недели, часа и т.д.), но помни: плавные изменения тренд может спокойно «проглотить».</li>
<li>Рабочий рецепт: совмещать мониторинг по абсолюту и по тренду, а не выбирать что‑то одно.</li>
</ul>
<h3 id="среднее-minmax-и-перцентили">Среднее, min/max и перцентили</h3>
<ul>
<li>Среднее без min/max — это классика «средней температуры по больнице».</li>
<li>Важно отслеживать <strong>min/max</strong> и перцентили (p90, p95, p99), потому что именно они часто первыми намекают на будущий сбой.</li>
<li>Если по агрегатам всё красиво, а один хост уже умирает — без min/max ты про это узнаешь только из инцидента.</li>
</ul>
<h3 id="молчаливый-мониторинг-и-резервный-мониторинг">Молчаливый мониторинг и резервный мониторинг</h3>
<ul>
<li>«Если мониторинг не пишет о проблемах — возможно, он просто не работает» — очень неприятная правда.</li>
<li>Резервный мониторинг на других технологиях (хоть отдельная Grafana+VM на retention 2 дня) — это не паранойя, а нормальная страховка.</li>
<li>Мониторинг должен быть не только внутренним, но и внешним: проверять доступность глазами пользователя из важных локаций.</li>
</ul>
<p>По хорошему, у тебя должны мониториться: сами сервисы, их зависимости, мониторинг, срок годности сертификатов/лицензий и <a href="/posts/wat-monitoring/">всё, что когда‑нибудь «протухнет»</a>
.</p>
<h2 id="нагрузочное-тестирование-и-правильные-учения">Нагрузочное тестирование и «правильные» учения</h2>
<p>Учения и нагрузка — самая недооценённая часть надёжности: все про них говорят, но мало кто делает это регулярно и по уму.</p>
<ul>
<li>Учения без подготовки — must‑have: либо автоматика работает, либо в ходе учений становится ясно, что её нет и её надо сделать.</li>
<li>Сценарии учений надо <strong>рандомизировать</strong> и пересматривать, иначе это будет не Chaos Engineering, а театральная постановка «все всё знают заранее».</li>
<li>Нагрузочные тесты с одинаковыми результатами — тревожный знак: значит, тесты устарели или слишком аккуратно обходят острые углы.</li>
</ul>
<p>Система с «отличными» нагрузочными тестами, которые никогда ничего не ломают, обычно падает от первого же реального всплеска.</p>
<h2 id="failover-расселение-сервисов-и-слон-с-моськой">Failover, расселение сервисов и «слон с моськой»</h2>
<p>Любая история про отказоустойчивость со временем приходит к трем вопросам: где у тебя точки отказа, кто с кем соседствует и как ты это всё переключаешь.</p>
<ul>
<li>Failover <strong>дороже</strong>, чем кажется: нужен не только второй инстанс, но и координатор, логика консенсуса и вся инфраструктура вокруг.</li>
<li>Не сажай «слона и моську» в одну базу: не смешивай критичные сервисы с теми, у кого неконтролируемый трафик (сбор аналитики, события с фронта и т.п.).</li>
<li>Микросервисный подход с явной разметкой по критичности: выделенные ресурсы для разных классов сервисов.</li>
</ul>
<p>Критичный сервис плюс «шумный» некритичный — идеальный рецепт для самодельной DDoS‑атаки на самого себя.</p>
<h2 id="capacity-management-и-finops-сколько-мощности-тебе-реально-нужно">Capacity Management и FinOps: сколько мощности тебе реально нужно</h2>
<p>«Просто добавить ресурсов» — худшая из возможных стратегий, особенно в облаке.</p>
<ul>
<li>Любой запас мощности должен быть осмысленным: под какой сценарий он нужен, на какой срок и при каких ограничениях по бюджету.</li>
<li>Capacity‑планирование нужно делать по <strong>CUJ</strong> (Critical User Journey): самые важные клиентские маршруты должны иметь понятный запас.</li>
<li>Это не только про железо, но и про архитектуру: где узкие места, какой компонент ограничивает пропускную способность и как быстро ты можешь масштабироваться.</li>
</ul>
<p>По сути, это чистый FinOps: договариваешься с бизнесом, какой трафик обязан выдерживать, а какой — нет, и уже под это строишь схему резервирования и бюджетов.</p>
<h2 id="gitops-версии-и-самодостаточный-релиз">GitOps, версии и «самодостаточный релиз»</h2>
<p>Очень много боли в инцидентах рождается не из багов в коде, а из конфигов и «плавающих» зависимостей.</p>
<ul>
<li>Всё, что имеет ценность и выглядит как файл, должно жить в VCS: скрипты, конфиги, инфраструктурные артефакты.</li>
<li>GitOps‑подход: релиз — это не только «бинарь» или образ, но и конфиги, секреты, схемы, миграции, всё с версионированием.</li>
<li>Самодостаточный релиз должен гарантированно уметь работать сам по себе и уметь откатываться вместе с конфигами и внешними зависимостями.</li>
</ul>
<p>Отдельная боль — изменения «на проде руками без бэкапа»: перед любым вмешательством в БД или конфиги должен быть свежий бэкап или хотя бы сохранённая копия файла с суффиксом даты.</p>
<h2 id="фичатогглы-canary-whitelistblacklist">Фичатогглы, canary, whitelist/blacklist</h2>
<p>Любая новая фича потенциально ломает прод — вопрос только в том, насколько контролируемо.</p>
<ul>
<li>Фичи надо выкатывать <strong>выключенными</strong> и включать через конфиги/рубильники: это даёт быстрый roll‑back без пересборки.</li>
<li>Whitelist/blacklist помогают управлять долей трафика: сначала включаешь фичу на сегмент, потом расширяешь, потом можешь точечно отключать.</li>
<li>В стабилизированном состоянии прод должен иметь одну версию сервиса: параллельные версии «Ok» только на время A/B и canary, а не «так и живём».</li>
</ul>
<p>Фичи, которые нельзя быстро и адресно отключить — это не фичи, а долговые ямы для дежурных.</p>
<h2 id="процессы-инструкции-и-людочка-на-ресепшене">Процессы, инструкции и «Людочка на ресепшене»</h2>
<p>Хорошие процессы — это не бюрократия, а защита от хаоса в самый неподходящий момент.</p>
<ul>
<li>Стандартизированные процессы с чёткими, зафиксированными шагами — лучший фундамент для будущей автоматизации.</li>
<li>Инструкция должна быть такова, чтобы её могла выполнить «Людочка» или условная секретарша: копировать команды, открывать ссылки и получать предсказуемый результат.</li>
<li>Плановые работы должны делаться <strong>по регламенту</strong>, без «давай заодно тут поправим, пока уже всё отключили».</li>
</ul>
<p>Сюда же — план Б на каждое нетипичное вмешательство: если «всё пойдёт не так», должен быть понятный сценарий возврата в состояние «как было».</p>
<h2 id="люди-психология-и-работа-в-стрессе">Люди, психология и работа в стрессе</h2>
<p>Любой серьёзный инцидент — это ещё и психологическая нагрузка, и к ней тоже надо готовиться.</p>
<ul>
<li>У каждого свой «деструктор» в стрессе: кто‑то начинает хаотично нажимать всё подряд, кто‑то «замерзает», кто‑то исчезает из коммуникации.</li>
<li>Личный чек‑лист дежурного («подышать», «записать идеи действий», «пройтись», «открыть инструкцию по оповещению») — очень мощный инструмент.</li>
<li>Интуицию стоит слушать: если внутри зудит «сделать бэкап» или «снять трафик» — лучше перебдеть, чем недобдеть.</li>
</ul>
<p>Отдельная история — групповые дежурства: если «ответственность на всех», то по факту не отвечает никто, поэтому нужны конкретные фамилии в графике.</p>
<h2 id="коммуникация-смежники-продакты-пользователи-твоих-инструментов">Коммуникация: смежники, продакты, пользователи твоих инструментов</h2>
<p>Надёжность ломается не только в коде, но и на стыках людей и команд.</p>
<ul>
<li>Если сервис <em>А</em> положил сервис <em>Б</em> десятикратным ростом запросов — виноваты оба: <em>А</em> не ограничил нагрузку, <em>Б</em> не предусмотрел верхнюю границу того, что он может переварить.</li>
<li>Разборы инцидентов должны быть <strong>публичными</strong>: любой участник должен иметь возможность задать вопрос, особенно из смежных команд.</li>
<li>С теми, кто пользуется твоими панелями и инструментами, надо регулярно говорить и смотреть «их глазами» на интерфейс — очень часто это приносит внезапные открытия, потому что очевидное для тебя — неочевидно для других.</li>
</ul>
<p>Плюс базовая дисциплина: общий календарь маркетинговых запусков и регламентных работ, понятные термины и общий словарь.</p>
<h2 id="безопасность-как-часть-надёжности">Безопасность как часть надёжности</h2>
<p>Про ИБ легко забыть, пока не прилетело.</p>
<ul>
<li>Требования информационной безопасности — это не внешняя бюрократия, а часть надёжности и доступности.</li>
<li>Чем раньше ты начнёшь приводить сервис к ИБ‑гайдам, тем меньше будет боли потом: всё равно придётся, но лучше не в режиме горящей пятой точки.</li>
<li>Debug‑режимы, скрытые параметры, хардкод в фронтенде, незащищённые «магические» урлы — всё это при первом же fuzzing&rsquo;е превращается в инцидент.</li>
</ul>
<p>ИБ — просто ещё один класс рисков для надёжности, и игнорировать его — то же самое, что не мониторить диск или БД.</p>
<h2 id="несколько-практических-выводов">Несколько практических выводов</h2>
<p>Соберём самое важное в виде коротких тезисов — то, что полезно прямо взять и примерить к своему проекту:</p>
<ul>
<li><strong>Формализуй принципы команды.</strong> Пойми, что для вас нормально, а что — нет, и как вы принимаете решения в проде.</li>
<li><strong>Строй иммунитет системы.</strong> Собирай данные об инцидентах, запускай учения, внедряй DIS, GD и fallback как связанный комплекс.</li>
<li><strong>Наведи порядок в мониторинге.</strong> Абсолютные значения + тренды, min/max + перцентили, резервный мониторинг и внешние проверки.</li>
<li><strong>Инвестируй в процесс.</strong> Стандартизированные инструкции, регламенты, планы отката, регулярные учения по релизам и rollback’ам.</li>
<li><strong>Живи через GitOps и версии.</strong> Всё важное — в VCS, релиз самодостаточен, откат — быстрый и предсказуемый.</li>
<li><strong>Не забывай про людей.</strong> Психология дежурств, личные чек‑листы, явные дежурные, нормальная коммуникация с продактами и смежниками.</li>
</ul>
<p>Если всё это собрать вместе, то «чинить прод» перестаёт быть вечным героическим подвигом и превращается в спокойную инженерную работу. А это, кажется, ровно то, к чему хочется прийти.</p>
<p>PS: Читать книгу &ldquo;<a href="https://www.litres.ru/book/natalya-savenkova/sre-recepty-vyzhivaniya-v-prodakshene-dlya-inzhenera-po-70232503/" rel="noopener noreferrer" target="_blank">SRE. Рецепты выживания в продакшне для инженера по надежности</a>
&rdquo; за авторством <a href="https://www.litres.ru/author/natalya-savenkova/" rel="noopener noreferrer" target="_blank">Натальи Савенковой</a>
 было и смешно и грустно одновременно. Но главная ценность лично для меня — я увидел, что я не одинок в своих выводах!</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></description>
      <content:encoded><![CDATA[<style>/* Inline-CSS, который тема вкладывает в <description> каждого item'а
   RSS-фида (layouts/index.rss.xml). RSS-ридеры (Feedly, Inoreader,
   NetNewsWire) уважают <style> внутри description с переменной
   степенью энтузиазма — это базовый fallback, достаточный для читаемой
   типографики, не более.

   Цвета продублированы из 00-vars.css (light-палитра) — поправь
   синхронно при изменении --bg / --text / --accent / --border. */

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  line-height: 1.6;
  color: #1c1c1f;
  max-width: 720px;
  margin: 0 auto;
  padding: 1em;
}
h1, h2, h3 { line-height: 1.25; margin-top: 1.4em; }
a { color: #c2410c; }
pre {
  background: #1e1e24;
  color: #e8e6df;
  padding: 1em;
  border-radius: 6px;
  overflow-x: auto;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.9em;
}
code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  background: #f3f1ed;
  padding: 0.1em 0.4em;
  border-radius: 4px;
}
pre code { background: transparent; padding: 0; }
blockquote {
  border-left: 3px solid #c2410c;
  padding-left: 1em;
  color: #5b5b62;
  font-style: italic;
  margin-left: 0;
}
img { max-width: 100%; height: auto; border-radius: 6px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #e5e3dc; padding: 6px 10px; text-align: left; }
</style><div><p>Привет, <code>%username%</code>! Иногда кажется, что про надежность уже сказано всё: SLO, error budget, postmortem’ы, Chaos Engineering и вот это всё. Но потом ты открываешь очередной инцидент в проде — и понимаешь, что падает не «абстрактная система», а вполне конкретная «штука», которую ты вчера трогал руками. И вот ты сидишь, смотришь в логи и графики, и главный вопрос звучит примерно так: «А можно было сделать так, чтобы сегодня я спал?»</p>
<p>На написание этой статьи меня сподвигла книга &ldquo;<a href="https://www.litres.ru/book/natalya-savenkova/sre-recepty-vyzhivaniya-v-prodakshene-dlya-inzhenera-po-70232503/" rel="noopener noreferrer" target="_blank">SRE. Рецепты выживания в продакшне для инженера по надежности</a>
&rdquo; за авторством <a href="https://www.litres.ru/author/natalya-savenkova/" rel="noopener noreferrer" target="_blank">Натальи Савенковой</a>
. Эта статья — попытка собрать в одном месте практические тезисы, которые помогают не просто «чинить прод», а строить такую эксплуатацию, где падения становятся реже, а восстановление — проще и спокойнее.</p>
<h2 id="принципы-вместо-героизма">Принципы вместо героизма</h2>
<p>Все начинается не с Grafana и не с Kubernetes, а с принципов команды: что мы считаем нормой, что считаем неприемлемым и как вообще привыкли работать.</p>
<ul>
<li>Надежность <strong>начинается</strong> с того, как команда договаривается работать: что считаем ок, а что считаем нарушением здравого смысла.</li>
<li>Если надежность сервиса нельзя управлять, измерять и регулировать — у тебя нет сервиса, у тебя набор случайно работающих скриптов.</li>
<li>Принцип «если страшно — делай чаще» отлично работает и для процедур (релизы, переключения, учения) — чем больше повторов, тем ближе автомация и тем меньше шансов, что «руки дрогнут».</li>
</ul>
<p>Характерная мысль: надежность — это не героические ночные починки, а заранее сформулированные правила, по которым команда принимает решения, особенно неприятные.</p>
<h2 id="иммунитет-системы-dis-gd-fallback">Иммунитет системы: DIS, GD, fallback</h2>
<p>Крутая метафора — иммунитет продукта: система рождается с каким‑то базовым «здоровьем», но дальше его нужно постоянно тренировать учебными встрясками и интеграцией опыта прошлых инцидентов.</p>
<ul>
<li>Всё, что с системой случается, должно попадать в общую память: DIS (<a href="/2026-01-30-digital-immune-system/">Digital Immune System</a>
, назови как хочешь) — не украшение, а база для эволюции.</li>
<li>Если смежный сервис начал чаще отвечать ошибками — это не только про ретраи, это триггер к запуску graceful degradation (GD) или fallback именно на этом участке.</li>
<li>Exponential backoff — не про «красивые алгоритмы», а про то, чтобы ретраи не продлевали агонию инцидента, а давали системе шанс «встать с колен».</li>
</ul>
<p>Идеальная связка: DIS аккумулирует историю ошибок, GD даёт «план Б», fallback закрывает совсем плохие сценарии, чтобы пользователю не прилетал унылый «502 Bad Gateway».</p>
<h2 id="graceful-degradation-всегда-отвечать-но-не-всегда-всем">Graceful Degradation: всегда отвечать, но не всегда всем</h2>
<p>Если в голове GD = «мы иногда отваливаемся по лёгкому», то ничего хорошего не выйдет.</p>
<ul>
<li>Правильная GD — это когда сервис <strong>всегда отвечает</strong>, но не всегда полной функциональностью.</li>
<li>Нужны <strong>уровни</strong> деградации: от выключения «сопутствующих товаров» до отдачи статики «техработы, вот наши лучшие предложения».</li>
<li>Кэширование и заглушки — такие же инструменты GD: лучше показать «Топ‑5» или дефолтный вариант, чем ничего.</li>
</ul>
<p>Очень важный момент — GD надо согласовывать с продактом заранее: какие блоки отключаем сначала, какие — потом, что для бизнеса критично, а что можно отрубить без слёз.</p>
<h2 id="fallback-когда-даже-gd-не-спасает">Fallback: когда даже GD не спасает</h2>
<p>Fallback — это не «ещё одна страница с ошибкой», это реальный последний шанс дать пользователю хоть какую‑то ценность.</p>
<ul>
<li>Fallback лучше любого 5xx: даже тетрис или одна страница с лучшим товаром лучше, чем пустой 502.</li>
<li>Важно мониторить, <strong>как часто</strong> показывается fallback: это отдельный сигнал о классах запросов, которые система не может обработать корректно.</li>
<li>Fallback и GD — не взаимоисключающие штуки: GD работает «по пути» запроса, fallback — когда пути уже не осталось.</li>
</ul>
<p>По сути, GD и fallback — это про уважение к пользователю: либо ты честно пытаешься дать хотя бы что‑то, либо молча падаешь в 5xx и надеешься, что он когда-нибудь вернётся.</p>
<h2 id="мониторинг-который-действительно-помогает">Мониторинг, который действительно помогает</h2>
<p>Мониторинг «чтобы был» только создает иллюзию контроля. Полезный мониторинг строится из нескольких идей.</p>
<h3 id="абсолютные-значения-и-тренды">Абсолютные значения и тренды</h3>
<ul>
<li>Контролируй трафик по <strong>абсолютным значениям</strong> сверху и снизу — чтобы видеть и внезапные всплески, и подозрительные провалы.</li>
<li>Используй <strong>тренды</strong>, чтобы ловить аномалии в поведении (типичное для дня недели, часа и т.д.), но помни: плавные изменения тренд может спокойно «проглотить».</li>
<li>Рабочий рецепт: совмещать мониторинг по абсолюту и по тренду, а не выбирать что‑то одно.</li>
</ul>
<h3 id="среднее-minmax-и-перцентили">Среднее, min/max и перцентили</h3>
<ul>
<li>Среднее без min/max — это классика «средней температуры по больнице».</li>
<li>Важно отслеживать <strong>min/max</strong> и перцентили (p90, p95, p99), потому что именно они часто первыми намекают на будущий сбой.</li>
<li>Если по агрегатам всё красиво, а один хост уже умирает — без min/max ты про это узнаешь только из инцидента.</li>
</ul>
<h3 id="молчаливый-мониторинг-и-резервный-мониторинг">Молчаливый мониторинг и резервный мониторинг</h3>
<ul>
<li>«Если мониторинг не пишет о проблемах — возможно, он просто не работает» — очень неприятная правда.</li>
<li>Резервный мониторинг на других технологиях (хоть отдельная Grafana+VM на retention 2 дня) — это не паранойя, а нормальная страховка.</li>
<li>Мониторинг должен быть не только внутренним, но и внешним: проверять доступность глазами пользователя из важных локаций.</li>
</ul>
<p>По хорошему, у тебя должны мониториться: сами сервисы, их зависимости, мониторинг, срок годности сертификатов/лицензий и <a href="/posts/wat-monitoring/">всё, что когда‑нибудь «протухнет»</a>
.</p>
<h2 id="нагрузочное-тестирование-и-правильные-учения">Нагрузочное тестирование и «правильные» учения</h2>
<p>Учения и нагрузка — самая недооценённая часть надёжности: все про них говорят, но мало кто делает это регулярно и по уму.</p>
<ul>
<li>Учения без подготовки — must‑have: либо автоматика работает, либо в ходе учений становится ясно, что её нет и её надо сделать.</li>
<li>Сценарии учений надо <strong>рандомизировать</strong> и пересматривать, иначе это будет не Chaos Engineering, а театральная постановка «все всё знают заранее».</li>
<li>Нагрузочные тесты с одинаковыми результатами — тревожный знак: значит, тесты устарели или слишком аккуратно обходят острые углы.</li>
</ul>
<p>Система с «отличными» нагрузочными тестами, которые никогда ничего не ломают, обычно падает от первого же реального всплеска.</p>
<h2 id="failover-расселение-сервисов-и-слон-с-моськой">Failover, расселение сервисов и «слон с моськой»</h2>
<p>Любая история про отказоустойчивость со временем приходит к трем вопросам: где у тебя точки отказа, кто с кем соседствует и как ты это всё переключаешь.</p>
<ul>
<li>Failover <strong>дороже</strong>, чем кажется: нужен не только второй инстанс, но и координатор, логика консенсуса и вся инфраструктура вокруг.</li>
<li>Не сажай «слона и моську» в одну базу: не смешивай критичные сервисы с теми, у кого неконтролируемый трафик (сбор аналитики, события с фронта и т.п.).</li>
<li>Микросервисный подход с явной разметкой по критичности: выделенные ресурсы для разных классов сервисов.</li>
</ul>
<p>Критичный сервис плюс «шумный» некритичный — идеальный рецепт для самодельной DDoS‑атаки на самого себя.</p>
<h2 id="capacity-management-и-finops-сколько-мощности-тебе-реально-нужно">Capacity Management и FinOps: сколько мощности тебе реально нужно</h2>
<p>«Просто добавить ресурсов» — худшая из возможных стратегий, особенно в облаке.</p>
<ul>
<li>Любой запас мощности должен быть осмысленным: под какой сценарий он нужен, на какой срок и при каких ограничениях по бюджету.</li>
<li>Capacity‑планирование нужно делать по <strong>CUJ</strong> (Critical User Journey): самые важные клиентские маршруты должны иметь понятный запас.</li>
<li>Это не только про железо, но и про архитектуру: где узкие места, какой компонент ограничивает пропускную способность и как быстро ты можешь масштабироваться.</li>
</ul>
<p>По сути, это чистый FinOps: договариваешься с бизнесом, какой трафик обязан выдерживать, а какой — нет, и уже под это строишь схему резервирования и бюджетов.</p>
<h2 id="gitops-версии-и-самодостаточный-релиз">GitOps, версии и «самодостаточный релиз»</h2>
<p>Очень много боли в инцидентах рождается не из багов в коде, а из конфигов и «плавающих» зависимостей.</p>
<ul>
<li>Всё, что имеет ценность и выглядит как файл, должно жить в VCS: скрипты, конфиги, инфраструктурные артефакты.</li>
<li>GitOps‑подход: релиз — это не только «бинарь» или образ, но и конфиги, секреты, схемы, миграции, всё с версионированием.</li>
<li>Самодостаточный релиз должен гарантированно уметь работать сам по себе и уметь откатываться вместе с конфигами и внешними зависимостями.</li>
</ul>
<p>Отдельная боль — изменения «на проде руками без бэкапа»: перед любым вмешательством в БД или конфиги должен быть свежий бэкап или хотя бы сохранённая копия файла с суффиксом даты.</p>
<h2 id="фичатогглы-canary-whitelistblacklist">Фичатогглы, canary, whitelist/blacklist</h2>
<p>Любая новая фича потенциально ломает прод — вопрос только в том, насколько контролируемо.</p>
<ul>
<li>Фичи надо выкатывать <strong>выключенными</strong> и включать через конфиги/рубильники: это даёт быстрый roll‑back без пересборки.</li>
<li>Whitelist/blacklist помогают управлять долей трафика: сначала включаешь фичу на сегмент, потом расширяешь, потом можешь точечно отключать.</li>
<li>В стабилизированном состоянии прод должен иметь одну версию сервиса: параллельные версии «Ok» только на время A/B и canary, а не «так и живём».</li>
</ul>
<p>Фичи, которые нельзя быстро и адресно отключить — это не фичи, а долговые ямы для дежурных.</p>
<h2 id="процессы-инструкции-и-людочка-на-ресепшене">Процессы, инструкции и «Людочка на ресепшене»</h2>
<p>Хорошие процессы — это не бюрократия, а защита от хаоса в самый неподходящий момент.</p>
<ul>
<li>Стандартизированные процессы с чёткими, зафиксированными шагами — лучший фундамент для будущей автоматизации.</li>
<li>Инструкция должна быть такова, чтобы её могла выполнить «Людочка» или условная секретарша: копировать команды, открывать ссылки и получать предсказуемый результат.</li>
<li>Плановые работы должны делаться <strong>по регламенту</strong>, без «давай заодно тут поправим, пока уже всё отключили».</li>
</ul>
<p>Сюда же — план Б на каждое нетипичное вмешательство: если «всё пойдёт не так», должен быть понятный сценарий возврата в состояние «как было».</p>
<h2 id="люди-психология-и-работа-в-стрессе">Люди, психология и работа в стрессе</h2>
<p>Любой серьёзный инцидент — это ещё и психологическая нагрузка, и к ней тоже надо готовиться.</p>
<ul>
<li>У каждого свой «деструктор» в стрессе: кто‑то начинает хаотично нажимать всё подряд, кто‑то «замерзает», кто‑то исчезает из коммуникации.</li>
<li>Личный чек‑лист дежурного («подышать», «записать идеи действий», «пройтись», «открыть инструкцию по оповещению») — очень мощный инструмент.</li>
<li>Интуицию стоит слушать: если внутри зудит «сделать бэкап» или «снять трафик» — лучше перебдеть, чем недобдеть.</li>
</ul>
<p>Отдельная история — групповые дежурства: если «ответственность на всех», то по факту не отвечает никто, поэтому нужны конкретные фамилии в графике.</p>
<h2 id="коммуникация-смежники-продакты-пользователи-твоих-инструментов">Коммуникация: смежники, продакты, пользователи твоих инструментов</h2>
<p>Надёжность ломается не только в коде, но и на стыках людей и команд.</p>
<ul>
<li>Если сервис <em>А</em> положил сервис <em>Б</em> десятикратным ростом запросов — виноваты оба: <em>А</em> не ограничил нагрузку, <em>Б</em> не предусмотрел верхнюю границу того, что он может переварить.</li>
<li>Разборы инцидентов должны быть <strong>публичными</strong>: любой участник должен иметь возможность задать вопрос, особенно из смежных команд.</li>
<li>С теми, кто пользуется твоими панелями и инструментами, надо регулярно говорить и смотреть «их глазами» на интерфейс — очень часто это приносит внезапные открытия, потому что очевидное для тебя — неочевидно для других.</li>
</ul>
<p>Плюс базовая дисциплина: общий календарь маркетинговых запусков и регламентных работ, понятные термины и общий словарь.</p>
<h2 id="безопасность-как-часть-надёжности">Безопасность как часть надёжности</h2>
<p>Про ИБ легко забыть, пока не прилетело.</p>
<ul>
<li>Требования информационной безопасности — это не внешняя бюрократия, а часть надёжности и доступности.</li>
<li>Чем раньше ты начнёшь приводить сервис к ИБ‑гайдам, тем меньше будет боли потом: всё равно придётся, но лучше не в режиме горящей пятой точки.</li>
<li>Debug‑режимы, скрытые параметры, хардкод в фронтенде, незащищённые «магические» урлы — всё это при первом же fuzzing&rsquo;е превращается в инцидент.</li>
</ul>
<p>ИБ — просто ещё один класс рисков для надёжности, и игнорировать его — то же самое, что не мониторить диск или БД.</p>
<h2 id="несколько-практических-выводов">Несколько практических выводов</h2>
<p>Соберём самое важное в виде коротких тезисов — то, что полезно прямо взять и примерить к своему проекту:</p>
<ul>
<li><strong>Формализуй принципы команды.</strong> Пойми, что для вас нормально, а что — нет, и как вы принимаете решения в проде.</li>
<li><strong>Строй иммунитет системы.</strong> Собирай данные об инцидентах, запускай учения, внедряй DIS, GD и fallback как связанный комплекс.</li>
<li><strong>Наведи порядок в мониторинге.</strong> Абсолютные значения + тренды, min/max + перцентили, резервный мониторинг и внешние проверки.</li>
<li><strong>Инвестируй в процесс.</strong> Стандартизированные инструкции, регламенты, планы отката, регулярные учения по релизам и rollback’ам.</li>
<li><strong>Живи через GitOps и версии.</strong> Всё важное — в VCS, релиз самодостаточен, откат — быстрый и предсказуемый.</li>
<li><strong>Не забывай про людей.</strong> Психология дежурств, личные чек‑листы, явные дежурные, нормальная коммуникация с продактами и смежниками.</li>
</ul>
<p>Если всё это собрать вместе, то «чинить прод» перестаёт быть вечным героическим подвигом и превращается в спокойную инженерную работу. А это, кажется, ровно то, к чему хочется прийти.</p>
<p>PS: Читать книгу &ldquo;<a href="https://www.litres.ru/book/natalya-savenkova/sre-recepty-vyzhivaniya-v-prodakshene-dlya-inzhenera-po-70232503/" rel="noopener noreferrer" target="_blank">SRE. Рецепты выживания в продакшне для инженера по надежности</a>
&rdquo; за авторством <a href="https://www.litres.ru/author/natalya-savenkova/" rel="noopener noreferrer" target="_blank">Натальи Савенковой</a>
 было и смешно и грустно одновременно. Но главная ценность лично для меня — я увидел, что я не одинок в своих выводах!</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></content:encoded>
    </item><item>
      <title>Digital Immune System: цифровой иммунитет твоей инфраструктуры</title>
      <link>https://jtprog.ru/posts/digital-immune-system/</link>
      <pubDate>Tue, 10 Feb 2026 22:14:14 +0300</pubDate>
      <dc:creator>jtprogru</dc:creator>
      <guid isPermaLink="true">https://jtprog.ru/posts/digital-immune-system/</guid>
      <category>SRE</category>
      <category>DIS</category>
      <category>Observability</category>
      <category>Chaos-Engineering</category>
      <category>Auto-Remediation</category>
      <category>DevOps</category>
      <category>Reliability</category>
      <category>Infrastructure</category>
      <category domain="category">Opinions</category>
      <enclosure url="https://jtprog.ru/opinions.png" type="image/jpeg" length="0" />
      <media:thumbnail url="https://jtprog.ru/opinions.png" /><description><![CDATA[<div><p>Привет, <code>%username%</code>! Сегодня поговорим о концепции, которую Gartner включил в топ-10 стратегических технологических трендов — <strong>Digital Immune System (DIS)</strong>, или «Цифровая иммунная система». Звучит футуристично, но на самом деле это про то, как сделать наши системы такими же адаптивными и самовосстанавливающимися, как человеческий организм.</p>
<h2 id="что-это-такое">Что это такое?</h2>
<p>Gartner определяет DIS как комбинацию практик и технологий проектирования, разработки, автоматизации, эксплуатации и аналитики ПО, направленных на снижение бизнес-рисков и создание превосходного пользовательского опыта. Главная идея — система должна не просто реагировать на сбои, а <strong>предвидеть их, противостоять им и автоматически восстанавливаться</strong>.</p>
<p>Проще говоря: вместо того чтобы тушить пожары каждый раз, когда что-то падает, мы строим систему, которая сама умеет обнаруживать проблемы, минимизировать их влияние и быстро возвращаться в норму — без ручного вмешательства или с минимальным участием команд разработки и эксплуатации.</p>
<h2 id="шесть-столпов-dis">Шесть столпов DIS</h2>
<p>По версии Gartner, цифровой иммунитет держится на шести ключевых практиках:</p>
<ol>
<li><strong>Observability (Наблюдаемость)</strong> — глубокое понимание состояния системы через логи, метрики и трейсы. Это не просто мониторинг, а возможность в реальном времени видеть, что происходит внутри.</li>
<li><strong>AI-augmented Testing (Тестирование с AI)</strong> — использование машинного обучения для автоматизации тестирования, предсказания дефектов и адаптации тест-кейсов к изменениям кода.</li>
<li><strong>Chaos Engineering (Хаос-инженерия)</strong> — контролируемые эксперименты с отказами, чтобы выявить слабые места до того, как они ударят по пользователям. Для SRE это прямой путь к снижению MTTR и повышению MTBF.</li>
<li><strong>Auto Remediation (Автоматическое исправление)</strong> — система сама устраняет проблемы без участия человека: перезапускает сервисы, масштабирует ресурсы, откатывает изменения.</li>
<li><strong>Site Reliability Engineering (SRE)</strong> — обеспечение непрерывности работы через автоматизацию, SLO/SLA и культуру надежности.</li>
<li><strong>Software Supply Chain Security</strong> — защита всей цепочки поставок ПО, от зависимостей до деплоя, чтобы предотвратить внедрение уязвимостей.</li>
</ol>
<h2 id="почему-это-важно-для-sre-и-devops">Почему это важно для SRE и DevOps?</h2>
<p>Gartner прогнозирует, что организации, инвестирующие в DIS, снизят даунтайм и значительно повысят удовлетворенность клиентов. В реальности это означает:</p>
<ul>
<li><strong>Меньше инцидентов</strong> — благодаря превентивному обнаружению проблем через observability и chaos engineering;</li>
<li><strong>Быстрее восстановление</strong> — auto remediation сокращает MTTR, автоматически реагируя на сбои;</li>
<li><strong>Выше надежность</strong> — системы проектируются с учетом отказоустойчивости с самого начала (Secure by Design);</li>
<li><strong>Меньше ручной работы</strong> — автоматизация освобождает время на стратегические задачи, а не на тушение пожаров.</li>
</ul>
<h2 id="digital-immune-system-vs-традиционный-подход">Digital Immune System vs традиционный подход</h2>
<p>Традиционно мы реагируем на проблемы постфактум: упало — подняли, нашли баг — зафиксили. DIS переворачивает этот подход: системы становятся <strong>проактивными</strong>. Они постоянно тестируют себя на прочность (chaos engineering), адаптируются к изменениям (AI-testing), мониторят каждый аспект работы (observability) и самостоятельно исправляют ошибки (auto remediation).</p>
<p>Это особенно актуально для распределенных систем и микросервисной архитектуры, где один сбой может каскадом распространиться на десятки зависимых сервисов.</p>
<h2 id="связь-с-другими-концепциями">Связь с другими концепциями</h2>
<p>Если ты следил за эволюцией подходов к безопасности и надежности, то заметишь, что DIS пересекается с <strong>Cyber Resilience</strong> (готовность к взлому), <strong>Zero Trust</strong> (никому не доверяй, всегда проверяй) и <strong>DevSecOps</strong> (безопасность на всех этапах SDLC). Но ключевое отличие DIS — это акцент на <strong>автоматическом самовосстановлении</strong> и <strong>встроенной безопасности с момента проектирования</strong> (а не в виде наложенных средств защиты).</p>
<p>В российском контексте похожий подход развивают «Лаборатория Касперского» и «Авито» под названием <strong>кибериммунитет</strong> — системы, где безопасность встроена в архитектуру и код, минимизирована доверенная кодовая база, а защита активирована по умолчанию (Secure by Design, Secure by Default). Аналогичные подходы развивают и другие компании, с той лишь разницей, что они не собирают это в единую экосистему надежности и их подходы находятся в более фрагментарном состоянии.</p>
<h2 id="как-применять-dis-на-практике">Как применять DIS на практике?</h2>
<p>Не обязательно внедрять все шесть столпов сразу. Начни с того, что ближе твоей команде:</p>
<ul>
<li>Уже используешь Prometheus и Grafana? Расширь их до full-stack observability с трейсингом (OpenTelemetry).</li>
<li>Есть CI/CD? Интегрируй AI-powered тестирование и SAST/SCA для раннего обнаружения багов.</li>
<li>Хочешь проверить устойчивость? Запусти chaos experiments с инструментами типа Chaos Monkey или Gremlin.</li>
<li>Настроил алерты? Добавь auto remediation — скрипты, которые автоматически реагируют на типовые инциденты.</li>
</ul>
<p>Главное — не пытаться достичь идеала сразу. DIS — это итеративный процесс, где каждая новая практика усиливает предыдущие.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></description>
      <content:encoded><![CDATA[<style>/* Inline-CSS, который тема вкладывает в <description> каждого item'а
   RSS-фида (layouts/index.rss.xml). RSS-ридеры (Feedly, Inoreader,
   NetNewsWire) уважают <style> внутри description с переменной
   степенью энтузиазма — это базовый fallback, достаточный для читаемой
   типографики, не более.

   Цвета продублированы из 00-vars.css (light-палитра) — поправь
   синхронно при изменении --bg / --text / --accent / --border. */

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  line-height: 1.6;
  color: #1c1c1f;
  max-width: 720px;
  margin: 0 auto;
  padding: 1em;
}
h1, h2, h3 { line-height: 1.25; margin-top: 1.4em; }
a { color: #c2410c; }
pre {
  background: #1e1e24;
  color: #e8e6df;
  padding: 1em;
  border-radius: 6px;
  overflow-x: auto;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.9em;
}
code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  background: #f3f1ed;
  padding: 0.1em 0.4em;
  border-radius: 4px;
}
pre code { background: transparent; padding: 0; }
blockquote {
  border-left: 3px solid #c2410c;
  padding-left: 1em;
  color: #5b5b62;
  font-style: italic;
  margin-left: 0;
}
img { max-width: 100%; height: auto; border-radius: 6px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #e5e3dc; padding: 6px 10px; text-align: left; }
</style><div><p>Привет, <code>%username%</code>! Сегодня поговорим о концепции, которую Gartner включил в топ-10 стратегических технологических трендов — <strong>Digital Immune System (DIS)</strong>, или «Цифровая иммунная система». Звучит футуристично, но на самом деле это про то, как сделать наши системы такими же адаптивными и самовосстанавливающимися, как человеческий организм.</p>
<h2 id="что-это-такое">Что это такое?</h2>
<p>Gartner определяет DIS как комбинацию практик и технологий проектирования, разработки, автоматизации, эксплуатации и аналитики ПО, направленных на снижение бизнес-рисков и создание превосходного пользовательского опыта. Главная идея — система должна не просто реагировать на сбои, а <strong>предвидеть их, противостоять им и автоматически восстанавливаться</strong>.</p>
<p>Проще говоря: вместо того чтобы тушить пожары каждый раз, когда что-то падает, мы строим систему, которая сама умеет обнаруживать проблемы, минимизировать их влияние и быстро возвращаться в норму — без ручного вмешательства или с минимальным участием команд разработки и эксплуатации.</p>
<h2 id="шесть-столпов-dis">Шесть столпов DIS</h2>
<p>По версии Gartner, цифровой иммунитет держится на шести ключевых практиках:</p>
<ol>
<li><strong>Observability (Наблюдаемость)</strong> — глубокое понимание состояния системы через логи, метрики и трейсы. Это не просто мониторинг, а возможность в реальном времени видеть, что происходит внутри.</li>
<li><strong>AI-augmented Testing (Тестирование с AI)</strong> — использование машинного обучения для автоматизации тестирования, предсказания дефектов и адаптации тест-кейсов к изменениям кода.</li>
<li><strong>Chaos Engineering (Хаос-инженерия)</strong> — контролируемые эксперименты с отказами, чтобы выявить слабые места до того, как они ударят по пользователям. Для SRE это прямой путь к снижению MTTR и повышению MTBF.</li>
<li><strong>Auto Remediation (Автоматическое исправление)</strong> — система сама устраняет проблемы без участия человека: перезапускает сервисы, масштабирует ресурсы, откатывает изменения.</li>
<li><strong>Site Reliability Engineering (SRE)</strong> — обеспечение непрерывности работы через автоматизацию, SLO/SLA и культуру надежности.</li>
<li><strong>Software Supply Chain Security</strong> — защита всей цепочки поставок ПО, от зависимостей до деплоя, чтобы предотвратить внедрение уязвимостей.</li>
</ol>
<h2 id="почему-это-важно-для-sre-и-devops">Почему это важно для SRE и DevOps?</h2>
<p>Gartner прогнозирует, что организации, инвестирующие в DIS, снизят даунтайм и значительно повысят удовлетворенность клиентов. В реальности это означает:</p>
<ul>
<li><strong>Меньше инцидентов</strong> — благодаря превентивному обнаружению проблем через observability и chaos engineering;</li>
<li><strong>Быстрее восстановление</strong> — auto remediation сокращает MTTR, автоматически реагируя на сбои;</li>
<li><strong>Выше надежность</strong> — системы проектируются с учетом отказоустойчивости с самого начала (Secure by Design);</li>
<li><strong>Меньше ручной работы</strong> — автоматизация освобождает время на стратегические задачи, а не на тушение пожаров.</li>
</ul>
<h2 id="digital-immune-system-vs-традиционный-подход">Digital Immune System vs традиционный подход</h2>
<p>Традиционно мы реагируем на проблемы постфактум: упало — подняли, нашли баг — зафиксили. DIS переворачивает этот подход: системы становятся <strong>проактивными</strong>. Они постоянно тестируют себя на прочность (chaos engineering), адаптируются к изменениям (AI-testing), мониторят каждый аспект работы (observability) и самостоятельно исправляют ошибки (auto remediation).</p>
<p>Это особенно актуально для распределенных систем и микросервисной архитектуры, где один сбой может каскадом распространиться на десятки зависимых сервисов.</p>
<h2 id="связь-с-другими-концепциями">Связь с другими концепциями</h2>
<p>Если ты следил за эволюцией подходов к безопасности и надежности, то заметишь, что DIS пересекается с <strong>Cyber Resilience</strong> (готовность к взлому), <strong>Zero Trust</strong> (никому не доверяй, всегда проверяй) и <strong>DevSecOps</strong> (безопасность на всех этапах SDLC). Но ключевое отличие DIS — это акцент на <strong>автоматическом самовосстановлении</strong> и <strong>встроенной безопасности с момента проектирования</strong> (а не в виде наложенных средств защиты).</p>
<p>В российском контексте похожий подход развивают «Лаборатория Касперского» и «Авито» под названием <strong>кибериммунитет</strong> — системы, где безопасность встроена в архитектуру и код, минимизирована доверенная кодовая база, а защита активирована по умолчанию (Secure by Design, Secure by Default). Аналогичные подходы развивают и другие компании, с той лишь разницей, что они не собирают это в единую экосистему надежности и их подходы находятся в более фрагментарном состоянии.</p>
<h2 id="как-применять-dis-на-практике">Как применять DIS на практике?</h2>
<p>Не обязательно внедрять все шесть столпов сразу. Начни с того, что ближе твоей команде:</p>
<ul>
<li>Уже используешь Prometheus и Grafana? Расширь их до full-stack observability с трейсингом (OpenTelemetry).</li>
<li>Есть CI/CD? Интегрируй AI-powered тестирование и SAST/SCA для раннего обнаружения багов.</li>
<li>Хочешь проверить устойчивость? Запусти chaos experiments с инструментами типа Chaos Monkey или Gremlin.</li>
<li>Настроил алерты? Добавь auto remediation — скрипты, которые автоматически реагируют на типовые инциденты.</li>
</ul>
<p>Главное — не пытаться достичь идеала сразу. DIS — это итеративный процесс, где каждая новая практика усиливает предыдущие.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></content:encoded>
    </item><item>
      <title>Эволюция практик Site Reliability Engineering: краткий анализ тенденций 2020-2025</title>
      <link>https://jtprog.ru/posts/sre-evolution-2020-2025/</link>
      <pubDate>Mon, 05 Jan 2026 19:16:29 +0300</pubDate>
      <dc:creator>jtprogru</dc:creator>
      <guid isPermaLink="true">https://jtprog.ru/posts/sre-evolution-2020-2025/</guid>
      <category>SRE</category>
      <category>Observability</category>
      <category>Report</category>
      <category domain="category">Opinions</category>
      <enclosure url="https://jtprog.ru/opinions.png" type="image/jpeg" length="0" />
      <media:thumbnail url="https://jtprog.ru/opinions.png" /><description><![CDATA[<div><p>Привет, <code>%username%</code>! Попытался разобраться, куда катится Site Reliability Engineering (SRE) за последние лет пять. Ниже накидал мысли по этому поводу. Ссылки на все отчеты вроде не забыл, так что зацени, а потом го в комменты – обсудим вместе.</p>
<h2 id="что-там-в-отчетах">Что там в отчетах?</h2>
<p>Короче, за последние лет пять SRE стала прямо хайповой темой для исследований. Вот самые толковые источники, чтобы быть в теме, что в SRE происходит:</p>
<ul>
<li><strong>Catchpoint — The SRE Report</strong> (<a href="https://www.catchpoint.com/asset/2020-sre-report" rel="noopener noreferrer" target="_blank">2020</a>
, <a href="https://www.catchpoint.com/asset/2021-sre-report" rel="noopener noreferrer" target="_blank">2021</a>
, <a href="https://www.catchpoint.com/asset/2023-sre-report" rel="noopener noreferrer" target="_blank">2023</a>
, <a href="https://www.catchpoint.com/asset/2024-sre-report" rel="noopener noreferrer" target="_blank">2024</a>
, <a href="https://www.catchpoint.com/asset/2025-sre-report" rel="noopener noreferrer" target="_blank">2025</a>
): Это, наверное, самый жирный отчет прям по SRE. В 2025 опросили больше 300 спецов из разных областей. Говорят, это типа реальное мнение людей из SRE команд, без воды и прикрас.</li>
<li><strong>DORA (DevOps Research and Assessment)</strong>: Каждый год (<a href="https://dora.dev/research/2020/" rel="noopener noreferrer" target="_blank">2020</a>
, <a href="https://dora.dev/research/2021/" rel="noopener noreferrer" target="_blank">2021</a>
, <a href="https://dora.dev/research/2022/" rel="noopener noreferrer" target="_blank">2022</a>
, <a href="https://dora.dev/research/2023/" rel="noopener noreferrer" target="_blank">2023</a>
, <a href="https://dora.dev/research/2024/" rel="noopener noreferrer" target="_blank">2024</a>
, <a href="https://dora.dev/research/2022/" rel="noopener noreferrer" target="_blank">2025</a>
) катают отчеты, где уже лет десять меряют, насколько круто DevOps и SRE работают. Смотрят на четыре главные метрики. В 2025 даже целый отчет выпустили про то, как AI влияет на разработку.</li>
<li><strong><a href="https://www.devopsinstitute.com/global-sre-pulse/" rel="noopener noreferrer" target="_blank">DevOps Institute — Global SRE Pulse 2022</a>
</strong>: Это было первое большое исследование, где опросили больше 460 SRE спецов и манагеров из средних и больших компаний. В отчете можно глянуть, как сейчас вообще живёт SRE, какие штуки юзают, как команды себя чувствуют и насколько все заавтоматизировано.</li>
<li><strong><a href="https://www.puppet.com/resources/history-of-devops-reports" rel="noopener noreferrer" target="_blank">Puppet — State of DevOps</a>
</strong> (2020-2021, 2023): В 2021 отметили десятилетие этих отчетов и выяснили, что у 78% компаний с DevOps дела так себе, где-то на середине. В 2023 больше смотрели на платформенную инженерию.</li>
<li><strong>Forrester Research</strong> (<a href="https://www.forrester.com/report/five-key-trends-to-benchmark-devops-progress/RES120481" rel="noopener noreferrer" target="_blank">2020</a>
): Выкатили отчет про десять главных трендов в инфраструктуре и сказали, что SRE – это база для стабильной работы всего.</li>
<li><strong>Gartner Hype Cycle</strong> (<a href="https://www.gartner.com/en/articles/hype-cycle-for-emerging-technologies" rel="noopener noreferrer" target="_blank">2025</a>
): Закинули SRE и Platform Engineering на свой график взросления технологий. Ещё упомянули всякие приколы для управления окружениями, чтоб каждый мог сам себе все сделать.</li>
<li><strong>ThoughtWorks Technology Radar</strong> (постоянно, <a href="https://www.thoughtworks.com/radar/archive" rel="noopener noreferrer" target="_blank">2020-2025</a>
): Эти ребята вообще всегда следят, как меняются инструменты и практики в SRE, наблюдаемости и чтоб системы были надежными.</li>
</ul>
<h2 id="главные-изменения-в-sre">Главные изменения в SRE</h2>
<h3 id="1-рост-toil-неожиданный-поворот-в-2025">1. Рост Toil: неожиданный поворот в 2025</h3>
<p><em>Что-то пошло не так</em>: Впервые за пять лет нудной работы (Toil) стало больше. Раньше было 14% времени, а теперь все 20%. Задачи по операционке тоже времени жрут больше – теперь 30% вместо 20%.</p>
<p>Все думали, с AI станет легче. Эксперты из Catchpoint удивились: ждали, что AI уберет рутину, а он наоборот, ее добавил. Может, все дело в том, что AI помогает быстрее делать полезные вещи, а свободное время забивается всякой фигней.</p>
<p><em>Как было раньше</em>: С 2020 по 2024 нудной работы становилось все меньше. Спасибо автоматизации, IaC, CI/CD и системам, которые сами чинятся. Google советует, чтоб такой работы было не больше половины времени инженера, а у SRE – не больше половины на операционку.</p>
<p><strong>Как бороться с Toil в 2025</strong>:</p>
<ul>
<li>Автоматизация через Terraform, Ansible, CI/CD пайплайны.</li>
<li>Внедряйте self-healing системы, чтоб все чинилось само.</li>
<li>Стандартизируйте все через плейбуки и runbooks.</li>
<li>AIOps инструменты – чтобы алерты сами между собой разбирались и мониторили все на будущее.</li>
<li>Переходите на self-service порталы вместо тикетов.</li>
</ul>
<h3 id="2-ai-и-machine-learning-уже-не-просто-побаловаться-а-без-них-никуда">2. AI и Machine Learning: уже не просто побаловаться, а без них никуда</h3>
<p><strong>Как развивалось</strong>:</p>
<ul>
<li><strong>2020</strong>: Только начали пробовать AI в мониторинге и поиске аномалий.</li>
<li><strong>2021-2022</strong>: Все больше интересуются, как AI может предсказывать проблемы и автоматом чинить инциденты.</li>
<li><strong>2023-2024</strong>: Вовсю внедряют AIOps платформы (Datadog, Splunk, Dynatrace).</li>
<li><strong>2025</strong>: GenAI – это революция! 39% спецов говорят, что AI круто генерит код.</li>
</ul>
<p><strong>Где AI нужен в SRE 2025</strong>:</p>
<ul>
<li><strong>Предсказывать инциденты</strong>: AI изучает старые данные и говорит, где может рвануть.</li>
<li><strong>Автоматически генерить тесты</strong>: ML создает тесты, когда код меняется.</li>
<li><strong>AI помогает в ChatOps</strong>: встраивают LLM в процессы управления инцидентами.</li>
<li><strong>Системы, которые сами чинятся</strong>: AI находит аномалии и сам все исправляет.</li>
<li><strong>Улучшение производительности</strong>: AI анализирует, что можно улучшить в SLO.</li>
</ul>
<p><strong>Важный момент из DORA 2024</strong>: второй год подряд получается, что AI делает доставку софта хуже. Короче, AI – не волшебная таблетка, надо аккуратно внедрять и смотреть, что получается.</p>
<p><strong>Что думают про AI</strong>: 53% SRE думают, что AI сделает их работу легче, и только 4% боятся, что AI их заменит. При этом 30% решили, что надо учиться AI.</p>
<h3 id="3-platform-engineering-и-sre-теперь-вместе-навсегда">3. Platform Engineering и SRE: теперь вместе навсегда</h3>
<p><strong>Как менялись отношения</strong>:</p>
<ul>
<li><strong>2020</strong>: Platform Engineering как отдельную штуку вообще не выделяли, все было в DevOps.</li>
<li><strong>2021-2022</strong>: Начали говорить про Platform Engineering.</li>
<li><strong>2023</strong>: Puppet выпустили отчет State of Platform Engineering, и 93% сказали, что это круто.</li>
<li><strong>2024-2025</strong>: Platform Engineering и SRE активно работают вместе.</li>
</ul>
<p><strong>В чем разница и как помогают друг другу</strong>:</p>
<ul>
<li><strong>Platform Engineering</strong> создает платформы, чтобы разрабам было проще работать: self-service, не надо думать про инфраструктуру, все стандартизировано.</li>
<li><strong>SRE</strong> следит, чтоб все работало надежно, SLO выполнялись, мониторит продакшн, разруливает инциденты и чтоб всего было в меру – и новых фич, и стабильности.</li>
<li><strong>Вместе им хорошо</strong>: если платформа сделана правильно, то у SRE меньше Toil, потому что все деплоится по стандарту и куча задач автоматизирована. А SRE, в свою очередь, делает платформы надежнее.</li>
</ul>
<h3 id="4-finops-sre-теперь-еще-и-за-бабки-отвечает">4. FinOps: SRE теперь еще и за бабки отвечает</h3>
<p><strong>Как росла важность</strong>:</p>
<ul>
<li><strong>2020</strong>: Только начали понимать, что надо следить за расходами в облаке.</li>
<li><strong>2021-2022</strong>: FinOps стала отдельной темой.</li>
<li><strong>2023-2024</strong>: FinOps активно встраивается в SRE практики.</li>
<li><strong>2025</strong>: SRE команды вовсю юзают FinOps, чтобы тратить меньше денег в облаке.</li>
</ul>
<p><strong>Что SRE должны знать про FinOps</strong>:</p>
<ul>
<li>Ответственность за деньги – часть DevOps.</li>
<li>Как тратить меньше, но чтоб все работало надежно.</li>
<li>Как правильно выделять деньги на облачные ресурсы.</li>
<li>Оптимизация производительности за свои деньги.</li>
<li>Управление ресурсами.</li>
</ul>
<p>Catchpoint 2025 говорит, что Capacity Management теперь в приоритете у компаний, наравне с SRE, SLO и автоматизацией починки инцидентов.</p>
<h3 id="5-opentelemetry-все-стандартизировали-наблюдаемость">5. OpenTelemetry: все стандартизировали наблюдаемость</h3>
<p><strong>Как быстро все начали юзать</strong>:</p>
<ul>
<li><strong>2020</strong>: Никто толком не знал (~5%).</li>
<li><strong>2021-2022</strong>: Уже многие в теме (~20-25% планируют или юзают).</li>
<li><strong>2023-2024</strong>: Уже хорошо (~48% юзают).</li>
<li><strong>2025</strong>: Практически все (~73% юзают или собираются).</li>
</ul>
<p><strong>Почему это круто</strong>:</p>
<ul>
<li><strong>Стандартизация</strong>: один стандарт для всего – как собирать данные, как их отправлять.</li>
<li><strong>Не надо зависеть от поставщиков</strong>: можно не привязываться к конкретному вендору.</li>
<li><strong>ROI</strong>: 46% компаний говорят, что ROI больше 20%, а еще 40% – 10-20%.</li>
<li><strong>Экономия</strong>: 84% компаний, которые стали меньше тратить на observability, говорят, что сэкономили минимум 10%.</li>
<li><strong>Зрелость</strong>: 81% считают, что OpenTelemetry уже достаточно взрослая штука.</li>
</ul>
<p><strong>Почему это важно для AI-SRE</strong>: OpenTelemetry – это база для AI, потому что он дает одинаковые, понятные данные для анализа.</p>
<p><strong>Но есть и проблемы</strong>: сложно внедрить, данных становится слишком много (в 4-5 раз больше), надо интегрировать со старыми системами и следить за расходами.</p>
<h3 id="6-chaos-engineering-теперь-это-не-просто-прикол-а-необходимость">6. Chaos Engineering: теперь это не просто прикол, а необходимость</h3>
<p><strong>Как это стало популярно</strong>:</p>
<ul>
<li><strong>2020</strong>: Какая-то странная штука, которую Netflix придумал.</li>
<li><strong>2021</strong>: 60% спецов хоть раз пробовали chaos-эксперименты.</li>
<li><strong>2022-2023</strong>: Все больше компаний юзают это, чтобы проверять, как системы работают при сбоях.</li>
<li><strong>2024-2025</strong>: Chaos Engineering стал важной частью SRE.</li>
</ul>
<p><strong>Как это работает с SRE</strong>:</p>
<ul>
<li><strong>Проверка на отказоустойчивость</strong>: специально ломают систему, чтоб найти слабые места.</li>
<li><strong>Валидация SLO/SLI</strong>: убеждаются, что все работает, даже когда что-то идет не так.</li>
<li><strong>Подготовка к инцидентам</strong>: тренируются реагировать, чтоб пользователи ничего не заметили.</li>
<li><strong>Уменьшение Toil</strong>: автоматом проверяют отказоустойчивость через CI/CD.</li>
<li><strong>Быстрее чинят</strong>: если заранее знают, что может сломаться, то быстрее восстановят.</li>
</ul>
<p><strong>Популярные инструменты 2025</strong>: Qinfinite by Quinnox, Gremlin, Chaos Mesh, LitmusChaos, AWS Fault Injection Simulator.</p>
<p><strong>Важный момент</strong>: Chaos Engineering помогает создать атмосферу, где не ищут виноватых, а стараются улучшить систему.</p>
<h3 id="7-slo-и-error-budgets-все-становится-серьезно">7. SLO и Error Budgets: все становится серьезно</h3>
<p><strong>Как взрослели</strong>:</p>
<ul>
<li><strong>2020</strong>: Только начали внедрять SLO, но часто не понимали, зачем это.</li>
<li><strong>2021-2022</strong>: Стало больше понимания, но 99% SRE не знают, как правильно определить SLO.</li>
<li><strong>2023-2024</strong>: SLO стали важны при принятии решений.</li>
<li><strong>2025</strong>: SLO помогают решать, что важнее – надежность или новые фичи, появились composite SLO и reliability scoring.</li>
</ul>
<p><strong>Что нового в SLO</strong>:</p>
<ul>
<li><strong>Composite SLOs</strong>: объединяют несколько SLO в одну метрику, чтобы видеть картину целиком.</li>
<li><strong>Reliability scoring</strong>: оценивают надежность системы в цифрах.</li>
<li><strong>Мониторинг в реальном времени и алерты</strong>: помогают управлять SLO.</li>
<li><strong>SLO Development Life Cycle (SLODLC)</strong>: как правильно внедрять SLO.</li>
</ul>
<p><strong>Error Budget Management – это целый рынок</strong>: он вырос с $1.2 млрд в 2024 году и, по прогнозам, будет $5.8 млрд к 2033 году. Это значит, что DevOps, SRE и cloud-native технологии становятся все популярнее.</p>
<p><strong>Проблемы с SLO</strong>:</p>
<ul>
<li>51% считают, что observability не очень, особенно там, где мало инструментов.</li>
<li>SLO бесполезны, если их не использовать постоянно, потому что системы меняются.</li>
<li>Надо думать о пользователях: SLO должны показывать, что пользователи чувствуют, а не только технические метрики.</li>
</ul>
<h3 id="8-автоматизация-управления-инцидентами-и-aiops">8. Автоматизация управления инцидентами и AIOps</h3>
<p><strong>Как развивалось</strong>:</p>
<ul>
<li><strong>2020</strong>: Только начали автоматом делать алерты и тикеты.</li>
<li><strong>2021-2022</strong>: Активно развивали runbook automation и self-healing.</li>
<li><strong>2023-2024</strong>: Внедрили AIOps, чтобы связывать события и предсказывать проблемы.</li>
<li><strong>2025</strong>: AI помогает управлять инцидентами, общаться на обычном языке и автоматом искать причины проблем.</li>
</ul>
<p><strong>Как выглядит incident management в 2025</strong>:</p>
<ul>
<li><strong>Видят все в реальном времени</strong>: AI анализирует логи и события и сразу находит закономерности.</li>
<li><strong>Алерты на будущее</strong>: ML предсказывает, где может случиться инцидент.</li>
<li><strong>Автоматически чинят</strong>: системы сами исправляют проблемы, без людей.</li>
<li><strong>Все общаются в одном месте</strong>: все стейкхолдеры сидят в одной системе.</li>
<li><strong>Удобные workflows</strong>: инструменты для управления инцидентами работают прямо в Slack.</li>
</ul>
<p><strong>Важный момент</strong>: 40% инженеров участвовали в 1-5 инцидентах за последние 30 дней. При этом руководители тоже в деле, не меньше, чем обычные инженеры. 14% сильно стрессуют после инцидентов, потому что им не хватает поддержки.</p>
<p><strong>Как дела с incident management (Global SRE Pulse 2022)</strong>: больше 70% говорят, что у них хорошо спроектирован процесс управления инцидентами и алерты обрабатываются четко.</p>
<p><strong>Как AI все изменил в 2025</strong>:</p>
<ul>
<li>На 56% точнее находят угрозы, чем старые системы.</li>
<li>Анализ инцидентов занимает 2.8 минуты вместо 18.5.</li>
<li>Автоматизируют 78% действий при обычных инцидентах, раньше было 35%.</li>
<li>Ложных срабатываний стало меньше – с 25% до 8%.</li>
</ul>
<h3 id="9-надежность-vs-скорость-кто-победит">9. Надежность vs. скорость: кто победит?</h3>
<p><strong>Плохая новость</strong>: большинство спецов (больше двух третей) чувствуют, что их заставляют выпускать релизы быстрее, чем это безопасно для надежности.</p>
<p><strong>Почему так происходит</strong>:</p>
<ul>
<li><strong>Уходят те, кто создавал SRE</strong>: эксперты уходят из компаний, и приоритеты меняются.</li>
<li><strong>Бизнес давит</strong>: хотят новые фичи и больше денег.</li>
<li><strong>Не все понимают одинаково</strong>: инженеры и руководители по-разному оценивают надежность – чем выше должность, тем больше уверенности, что все хорошо.</li>
</ul>
<p><strong>Как было раньше</strong>: это старая проблема – что важнее, быстро или безопасно. SRE пытаются это решить с помощью error budgets и SLO. Но в 2025 давление стало слишком сильным.</p>
<p><strong>Что делать</strong>:</p>
<ul>
<li>Регулярно проверять и обновлять оценки процессов.</li>
<li>Звать внешних экспертов.</li>
<li>Улучшать культуру SRE и учить всех в компании, что надежность – это важно.</li>
<li>Использовать error budgets, чтобы принимать решения.</li>
</ul>
<h3 id="10-структуры-sre-команд-и-как-их-организовать">10. Структуры SRE-команд и как их организовать</h3>
<p><strong>Основные варианты</strong> (из книги Establishing SRE Foundations):</p>
<ol>
<li><strong>You Build It, You Run It</strong>: разрабы сами отвечают и за разработку, и за эксплуатацию. Быстро деплоят, но много операционных задач и сложно управлять изменениями.</li>
<li><strong>You Build It, SRE Run It</strong>: разрабы пилят код, SRE занимаются операционкой. Может случиться разрыв между командами.</li>
<li><strong>You Build It, You and SRE Run It</strong>: все в ответе вместе – SRE управляют операционными задачами, разрабы пишут код, но все вместе смотрят на метрики.</li>
</ol>
<p><strong>Где команда SRE находится в компании</strong> (Global SRE Pulse 2022):</p>
<ul>
<li>30% — IT operations</li>
<li>22% — отдельная команда</li>
<li>18% — application design &amp; development</li>
<li>18% — IT infrastructure</li>
<li>3% — IT security</li>
</ul>
<p><strong>Типы команд</strong>:</p>
<ul>
<li><strong>Centralized</strong>: помогают многим продуктам/сервисам.</li>
<li><strong>Dedicated</strong>: занимаются конкретными продуктами.</li>
<li><strong>Platform-based</strong>: строят облачные платформы.</li>
<li><strong>Stack-based</strong>: отдельные команды для разных стеков приложений/инфраструктуры.</li>
</ul>
<p><strong>Главное правило Google SRE</strong>: максимум 50% времени на операционку, минимум 50% на engineering (улучшения, автоматизация, исправление проблем).</p>
<h3 id="11-observability-от-мониторинга-к-ai">11. Observability: от мониторинга к AI</h3>
<p><strong>Как менялось</strong>:</p>
<ul>
<li><strong>2020</strong>: Просто мониторили (метрики, логи).</li>
<li><strong>2021-2022</strong>: Перешли к observability (метрики + логи + трассировки).</li>
<li><strong>2023-2024</strong>: Observability всего стека, смотрят на user experience.</li>
<li><strong>2025</strong>: AI сам находит полезную информацию в телеметрии.</li>
</ul>
<p><strong>Что важно в 2025</strong>:</p>
<ul>
<li><strong>Slow is the new down</strong>: 53% компаний согласны, что плохая производительность – это так же плохо, как если бы все упало.</li>
<li><strong>Много инструментов – это нормально</strong>: большинство компаний используют 2-10 инструментов для мониторинга/observability, и это не проблема, если они приносят пользу.</li>
<li><strong>Разные данные</strong>: 81% компаний используют 2+ типа телеметрии, 43% – 4+ типа.</li>
<li><strong>Что в приоритете</strong>: логи (65%), метрики (56%), события и трассировки.</li>
</ul>
<p><strong>Как все поменялось</strong>: раньше observability была нужна, чтобы люди могли понять терабайты данных. Сейчас, с AI, главное, чтобы машина могла быстро найти нужную информацию.</p>
<h3 id="12-обучение-и-развитие">12. Обучение и развитие</h3>
<p><strong>Учиться надо</strong>: технические тренинги очень важны, чтобы освоить новые технологии, включая AI. Но каждая пятая компания на это забивает.</p>
<p><strong>Как учатся</strong> (Catchpoint 2025):</p>
<ul>
<li>Онлайн-платформы (55%).</li>
<li>Очное обучение (45%).</li>
<li>Конференции (41%).</li>
</ul>
<p><strong>Странно</strong>: все говорят, что учиться важно, но времени нет. Руководители учатся меньше других и, наверное, думают, что им это не нужно.</p>
<p><strong>Важно для карьеры</strong>: DevOps Institute говорит, что SRE – это хороший способ продвинуться в IT, если прокачивать нужные навыки.</p>
<h2 id="выводы-и-что-будет-дальше">Выводы и что будет дальше</h2>
<h3 id="главное-из-анализа">Главное из анализа</h3>
<ol>
<li><strong>Странности 2025</strong>: несмотря на AI и автоматизацию, Toil впервые вырос за пять лет, и AI пока не оправдывает надежд. Значит, дело не только в технологиях, но и в культуре и правильном подходе.</li>
<li><strong>SRE взрослеет</strong>: SRE стала серьезной штукой – 62% компаний в той или иной степени используют SRE (19% во всей компании, 55% в отдельных командах, 23% пробуют). SLO, error budgets и chaos engineering – это уже не ново, а стандарт.</li>
<li><strong>Все работают вместе</strong>: SRE, Platform Engineering, DevOps, DevSecOps и FinOps – это не конкуренты, а друзья, которые помогают друг другу. Компании, которые это понимают, получают больше выгоды.</li>
<li><strong>AI – это помощник, а не замена</strong>: AI помогает инженерам, а не заменяет их. AI должен быть частью культуры и процессов.</li>
<li><strong>Культура важнее</strong>: Puppet 2021 показал, что 78% компаний застряли на середине пути в DevOps/SRE, потому что думают только о технологиях, а не о культуре. Надо менять культуру, а не просто внедрять новые инструменты.</li>
<li><strong>Надежность под угрозой</strong>: все хотят быстро, но забывают про надежность. Надо этим управлять с помощью error budgets, SLO и объяснять всем, что надежность – это важно.</li>
</ol>
<h3 id="что-ждет-нас-после-2025">Что ждет нас после 2025</h3>
<ul>
<li><strong>AI будет еще круче</strong>: AI будет лучше предсказывать проблемы, автоматом искать причины и чинить системы. Но важно помнить, что надо измерять, как AI влияет на производительность.</li>
<li><strong>Platform Engineering станет важнее</strong>: платформы будут строить по строгим правилам, чтобы разрабам было удобнее. Internal Developer Platforms (IDP) станут стандартом для больших компаний.</li>
<li><strong>Больше контроля</strong>: будут следить за тем, чтобы все было безопасно и надежно. Regulation as code станет важной темой.</li>
<li><strong>Инструменты станут проще</strong>: все инструменты DevOps/SRE объединят в одну платформу, чтобы было проще управлять.</li>
<li><strong>Экология</strong>: будут думать о том, как технологии влияют на экологию, и стараться делать все более зеленым.</li>
<li><strong>eBPF</strong>: будут больше использовать eBPF, чтобы видеть, что происходит внутри системы, без лишних инструментов.</li>
<li><strong>Kubernetes</strong>: Kubernetes останется главной системой для управления приложениями.</li>
<li><strong>Zero Trust</strong>: безопасность станет еще важнее, и будут использовать принципы Zero Trust.</li>
</ul>
<h3 id="что-посоветовать-компаниям">Что посоветовать компаниям</h3>
<ol>
<li><strong>Считайте Toil</strong>: регулярно проверяйте, сколько времени уходит на рутину, и выделяйте время на автоматизацию.</li>
<li><strong>Observability – это важно</strong>: переходите от простого мониторинга к полноценной observability с OpenTelemetry.</li>
<li><strong>SLO – это культура</strong>: SLO должны быть не просто цифрами, а частью процесса принятия решений.</li>
<li><strong>Пробуйте Chaos Engineering</strong>: начните с маленьких экспериментов в staging и постепенно переходите к production.</li>
<li><strong>Культура и люди</strong>: учите людей, создавайте атмосферу, где не боятся ошибаться, и поддерживайте друг друга.</li>
<li><strong>Не перегибайте с централизацией</strong>: выберите подходящую структуру SRE-команды, чтобы централизация помогала, а не мешала.</li>
<li><strong>Думайте, зачем вам AI</strong>: внедряйте AI, только если понимаете, какие проблемы он решает, и измеряйте результат.</li>
</ol>
<p>SRE продолжает развиваться и становится все важнее для компаний. Чтобы добиться успеха в SRE, нужно уметь соблюдать баланс – между технологиями и культурой, между новым и стабильным, между скоростью и надежностью. Компании, которые это понимают, будут готовы к будущему.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></description>
      <content:encoded><![CDATA[<style>/* Inline-CSS, который тема вкладывает в <description> каждого item'а
   RSS-фида (layouts/index.rss.xml). RSS-ридеры (Feedly, Inoreader,
   NetNewsWire) уважают <style> внутри description с переменной
   степенью энтузиазма — это базовый fallback, достаточный для читаемой
   типографики, не более.

   Цвета продублированы из 00-vars.css (light-палитра) — поправь
   синхронно при изменении --bg / --text / --accent / --border. */

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  line-height: 1.6;
  color: #1c1c1f;
  max-width: 720px;
  margin: 0 auto;
  padding: 1em;
}
h1, h2, h3 { line-height: 1.25; margin-top: 1.4em; }
a { color: #c2410c; }
pre {
  background: #1e1e24;
  color: #e8e6df;
  padding: 1em;
  border-radius: 6px;
  overflow-x: auto;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.9em;
}
code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  background: #f3f1ed;
  padding: 0.1em 0.4em;
  border-radius: 4px;
}
pre code { background: transparent; padding: 0; }
blockquote {
  border-left: 3px solid #c2410c;
  padding-left: 1em;
  color: #5b5b62;
  font-style: italic;
  margin-left: 0;
}
img { max-width: 100%; height: auto; border-radius: 6px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #e5e3dc; padding: 6px 10px; text-align: left; }
</style><div><p>Привет, <code>%username%</code>! Попытался разобраться, куда катится Site Reliability Engineering (SRE) за последние лет пять. Ниже накидал мысли по этому поводу. Ссылки на все отчеты вроде не забыл, так что зацени, а потом го в комменты – обсудим вместе.</p>
<h2 id="что-там-в-отчетах">Что там в отчетах?</h2>
<p>Короче, за последние лет пять SRE стала прямо хайповой темой для исследований. Вот самые толковые источники, чтобы быть в теме, что в SRE происходит:</p>
<ul>
<li><strong>Catchpoint — The SRE Report</strong> (<a href="https://www.catchpoint.com/asset/2020-sre-report" rel="noopener noreferrer" target="_blank">2020</a>
, <a href="https://www.catchpoint.com/asset/2021-sre-report" rel="noopener noreferrer" target="_blank">2021</a>
, <a href="https://www.catchpoint.com/asset/2023-sre-report" rel="noopener noreferrer" target="_blank">2023</a>
, <a href="https://www.catchpoint.com/asset/2024-sre-report" rel="noopener noreferrer" target="_blank">2024</a>
, <a href="https://www.catchpoint.com/asset/2025-sre-report" rel="noopener noreferrer" target="_blank">2025</a>
): Это, наверное, самый жирный отчет прям по SRE. В 2025 опросили больше 300 спецов из разных областей. Говорят, это типа реальное мнение людей из SRE команд, без воды и прикрас.</li>
<li><strong>DORA (DevOps Research and Assessment)</strong>: Каждый год (<a href="https://dora.dev/research/2020/" rel="noopener noreferrer" target="_blank">2020</a>
, <a href="https://dora.dev/research/2021/" rel="noopener noreferrer" target="_blank">2021</a>
, <a href="https://dora.dev/research/2022/" rel="noopener noreferrer" target="_blank">2022</a>
, <a href="https://dora.dev/research/2023/" rel="noopener noreferrer" target="_blank">2023</a>
, <a href="https://dora.dev/research/2024/" rel="noopener noreferrer" target="_blank">2024</a>
, <a href="https://dora.dev/research/2022/" rel="noopener noreferrer" target="_blank">2025</a>
) катают отчеты, где уже лет десять меряют, насколько круто DevOps и SRE работают. Смотрят на четыре главные метрики. В 2025 даже целый отчет выпустили про то, как AI влияет на разработку.</li>
<li><strong><a href="https://www.devopsinstitute.com/global-sre-pulse/" rel="noopener noreferrer" target="_blank">DevOps Institute — Global SRE Pulse 2022</a>
</strong>: Это было первое большое исследование, где опросили больше 460 SRE спецов и манагеров из средних и больших компаний. В отчете можно глянуть, как сейчас вообще живёт SRE, какие штуки юзают, как команды себя чувствуют и насколько все заавтоматизировано.</li>
<li><strong><a href="https://www.puppet.com/resources/history-of-devops-reports" rel="noopener noreferrer" target="_blank">Puppet — State of DevOps</a>
</strong> (2020-2021, 2023): В 2021 отметили десятилетие этих отчетов и выяснили, что у 78% компаний с DevOps дела так себе, где-то на середине. В 2023 больше смотрели на платформенную инженерию.</li>
<li><strong>Forrester Research</strong> (<a href="https://www.forrester.com/report/five-key-trends-to-benchmark-devops-progress/RES120481" rel="noopener noreferrer" target="_blank">2020</a>
): Выкатили отчет про десять главных трендов в инфраструктуре и сказали, что SRE – это база для стабильной работы всего.</li>
<li><strong>Gartner Hype Cycle</strong> (<a href="https://www.gartner.com/en/articles/hype-cycle-for-emerging-technologies" rel="noopener noreferrer" target="_blank">2025</a>
): Закинули SRE и Platform Engineering на свой график взросления технологий. Ещё упомянули всякие приколы для управления окружениями, чтоб каждый мог сам себе все сделать.</li>
<li><strong>ThoughtWorks Technology Radar</strong> (постоянно, <a href="https://www.thoughtworks.com/radar/archive" rel="noopener noreferrer" target="_blank">2020-2025</a>
): Эти ребята вообще всегда следят, как меняются инструменты и практики в SRE, наблюдаемости и чтоб системы были надежными.</li>
</ul>
<h2 id="главные-изменения-в-sre">Главные изменения в SRE</h2>
<h3 id="1-рост-toil-неожиданный-поворот-в-2025">1. Рост Toil: неожиданный поворот в 2025</h3>
<p><em>Что-то пошло не так</em>: Впервые за пять лет нудной работы (Toil) стало больше. Раньше было 14% времени, а теперь все 20%. Задачи по операционке тоже времени жрут больше – теперь 30% вместо 20%.</p>
<p>Все думали, с AI станет легче. Эксперты из Catchpoint удивились: ждали, что AI уберет рутину, а он наоборот, ее добавил. Может, все дело в том, что AI помогает быстрее делать полезные вещи, а свободное время забивается всякой фигней.</p>
<p><em>Как было раньше</em>: С 2020 по 2024 нудной работы становилось все меньше. Спасибо автоматизации, IaC, CI/CD и системам, которые сами чинятся. Google советует, чтоб такой работы было не больше половины времени инженера, а у SRE – не больше половины на операционку.</p>
<p><strong>Как бороться с Toil в 2025</strong>:</p>
<ul>
<li>Автоматизация через Terraform, Ansible, CI/CD пайплайны.</li>
<li>Внедряйте self-healing системы, чтоб все чинилось само.</li>
<li>Стандартизируйте все через плейбуки и runbooks.</li>
<li>AIOps инструменты – чтобы алерты сами между собой разбирались и мониторили все на будущее.</li>
<li>Переходите на self-service порталы вместо тикетов.</li>
</ul>
<h3 id="2-ai-и-machine-learning-уже-не-просто-побаловаться-а-без-них-никуда">2. AI и Machine Learning: уже не просто побаловаться, а без них никуда</h3>
<p><strong>Как развивалось</strong>:</p>
<ul>
<li><strong>2020</strong>: Только начали пробовать AI в мониторинге и поиске аномалий.</li>
<li><strong>2021-2022</strong>: Все больше интересуются, как AI может предсказывать проблемы и автоматом чинить инциденты.</li>
<li><strong>2023-2024</strong>: Вовсю внедряют AIOps платформы (Datadog, Splunk, Dynatrace).</li>
<li><strong>2025</strong>: GenAI – это революция! 39% спецов говорят, что AI круто генерит код.</li>
</ul>
<p><strong>Где AI нужен в SRE 2025</strong>:</p>
<ul>
<li><strong>Предсказывать инциденты</strong>: AI изучает старые данные и говорит, где может рвануть.</li>
<li><strong>Автоматически генерить тесты</strong>: ML создает тесты, когда код меняется.</li>
<li><strong>AI помогает в ChatOps</strong>: встраивают LLM в процессы управления инцидентами.</li>
<li><strong>Системы, которые сами чинятся</strong>: AI находит аномалии и сам все исправляет.</li>
<li><strong>Улучшение производительности</strong>: AI анализирует, что можно улучшить в SLO.</li>
</ul>
<p><strong>Важный момент из DORA 2024</strong>: второй год подряд получается, что AI делает доставку софта хуже. Короче, AI – не волшебная таблетка, надо аккуратно внедрять и смотреть, что получается.</p>
<p><strong>Что думают про AI</strong>: 53% SRE думают, что AI сделает их работу легче, и только 4% боятся, что AI их заменит. При этом 30% решили, что надо учиться AI.</p>
<h3 id="3-platform-engineering-и-sre-теперь-вместе-навсегда">3. Platform Engineering и SRE: теперь вместе навсегда</h3>
<p><strong>Как менялись отношения</strong>:</p>
<ul>
<li><strong>2020</strong>: Platform Engineering как отдельную штуку вообще не выделяли, все было в DevOps.</li>
<li><strong>2021-2022</strong>: Начали говорить про Platform Engineering.</li>
<li><strong>2023</strong>: Puppet выпустили отчет State of Platform Engineering, и 93% сказали, что это круто.</li>
<li><strong>2024-2025</strong>: Platform Engineering и SRE активно работают вместе.</li>
</ul>
<p><strong>В чем разница и как помогают друг другу</strong>:</p>
<ul>
<li><strong>Platform Engineering</strong> создает платформы, чтобы разрабам было проще работать: self-service, не надо думать про инфраструктуру, все стандартизировано.</li>
<li><strong>SRE</strong> следит, чтоб все работало надежно, SLO выполнялись, мониторит продакшн, разруливает инциденты и чтоб всего было в меру – и новых фич, и стабильности.</li>
<li><strong>Вместе им хорошо</strong>: если платформа сделана правильно, то у SRE меньше Toil, потому что все деплоится по стандарту и куча задач автоматизирована. А SRE, в свою очередь, делает платформы надежнее.</li>
</ul>
<h3 id="4-finops-sre-теперь-еще-и-за-бабки-отвечает">4. FinOps: SRE теперь еще и за бабки отвечает</h3>
<p><strong>Как росла важность</strong>:</p>
<ul>
<li><strong>2020</strong>: Только начали понимать, что надо следить за расходами в облаке.</li>
<li><strong>2021-2022</strong>: FinOps стала отдельной темой.</li>
<li><strong>2023-2024</strong>: FinOps активно встраивается в SRE практики.</li>
<li><strong>2025</strong>: SRE команды вовсю юзают FinOps, чтобы тратить меньше денег в облаке.</li>
</ul>
<p><strong>Что SRE должны знать про FinOps</strong>:</p>
<ul>
<li>Ответственность за деньги – часть DevOps.</li>
<li>Как тратить меньше, но чтоб все работало надежно.</li>
<li>Как правильно выделять деньги на облачные ресурсы.</li>
<li>Оптимизация производительности за свои деньги.</li>
<li>Управление ресурсами.</li>
</ul>
<p>Catchpoint 2025 говорит, что Capacity Management теперь в приоритете у компаний, наравне с SRE, SLO и автоматизацией починки инцидентов.</p>
<h3 id="5-opentelemetry-все-стандартизировали-наблюдаемость">5. OpenTelemetry: все стандартизировали наблюдаемость</h3>
<p><strong>Как быстро все начали юзать</strong>:</p>
<ul>
<li><strong>2020</strong>: Никто толком не знал (~5%).</li>
<li><strong>2021-2022</strong>: Уже многие в теме (~20-25% планируют или юзают).</li>
<li><strong>2023-2024</strong>: Уже хорошо (~48% юзают).</li>
<li><strong>2025</strong>: Практически все (~73% юзают или собираются).</li>
</ul>
<p><strong>Почему это круто</strong>:</p>
<ul>
<li><strong>Стандартизация</strong>: один стандарт для всего – как собирать данные, как их отправлять.</li>
<li><strong>Не надо зависеть от поставщиков</strong>: можно не привязываться к конкретному вендору.</li>
<li><strong>ROI</strong>: 46% компаний говорят, что ROI больше 20%, а еще 40% – 10-20%.</li>
<li><strong>Экономия</strong>: 84% компаний, которые стали меньше тратить на observability, говорят, что сэкономили минимум 10%.</li>
<li><strong>Зрелость</strong>: 81% считают, что OpenTelemetry уже достаточно взрослая штука.</li>
</ul>
<p><strong>Почему это важно для AI-SRE</strong>: OpenTelemetry – это база для AI, потому что он дает одинаковые, понятные данные для анализа.</p>
<p><strong>Но есть и проблемы</strong>: сложно внедрить, данных становится слишком много (в 4-5 раз больше), надо интегрировать со старыми системами и следить за расходами.</p>
<h3 id="6-chaos-engineering-теперь-это-не-просто-прикол-а-необходимость">6. Chaos Engineering: теперь это не просто прикол, а необходимость</h3>
<p><strong>Как это стало популярно</strong>:</p>
<ul>
<li><strong>2020</strong>: Какая-то странная штука, которую Netflix придумал.</li>
<li><strong>2021</strong>: 60% спецов хоть раз пробовали chaos-эксперименты.</li>
<li><strong>2022-2023</strong>: Все больше компаний юзают это, чтобы проверять, как системы работают при сбоях.</li>
<li><strong>2024-2025</strong>: Chaos Engineering стал важной частью SRE.</li>
</ul>
<p><strong>Как это работает с SRE</strong>:</p>
<ul>
<li><strong>Проверка на отказоустойчивость</strong>: специально ломают систему, чтоб найти слабые места.</li>
<li><strong>Валидация SLO/SLI</strong>: убеждаются, что все работает, даже когда что-то идет не так.</li>
<li><strong>Подготовка к инцидентам</strong>: тренируются реагировать, чтоб пользователи ничего не заметили.</li>
<li><strong>Уменьшение Toil</strong>: автоматом проверяют отказоустойчивость через CI/CD.</li>
<li><strong>Быстрее чинят</strong>: если заранее знают, что может сломаться, то быстрее восстановят.</li>
</ul>
<p><strong>Популярные инструменты 2025</strong>: Qinfinite by Quinnox, Gremlin, Chaos Mesh, LitmusChaos, AWS Fault Injection Simulator.</p>
<p><strong>Важный момент</strong>: Chaos Engineering помогает создать атмосферу, где не ищут виноватых, а стараются улучшить систему.</p>
<h3 id="7-slo-и-error-budgets-все-становится-серьезно">7. SLO и Error Budgets: все становится серьезно</h3>
<p><strong>Как взрослели</strong>:</p>
<ul>
<li><strong>2020</strong>: Только начали внедрять SLO, но часто не понимали, зачем это.</li>
<li><strong>2021-2022</strong>: Стало больше понимания, но 99% SRE не знают, как правильно определить SLO.</li>
<li><strong>2023-2024</strong>: SLO стали важны при принятии решений.</li>
<li><strong>2025</strong>: SLO помогают решать, что важнее – надежность или новые фичи, появились composite SLO и reliability scoring.</li>
</ul>
<p><strong>Что нового в SLO</strong>:</p>
<ul>
<li><strong>Composite SLOs</strong>: объединяют несколько SLO в одну метрику, чтобы видеть картину целиком.</li>
<li><strong>Reliability scoring</strong>: оценивают надежность системы в цифрах.</li>
<li><strong>Мониторинг в реальном времени и алерты</strong>: помогают управлять SLO.</li>
<li><strong>SLO Development Life Cycle (SLODLC)</strong>: как правильно внедрять SLO.</li>
</ul>
<p><strong>Error Budget Management – это целый рынок</strong>: он вырос с $1.2 млрд в 2024 году и, по прогнозам, будет $5.8 млрд к 2033 году. Это значит, что DevOps, SRE и cloud-native технологии становятся все популярнее.</p>
<p><strong>Проблемы с SLO</strong>:</p>
<ul>
<li>51% считают, что observability не очень, особенно там, где мало инструментов.</li>
<li>SLO бесполезны, если их не использовать постоянно, потому что системы меняются.</li>
<li>Надо думать о пользователях: SLO должны показывать, что пользователи чувствуют, а не только технические метрики.</li>
</ul>
<h3 id="8-автоматизация-управления-инцидентами-и-aiops">8. Автоматизация управления инцидентами и AIOps</h3>
<p><strong>Как развивалось</strong>:</p>
<ul>
<li><strong>2020</strong>: Только начали автоматом делать алерты и тикеты.</li>
<li><strong>2021-2022</strong>: Активно развивали runbook automation и self-healing.</li>
<li><strong>2023-2024</strong>: Внедрили AIOps, чтобы связывать события и предсказывать проблемы.</li>
<li><strong>2025</strong>: AI помогает управлять инцидентами, общаться на обычном языке и автоматом искать причины проблем.</li>
</ul>
<p><strong>Как выглядит incident management в 2025</strong>:</p>
<ul>
<li><strong>Видят все в реальном времени</strong>: AI анализирует логи и события и сразу находит закономерности.</li>
<li><strong>Алерты на будущее</strong>: ML предсказывает, где может случиться инцидент.</li>
<li><strong>Автоматически чинят</strong>: системы сами исправляют проблемы, без людей.</li>
<li><strong>Все общаются в одном месте</strong>: все стейкхолдеры сидят в одной системе.</li>
<li><strong>Удобные workflows</strong>: инструменты для управления инцидентами работают прямо в Slack.</li>
</ul>
<p><strong>Важный момент</strong>: 40% инженеров участвовали в 1-5 инцидентах за последние 30 дней. При этом руководители тоже в деле, не меньше, чем обычные инженеры. 14% сильно стрессуют после инцидентов, потому что им не хватает поддержки.</p>
<p><strong>Как дела с incident management (Global SRE Pulse 2022)</strong>: больше 70% говорят, что у них хорошо спроектирован процесс управления инцидентами и алерты обрабатываются четко.</p>
<p><strong>Как AI все изменил в 2025</strong>:</p>
<ul>
<li>На 56% точнее находят угрозы, чем старые системы.</li>
<li>Анализ инцидентов занимает 2.8 минуты вместо 18.5.</li>
<li>Автоматизируют 78% действий при обычных инцидентах, раньше было 35%.</li>
<li>Ложных срабатываний стало меньше – с 25% до 8%.</li>
</ul>
<h3 id="9-надежность-vs-скорость-кто-победит">9. Надежность vs. скорость: кто победит?</h3>
<p><strong>Плохая новость</strong>: большинство спецов (больше двух третей) чувствуют, что их заставляют выпускать релизы быстрее, чем это безопасно для надежности.</p>
<p><strong>Почему так происходит</strong>:</p>
<ul>
<li><strong>Уходят те, кто создавал SRE</strong>: эксперты уходят из компаний, и приоритеты меняются.</li>
<li><strong>Бизнес давит</strong>: хотят новые фичи и больше денег.</li>
<li><strong>Не все понимают одинаково</strong>: инженеры и руководители по-разному оценивают надежность – чем выше должность, тем больше уверенности, что все хорошо.</li>
</ul>
<p><strong>Как было раньше</strong>: это старая проблема – что важнее, быстро или безопасно. SRE пытаются это решить с помощью error budgets и SLO. Но в 2025 давление стало слишком сильным.</p>
<p><strong>Что делать</strong>:</p>
<ul>
<li>Регулярно проверять и обновлять оценки процессов.</li>
<li>Звать внешних экспертов.</li>
<li>Улучшать культуру SRE и учить всех в компании, что надежность – это важно.</li>
<li>Использовать error budgets, чтобы принимать решения.</li>
</ul>
<h3 id="10-структуры-sre-команд-и-как-их-организовать">10. Структуры SRE-команд и как их организовать</h3>
<p><strong>Основные варианты</strong> (из книги Establishing SRE Foundations):</p>
<ol>
<li><strong>You Build It, You Run It</strong>: разрабы сами отвечают и за разработку, и за эксплуатацию. Быстро деплоят, но много операционных задач и сложно управлять изменениями.</li>
<li><strong>You Build It, SRE Run It</strong>: разрабы пилят код, SRE занимаются операционкой. Может случиться разрыв между командами.</li>
<li><strong>You Build It, You and SRE Run It</strong>: все в ответе вместе – SRE управляют операционными задачами, разрабы пишут код, но все вместе смотрят на метрики.</li>
</ol>
<p><strong>Где команда SRE находится в компании</strong> (Global SRE Pulse 2022):</p>
<ul>
<li>30% — IT operations</li>
<li>22% — отдельная команда</li>
<li>18% — application design &amp; development</li>
<li>18% — IT infrastructure</li>
<li>3% — IT security</li>
</ul>
<p><strong>Типы команд</strong>:</p>
<ul>
<li><strong>Centralized</strong>: помогают многим продуктам/сервисам.</li>
<li><strong>Dedicated</strong>: занимаются конкретными продуктами.</li>
<li><strong>Platform-based</strong>: строят облачные платформы.</li>
<li><strong>Stack-based</strong>: отдельные команды для разных стеков приложений/инфраструктуры.</li>
</ul>
<p><strong>Главное правило Google SRE</strong>: максимум 50% времени на операционку, минимум 50% на engineering (улучшения, автоматизация, исправление проблем).</p>
<h3 id="11-observability-от-мониторинга-к-ai">11. Observability: от мониторинга к AI</h3>
<p><strong>Как менялось</strong>:</p>
<ul>
<li><strong>2020</strong>: Просто мониторили (метрики, логи).</li>
<li><strong>2021-2022</strong>: Перешли к observability (метрики + логи + трассировки).</li>
<li><strong>2023-2024</strong>: Observability всего стека, смотрят на user experience.</li>
<li><strong>2025</strong>: AI сам находит полезную информацию в телеметрии.</li>
</ul>
<p><strong>Что важно в 2025</strong>:</p>
<ul>
<li><strong>Slow is the new down</strong>: 53% компаний согласны, что плохая производительность – это так же плохо, как если бы все упало.</li>
<li><strong>Много инструментов – это нормально</strong>: большинство компаний используют 2-10 инструментов для мониторинга/observability, и это не проблема, если они приносят пользу.</li>
<li><strong>Разные данные</strong>: 81% компаний используют 2+ типа телеметрии, 43% – 4+ типа.</li>
<li><strong>Что в приоритете</strong>: логи (65%), метрики (56%), события и трассировки.</li>
</ul>
<p><strong>Как все поменялось</strong>: раньше observability была нужна, чтобы люди могли понять терабайты данных. Сейчас, с AI, главное, чтобы машина могла быстро найти нужную информацию.</p>
<h3 id="12-обучение-и-развитие">12. Обучение и развитие</h3>
<p><strong>Учиться надо</strong>: технические тренинги очень важны, чтобы освоить новые технологии, включая AI. Но каждая пятая компания на это забивает.</p>
<p><strong>Как учатся</strong> (Catchpoint 2025):</p>
<ul>
<li>Онлайн-платформы (55%).</li>
<li>Очное обучение (45%).</li>
<li>Конференции (41%).</li>
</ul>
<p><strong>Странно</strong>: все говорят, что учиться важно, но времени нет. Руководители учатся меньше других и, наверное, думают, что им это не нужно.</p>
<p><strong>Важно для карьеры</strong>: DevOps Institute говорит, что SRE – это хороший способ продвинуться в IT, если прокачивать нужные навыки.</p>
<h2 id="выводы-и-что-будет-дальше">Выводы и что будет дальше</h2>
<h3 id="главное-из-анализа">Главное из анализа</h3>
<ol>
<li><strong>Странности 2025</strong>: несмотря на AI и автоматизацию, Toil впервые вырос за пять лет, и AI пока не оправдывает надежд. Значит, дело не только в технологиях, но и в культуре и правильном подходе.</li>
<li><strong>SRE взрослеет</strong>: SRE стала серьезной штукой – 62% компаний в той или иной степени используют SRE (19% во всей компании, 55% в отдельных командах, 23% пробуют). SLO, error budgets и chaos engineering – это уже не ново, а стандарт.</li>
<li><strong>Все работают вместе</strong>: SRE, Platform Engineering, DevOps, DevSecOps и FinOps – это не конкуренты, а друзья, которые помогают друг другу. Компании, которые это понимают, получают больше выгоды.</li>
<li><strong>AI – это помощник, а не замена</strong>: AI помогает инженерам, а не заменяет их. AI должен быть частью культуры и процессов.</li>
<li><strong>Культура важнее</strong>: Puppet 2021 показал, что 78% компаний застряли на середине пути в DevOps/SRE, потому что думают только о технологиях, а не о культуре. Надо менять культуру, а не просто внедрять новые инструменты.</li>
<li><strong>Надежность под угрозой</strong>: все хотят быстро, но забывают про надежность. Надо этим управлять с помощью error budgets, SLO и объяснять всем, что надежность – это важно.</li>
</ol>
<h3 id="что-ждет-нас-после-2025">Что ждет нас после 2025</h3>
<ul>
<li><strong>AI будет еще круче</strong>: AI будет лучше предсказывать проблемы, автоматом искать причины и чинить системы. Но важно помнить, что надо измерять, как AI влияет на производительность.</li>
<li><strong>Platform Engineering станет важнее</strong>: платформы будут строить по строгим правилам, чтобы разрабам было удобнее. Internal Developer Platforms (IDP) станут стандартом для больших компаний.</li>
<li><strong>Больше контроля</strong>: будут следить за тем, чтобы все было безопасно и надежно. Regulation as code станет важной темой.</li>
<li><strong>Инструменты станут проще</strong>: все инструменты DevOps/SRE объединят в одну платформу, чтобы было проще управлять.</li>
<li><strong>Экология</strong>: будут думать о том, как технологии влияют на экологию, и стараться делать все более зеленым.</li>
<li><strong>eBPF</strong>: будут больше использовать eBPF, чтобы видеть, что происходит внутри системы, без лишних инструментов.</li>
<li><strong>Kubernetes</strong>: Kubernetes останется главной системой для управления приложениями.</li>
<li><strong>Zero Trust</strong>: безопасность станет еще важнее, и будут использовать принципы Zero Trust.</li>
</ul>
<h3 id="что-посоветовать-компаниям">Что посоветовать компаниям</h3>
<ol>
<li><strong>Считайте Toil</strong>: регулярно проверяйте, сколько времени уходит на рутину, и выделяйте время на автоматизацию.</li>
<li><strong>Observability – это важно</strong>: переходите от простого мониторинга к полноценной observability с OpenTelemetry.</li>
<li><strong>SLO – это культура</strong>: SLO должны быть не просто цифрами, а частью процесса принятия решений.</li>
<li><strong>Пробуйте Chaos Engineering</strong>: начните с маленьких экспериментов в staging и постепенно переходите к production.</li>
<li><strong>Культура и люди</strong>: учите людей, создавайте атмосферу, где не боятся ошибаться, и поддерживайте друг друга.</li>
<li><strong>Не перегибайте с централизацией</strong>: выберите подходящую структуру SRE-команды, чтобы централизация помогала, а не мешала.</li>
<li><strong>Думайте, зачем вам AI</strong>: внедряйте AI, только если понимаете, какие проблемы он решает, и измеряйте результат.</li>
</ol>
<p>SRE продолжает развиваться и становится все важнее для компаний. Чтобы добиться успеха в SRE, нужно уметь соблюдать баланс – между технологиями и культурой, между новым и стабильным, между скоростью и надежностью. Компании, которые это понимают, будут готовы к будущему.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></content:encoded>
    </item><item>
      <title>Почему тебе НЕ стоит идти работать в АйТи</title>
      <link>https://jtprog.ru/posts/pochemu-ne-idti-v-it/</link>
      <pubDate>Tue, 23 Dec 2025 20:02:29 +0300</pubDate>
      <dc:creator>jtprogru</dc:creator>
      <guid isPermaLink="true">https://jtprog.ru/posts/pochemu-ne-idti-v-it/</guid>
      <category>Career</category>
      <category>Work</category>
      <category>It</category>
      <category>Burnout</category>
      <category>Reality</category>
      <category domain="category">Work</category>
      <enclosure url="https://jtprog.ru/work.png" type="image/jpeg" length="0" />
      <media:thumbnail url="https://jtprog.ru/work.png" /><description><![CDATA[<div><p>Привет, <code>%username%</code>! Слушай, прежде чем ты понесёшь свои кровные на очередные курсы «стань программистом за три месяца», давай честно поговорим о том, о чём тебе не расскажут продавцы этих самых курсов. Все эти истории про гибкий график, работу с ноутбуком на Бали и зарплаты в долларах — это как картинки в меню в забегаловке: выглядят аппетитно, а на деле ты получаешь совсем не то, что ожидал.</p>
<p>Я собрал для тебя реальные истории о рутинной, скучной, монотонной работе в АйТи — для каждой профессии отдельно. Потому что рутина везде своя, но одинаково тоскливая. Погнали разбираться.</p>
<h2 id="devopssre-инженер-добро-пожаловать-в-кошмар-247">DevOps/SRE инженер: добро пожаловать в кошмар 24/7</h2>
<p>Знаешь, что самое «клёвое» в работе DevOps-инженера? Возможность проснуться в 6 утра от звонка, когда у клиента упала нода в кластере БД. И это не какой-то редкий случай — это твоя новая реальность, которая будет случаться 1–2 раза в месяц. Только представь: ты ещё толком не проснулся, одним глазом смотришь в телефон, копируешь логи и машинально запускаешь стандартный набор инструментов восстановления.</p>
<h3 id="бесконечный-мониторинг">Бесконечный мониторинг</h3>
<p>Твой рабочий день начинается с проверки дашбордов. Grafana, Prometheus, Datadog — твои новые лучшие друзья. Ты часами смотришь на графики, анализируешь метрики: время отклика, загрузку CPU, потребление памяти. Звучит захватывающе? Попробуй делать это каждый день в течение года.</p>
<p>А ещё есть логи. Море логов. Океан логов. ELK-стек становится твоим вторым домом, где ты проводишь больше времени, чем в настоящем. Тебе нужно найти иголку в стоге сена — вот только стог размером с небоскрёб, а игла может быть где угодно.</p>
<h3 id="дежурства-и-инциденты">Дежурства и инциденты</h3>
<p>Помнишь, как тебе обещали гибкий график? Ну так вот, он действительно гибкий — гнётся во все стороны, только не в твою пользу. Ты дежуришь по ночам и выходным. Алерт может прилететь в любой момент. Семейный ужин? Прогулка с собакой? Извини, приятель, но продакшен горит, и тушить его будешь ты.</p>
<p>И после того как ты всё починил, наступает самое «весёлое» — написание отчёта клиенту. Нужно расписать, что произошло, почему произошло, как ты это починил и что сделал, чтобы это больше не повторилось. На 200 страниц. Потому что некоторые заказчики испытывают благоговейный ужас перед кипой бумаг.</p>
<h3 id="рутинная-автоматизация">Рутинная автоматизация</h3>
<p>Ирония в том, что половину своего времени ты тратишь на автоматизацию… чтобы автоматизировать рутину. Пишешь CI/CD-пайплайны, настраиваешь мониторинг, конфигурируешь инфраструктуру через Ansible или Terraform. Но это тоже рутина! Просто рутина для автоматизации рутины. Рутинный Inception, понимаешь?</p>
<p>По концепции SRE ты не должен тратить больше 50% времени на операционные задачи (toil). Звучит неплохо, правда? Только вот в реальности эти 50% превращаются в 80%, а оставшиеся 20% ты тратишь на то, чтобы объяснять менеджерам, почему у тебя нет времени на разработку.</p>
<h2 id="системный-администратор-а-можешь-включить-принтер">Системный администратор: &ldquo;а можешь включить принтер?&rdquo;</h2>
<p>Если ты думаешь, что системный администратор — это крутой хакер из фильмов, который взламывает Пентагон за пять минут, у меня для тебя плохие новости.</p>
<h3 id="техподдержка-first-line">Техподдержка first-line</h3>
<p>Реальная жизнь сисадмина выглядит так: ты бежишь в бухгалтерию, чтобы «включить процессор». Да-да, именно так пользователи называют системный блок. Или меняешь картридж в принтере. Снова. В третий раз за день. В том же самом принтере.</p>
<p>Тебе прилетает 5–10 заявок в день через ServiceDesk. «Не работает интернет» (кабель не воткнут), «Компьютер тормозит» (забита оперативка хромом с 50 вкладками), «Пропал Word» (иконку случайно удалили с рабочего стола). И так каждый день. Месяц за месяцем. Год за годом.</p>
<h3 id="обслуживание-инфраструктуры">Обслуживание инфраструктуры</h3>
<p>А ещё есть «настоящая» работа. Резервное копирование данных — каждый день, каждую ночь. Обновление систем — вручную, на каждом сервере. Проверка работоспособности — по списку, в Excel-табличке. Настройка учётных записей — одна за другой.</p>
<p>Знаешь, что самое страшное? «Панический ступор от осознания, что бэкапа нет, а ты только что отформатировал диск с документами целого отдела». Это не шутка. Это реальная история.</p>
<h3 id="работа-247">Работа 24/7</h3>
<p>Ты всегда на связи. Всегда. В отпуске, в выходные, на пляже с коктейлем. Бизнес не может обходиться без IT. Даже пробить товар невозможно без софта. Поэтому, когда что-то падает, — звонят тебе. В любое время суток.</p>
<p>Монотонность, усидчивость, умение выполнять однообразную работу — вот твои главные навыки. А ещё стрессоустойчивость, потому что работать приходится в ненормированном графике при постоянных форс-мажорах.</p>
<h2 id="программист-код-баги-рефакторинг-повтори">Программист: код, баги, рефакторинг, повтори</h2>
<p>Теперь — о самой, казалось бы, творческой профессии в АйТи. Спойлер: творчества там не больше, чем в работе на конвейере.</p>
<h3 id="backend-разработчик-crud-до-потери-пульса">Backend-разработчик: CRUD до потери пульса</h3>
<p>CRUD: Create, Read, Update, Delete. Четыре операции, которые ты будешь писать до конца своих дней. Создать запись в базе, прочитать, обновить, удалить. Снова и снова. С разными таблицами, разными сущностями, но суть одна и та же.</p>
<p>API-endpoints. Сотни, тысячи API-endpoints. Принять запрос, валидировать данные, сделать запрос в базу, отдать ответ. Меняются только названия. Для разнообразия можешь добавить аутентификацию и авторизацию — но это тоже шаблонный код.</p>
<p>А ещё есть legacy. Старый код, написанный предыдущим разработчиком, который давно уволился и теперь занимается разведением кроликов на даче. Тебе нужно разобраться в этом коде, понять логику (если она там есть) и что-то исправить. «Тебе приходится исправлять написанный не очень хорошо проект за кем-то. Это в итоге выходит дороже, чем если бы его изначально дали мне».</p>
<h3 id="frontend-разработчик-подвигай-кнопку">Frontend-разработчик: подвигай кнопку</h3>
<p>«Одна кнопка — одна задача на день». Это не преувеличение, это реальность многих фронтендеров. Вся логика на бэке, а ты просто двигаешь элементы туда-сюда. «Подвигать кнопку или перекрасить её».</p>
<p>Адаптация под разные браузеры и устройства. Chrome, Firefox, Safari, Edge. Desktop, tablet, mobile. Android, iOS. И у каждого свои приколы. То, что работает в Chrome, падает в Safari. То, что красиво на desktop, разваливается на mobile.</p>
<p>Работа с отступами. «14px вместо 16px, нарушая дефолтные шаги в 8px». Дизайнер внезапно решает, что нужен отступ не 16, а 14 пикселей. Зачем? А фиг его знает. Просто так захотелось. И ты меняешь эти 2 пикселя во всём проекте.</p>
<h3 id="общая-рутина-для-всех">Общая рутина для всех</h3>
<p>Код-ревью. Часами. Днями. Проверять чужой код, оставлять комментарии, спорить о том, нужна ли тут переменная или можно инлайнить. «Раздражает проверка pull request. Это может продолжаться часами (и днями!)».</p>
<p>Написание документации. Это не просто скучно — это смертельно скучно. «Раздражает создавать и упорядочивать документацию. В процессе бывает сложно перевести знания в голове на человеческий язык».</p>
<p>Тестирование. Написание тестов. Перезапуск тестов. Запустил тест — упал. Починил — запустил снова. Упал в другом месте. И так по кругу.</p>
<h2 id="qa-тестировщик-регресс-регресс-регресс">QA-тестировщик: регресс, регресс, регресс</h2>
<p>Думаешь, тестировщики просто играют в игры или тыкают в приложения? Ха. Если бы.</p>
<h3 id="регрессионное-тестирование">Регрессионное тестирование</h3>
<p>«Регрессионное тестирование — сотый раз прогонять». Представь, что тебя заставляют играть в одну и ту же игру, проходить один и тот же уровень, ровно по тому же маршруту, делать те же действия. Сто раз подряд. А потом ещё сто.</p>
<p>Smoke-тесты после каждого деплоя. Один и тот же набор проверок: открыть приложение, залогиниться, открыть главную страницу, проверить основные функции. И так после каждого обновления.</p>
<p>«Играть в одно и то же раз за разом». Это не просто скучно — это убивает мотивацию. «Чаще всего работа трудная, но интересная. Иногда — безумно скучная».</p>
<h3 id="документация-test-кейсов">Документация test-кейсов</h3>
<p>Составление подробных тест-кейсов. Шаг 1: открыть приложение. Шаг 2: нажать на кнопку входа. Шаг 3: ввести логин. Шаг 4: ввести пароль. И так на 100 шагов для одного простого сценария. А сценариев — сотни.</p>
<p>Баг-репорты. Каждый баг нужно задокументировать: что делал, что ожидал, что получил, окружение, версия билда, шаги для воспроизведения. И таких багов в день может быть десятки.</p>
<p>Поддержание документации в актуальном состоянии. Изменилась кнопка — нужно обновить все тест-кейсы, где она упоминается. Добавился новый экран — нужно написать новые тест-кейсы. Бесконечная рутина.</p>
<h2 id="team-lead--tech-lead-совещания-вместо-кода">Team Lead / Tech Lead: совещания вместо кода</h2>
<p>Ты думал стать лидером, чтобы больше влиять на проект? Приятель, у меня для тебя новости.</p>
<h3 id="встречи-встречи-встречи">Встречи, встречи, встречи</h3>
<p>«Марафон встреч на несколько часов». Ежедневные стендапы, груминги, планирования, ретроспективы, one-to-one-встречи. Твой календарь похож на тетрис, где каждый блок — это совещание. И между этими блоками нет места для того, чтобы что-то сделать.</p>
<p>Утро начинается с дейли. Потом — планирование спринта. После обеда — груминг бэклога. Вечером — one-to-one с разработчиками. А между всем этим нужно ещё и работу делать. Когда? После работы. Ночью. На выходных.</p>
<h3 id="код-ревью-как-основная-работа">Код-ревью как основная работа</h3>
<p>Проверка pull request&rsquo;ов. Это теперь не просто часть твоей работы — это основная часть. Ты проверяешь код, оставляешь комментарии, споришь с разработчиками о том, почему этот подход лучше или хуже. Часами.</p>
<p>Парное программирование с джунами. Объяснять базовые вещи. Показывать, как правильно. Смотреть, как они делают ошибки, которые ты совершал пять лет назад. Терпеть и снова объяснять.</p>
<h3 id="административная-рутина">Административная рутина</h3>
<p>Распределение задач: кому что дать, кто с чем справится, у кого какая загрузка. Excel-таблички или Jira-борды — твои новые инструменты.</p>
<p>Решение конфликтов. Вася не может работать с Петей, потому что они поругались из-за подхода к написанию тестов. Маша выгорает, потому что все задачи скучные. Коля хочет уйти, потому что нет карьерного роста.</p>
<p>Заполнение отчётов: что сделали, сколько времени потратили, какие проблемы возникли, какие планы на следующую неделю. Каждую неделю. Каждый спринт. Каждый месяц.</p>
<h2 id="product-manager-созвоны-метрики-согласования">Product Manager: созвоны, метрики, согласования</h2>
<p>PM — это человек, который общается. Много общается. Очень много общается. И потом ещё немного общается.</p>
<h3 id="марафон-встреч">Марафон встреч</h3>
<p>Типичный день продакта: «утренний скрам, архитектурный созвон, созвон с клиентом, синк с инженерами, груминг бэклога». Твой день — это бесконечная череда встреч. Созвон за созвоном, без перерывов.</p>
<p>С 11 до 14:00, иногда до 16:00 — ты в постоянной коммуникации. Команда, клиенты, стейкхолдеры, партнёры. Все хотят с тобой поговорить. Все хотят что-то обсудить. Все хотят твоего внимания.</p>
<p>Focus time? Первые пару часов утром, до того как начнутся встречи. Вот это твоё время, чтобы подумать, написать документацию, сформулировать гипотезы. А потом — добро пожаловать в марафон.</p>
<h3 id="проверка-метрик-каждое-утро">Проверка метрик каждое утро</h3>
<p>«Первым делом всегда смотрю все метрики по продукту на дашборде». Каждый день. Без исключений. Retention, NPS, конверсия, активность пользователей, revenue. Цифры, цифры, цифры.</p>
<p>Анализ результатов A/B-тестов. Запустили тест — нужно посмотреть результаты. Победила версия B — нужно раскатать на всех. Не сработало — нужно понять, почему, и придумать новую гипотезу.</p>
<h3 id="документация-документация-документация">Документация, документация, документация</h3>
<p>Написание ТЗ и требований. Для каждой фичи нужно написать, что хотим сделать, зачем, для кого, как это будет выглядеть, как это должно работать.</p>
<p>Подготовка бизнес-планов. Что даст эта фича, как будем измерять успех, какие метрики должны вырасти, на сколько, почему именно на столько.</p>
<p>Формирование бэклога. Приоритизация задач: что делаем сейчас, что потом, что не делаем вообще. И объяснение команде, почему именно в таком порядке.</p>
<h2 id="data-scientist-80-времени-на-подготовку-данных">Data Scientist: 80% времени на подготовку данных</h2>
<p>Забудь про крутые нейросети и машинное обучение. Реальность DS — это работа с данными. Очень. Долгая. Работа. С. Данными.</p>
<h3 id="разметка-очистка-препроцессинг">Разметка, очистка, препроцессинг</h3>
<p>«Data scientist тратит большую часть своего времени на сбор, разметку, классификацию данных». Не на обучение моделей. Не на анализ. На работу с сырыми данными.</p>
<p>Разметка данных. Вручную. Тысячи, десятки тысяч образцов. «Это кошка. Это собака. Это тоже кошка. А это размытая фигня, которую хрен пойми что».</p>
<p>Очистка данных. Удаление дубликатов, обработка пропусков, исправление ошибок, нормализация форматов. Excel, Python, pandas — твои инструменты. Рутина — твоя реальность.</p>
<h3 id="документация-на-200-страниц">Документация на 200 страниц</h3>
<p>«Написание 200 страниц текста для заказчика». Техническая документация, сопроводительная документация. Описание модели, описание данных, описание метрик, описание результатов.</p>
<p>«Что, как, почему именно так». Каждое решение нужно обосновать: почему выбрали эту модель, а не ту; почему эти гиперпараметры, а не другие; почему эта метрика, а не другая.</p>
<h3 id="работа-в-изоляции">Работа в изоляции</h3>
<p>«Data scientists в итоге работают одни, даже если сидят за тем же столом, что и разработчики». Один DS на всю команду. Не с кем посоветоваться, не с кем обсудить подходы.</p>
<p>«Рассчитывают финансы в Excel». Иногда вместо машинного обучения ты просто заполняешь Excel-таблички. Потому что бизнесу нужен быстрый результат, а не красивая модель.</p>
<h2 id="it-архитектор-документация-и-согласования">IT-архитектор: документация и согласования</h2>
<p>Ты думал, будешь проектировать крутые системы? Будешь. Но сначала напишешь 300 страниц документации.</p>
<h3 id="рутина-документации">Рутина документации</h3>
<p>«Подготовка документации по проектам. Рутины более чем достаточно». Техническая документация, архитектурная документация, пользовательская документация.</p>
<p>«Вычертить огромный генплан месяцами». Схемы, диаграммы, чертежи. Одно и то же, но с небольшими вариациями. Для одного проекта. Потом для другого. Потом для третьего.</p>
<p>Проектирование типовых проектов («коробок»). Не каждый раз что-то новое. Часто — одно и то же, со стандартными решениями, стандартными подходами.</p>
<h3 id="согласования">Согласования</h3>
<p>Координация команды. Распределение задач, контроль сроков, проверка качества. People management, как ни крути.</p>
<p>Согласования с бизнесом. Объяснять, почему это решение лучше, почему оно стоит таких денег, почему нужно столько времени. Презентации, совещания, обоснования.</p>
<h2 id="дизайнер-правки-правки-ещё-правки">Дизайнер: правки, правки, ещё правки</h2>
<p>«Бесконечные правки, а потом просят вернуться к первоначальному варианту».</p>
<h3 id="рутинные-задачи">Рутинные задачи</h3>
<p>Разработка технических эскизов. Создание макетов. Адаптация под разные разрешения. Экспорт в разные форматы. Подготовка ассетов для разработчиков.</p>
<p>Многочасовые правки. Клиент посмотрел — что-то не нравится. Изменил — опять не то. Сделал как было в начале — вот теперь хорошо. Три дня работы — в урну.</p>
<p>Монотонность и выгорание. «Дизайнер заставляет себя работать над рутинным процессом, пока все однотипные и скучные задачи не будут завершены».</p>
<h2 id="общие-паттерны-рутины-что-объединяет-всех">Общие паттерны рутины: что объединяет всех</h2>
<p>Изучив десятки источников и истории реальных людей, я вывел паттерны, которые присутствуют в каждой АйТи-профессии:</p>
<h3 id="1-документация--бесит-всех">1. Документация — бесит всех</h3>
<p>От джуна до архитектора, от тестировщика до продакта — все ненавидят писать документацию. Но все обязаны это делать. Снова и снова.</p>
<h3 id="2-встречи-вместо-работы">2. Встречи вместо работы</h3>
<p>Стендапы, планирования, груминги, ретро, синки, one-to-one. Твой день превращается в марафон встреч, между которыми нужно ещё и работу делать.</p>
<h3 id="3-legacy-код-и-технический-долг">3. Legacy-код и технический долг</h3>
<p>«30% всего объёма работ по итогу не используется». Работа в стол. Или работа с кодом, который написали пять лет назад и который теперь никто не понимает.</p>
<h3 id="4-работа-247">4. Работа 24/7</h3>
<p>Особенно для DevOps, SRE, сисадминов. Ты всегда на связи. Отпуск, выходные, праздники — неважно. Если упало — звонят тебе.</p>
<h3 id="5-выгорание-через-рутину">5. Выгорание через рутину</h3>
<p>«78% ИТ-работников страдают от выгорания». «89% специалистов трудятся в режиме 5/2, 69% работают сверхурочно и дома». Монотонные задачи, большая нагрузка, постоянный стресс.</p>
<h3 id="6-ненормированный-рабочий-день">6. Ненормированный рабочий день</h3>
<p>Никаких доплат за переработку. В качестве компенсации — три дополнительных дня отпуска. И это в лучшем случае. А в худшем — просто работай больше за те же деньги.</p>
<h3 id="7-можно-легко-разлюбить-свою-работу">7. &ldquo;Можно легко разлюбить свою работу&rdquo;</h3>
<p>«Проблемы имеют свойство накапливаться как снежный ком. Большой технический долг, давление руководства, административно-бюрократические проблемы — если не уметь с этим справляться, можно легко разлюбить свою работу».</p>
<h2 id="итого-суровая-правда-о-работе-в-айти">Итого: суровая правда о работе в АйТи</h2>
<p>Знаешь, что самое смешное? Я не придумал ничего из этого. Всё, что ты прочитал выше, — это реальные истории реальных людей.</p>
<p>АйТи — это не работа мечты с кофе на Бали. Это рутина, стресс, выгорание и постоянное ощущение, что ты бежишь на месте.</p>
<p>Это ненормированный рабочий день, где «гибкий график» означает «работай, когда хочешь, но 24/7». Это постоянное обучение, потому что технологии устаревают быстрее, чем молоко в холодильнике.</p>
<p>Это работа, где «30% всего объёма работ по итогу не используется». Где проекты закрываются на полпути. Где требования меняются каждую неделю.</p>
<h3 id="но-стоит-ли-оно-того">Но стоит ли оно того?</h3>
<p>Если после всего прочитанного ты всё ещё хочешь в АйТи — значит, это твоё. Потому что, несмотря на всю эту рутину, в АйТи есть кайф от решённой сложной задачи. Есть драйв от того, что твой код работает на миллионах устройств. Есть удовлетворение от автоматизации, которая избавляет людей от рутины (хотя и создаёт свою).</p>
<p>Но если ты идёшь в АйТи за «лёгкими деньгами», «гибким графиком» и «работой на Бали» — разворачивайся и уходи. Потому что это миф. Красивая сказка, которую рассказывают продавцы курсов.</p>
<p>Реальность — она другая. Реальность — это твой 50-й pull request за день, 20-е совещание за неделю, 100-й регресс-тест за месяц. Реальность — это алерт в 3 часа ночи и вопрос «а где бэкап?».</p>
<p>И знаешь что? Многим это нравится. Потому что рутина — это часть работы. Любой работы. В АйТи, как и везде, есть своя грязная работа, которую кто-то должен делать.</p>
<p>Так что решай сам. Я просто показал тебе, что находится за красивой витриной «работы мечты в АйТи». А дальше — твой выбор.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице «<a href="https://jtprog.ru/donations/">Донаты</a>
».</p>
</div>]]></description>
      <content:encoded><![CDATA[<style>/* Inline-CSS, который тема вкладывает в <description> каждого item'а
   RSS-фида (layouts/index.rss.xml). RSS-ридеры (Feedly, Inoreader,
   NetNewsWire) уважают <style> внутри description с переменной
   степенью энтузиазма — это базовый fallback, достаточный для читаемой
   типографики, не более.

   Цвета продублированы из 00-vars.css (light-палитра) — поправь
   синхронно при изменении --bg / --text / --accent / --border. */

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  line-height: 1.6;
  color: #1c1c1f;
  max-width: 720px;
  margin: 0 auto;
  padding: 1em;
}
h1, h2, h3 { line-height: 1.25; margin-top: 1.4em; }
a { color: #c2410c; }
pre {
  background: #1e1e24;
  color: #e8e6df;
  padding: 1em;
  border-radius: 6px;
  overflow-x: auto;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.9em;
}
code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  background: #f3f1ed;
  padding: 0.1em 0.4em;
  border-radius: 4px;
}
pre code { background: transparent; padding: 0; }
blockquote {
  border-left: 3px solid #c2410c;
  padding-left: 1em;
  color: #5b5b62;
  font-style: italic;
  margin-left: 0;
}
img { max-width: 100%; height: auto; border-radius: 6px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #e5e3dc; padding: 6px 10px; text-align: left; }
</style><div><p>Привет, <code>%username%</code>! Слушай, прежде чем ты понесёшь свои кровные на очередные курсы «стань программистом за три месяца», давай честно поговорим о том, о чём тебе не расскажут продавцы этих самых курсов. Все эти истории про гибкий график, работу с ноутбуком на Бали и зарплаты в долларах — это как картинки в меню в забегаловке: выглядят аппетитно, а на деле ты получаешь совсем не то, что ожидал.</p>
<p>Я собрал для тебя реальные истории о рутинной, скучной, монотонной работе в АйТи — для каждой профессии отдельно. Потому что рутина везде своя, но одинаково тоскливая. Погнали разбираться.</p>
<h2 id="devopssre-инженер-добро-пожаловать-в-кошмар-247">DevOps/SRE инженер: добро пожаловать в кошмар 24/7</h2>
<p>Знаешь, что самое «клёвое» в работе DevOps-инженера? Возможность проснуться в 6 утра от звонка, когда у клиента упала нода в кластере БД. И это не какой-то редкий случай — это твоя новая реальность, которая будет случаться 1–2 раза в месяц. Только представь: ты ещё толком не проснулся, одним глазом смотришь в телефон, копируешь логи и машинально запускаешь стандартный набор инструментов восстановления.</p>
<h3 id="бесконечный-мониторинг">Бесконечный мониторинг</h3>
<p>Твой рабочий день начинается с проверки дашбордов. Grafana, Prometheus, Datadog — твои новые лучшие друзья. Ты часами смотришь на графики, анализируешь метрики: время отклика, загрузку CPU, потребление памяти. Звучит захватывающе? Попробуй делать это каждый день в течение года.</p>
<p>А ещё есть логи. Море логов. Океан логов. ELK-стек становится твоим вторым домом, где ты проводишь больше времени, чем в настоящем. Тебе нужно найти иголку в стоге сена — вот только стог размером с небоскрёб, а игла может быть где угодно.</p>
<h3 id="дежурства-и-инциденты">Дежурства и инциденты</h3>
<p>Помнишь, как тебе обещали гибкий график? Ну так вот, он действительно гибкий — гнётся во все стороны, только не в твою пользу. Ты дежуришь по ночам и выходным. Алерт может прилететь в любой момент. Семейный ужин? Прогулка с собакой? Извини, приятель, но продакшен горит, и тушить его будешь ты.</p>
<p>И после того как ты всё починил, наступает самое «весёлое» — написание отчёта клиенту. Нужно расписать, что произошло, почему произошло, как ты это починил и что сделал, чтобы это больше не повторилось. На 200 страниц. Потому что некоторые заказчики испытывают благоговейный ужас перед кипой бумаг.</p>
<h3 id="рутинная-автоматизация">Рутинная автоматизация</h3>
<p>Ирония в том, что половину своего времени ты тратишь на автоматизацию… чтобы автоматизировать рутину. Пишешь CI/CD-пайплайны, настраиваешь мониторинг, конфигурируешь инфраструктуру через Ansible или Terraform. Но это тоже рутина! Просто рутина для автоматизации рутины. Рутинный Inception, понимаешь?</p>
<p>По концепции SRE ты не должен тратить больше 50% времени на операционные задачи (toil). Звучит неплохо, правда? Только вот в реальности эти 50% превращаются в 80%, а оставшиеся 20% ты тратишь на то, чтобы объяснять менеджерам, почему у тебя нет времени на разработку.</p>
<h2 id="системный-администратор-а-можешь-включить-принтер">Системный администратор: &ldquo;а можешь включить принтер?&rdquo;</h2>
<p>Если ты думаешь, что системный администратор — это крутой хакер из фильмов, который взламывает Пентагон за пять минут, у меня для тебя плохие новости.</p>
<h3 id="техподдержка-first-line">Техподдержка first-line</h3>
<p>Реальная жизнь сисадмина выглядит так: ты бежишь в бухгалтерию, чтобы «включить процессор». Да-да, именно так пользователи называют системный блок. Или меняешь картридж в принтере. Снова. В третий раз за день. В том же самом принтере.</p>
<p>Тебе прилетает 5–10 заявок в день через ServiceDesk. «Не работает интернет» (кабель не воткнут), «Компьютер тормозит» (забита оперативка хромом с 50 вкладками), «Пропал Word» (иконку случайно удалили с рабочего стола). И так каждый день. Месяц за месяцем. Год за годом.</p>
<h3 id="обслуживание-инфраструктуры">Обслуживание инфраструктуры</h3>
<p>А ещё есть «настоящая» работа. Резервное копирование данных — каждый день, каждую ночь. Обновление систем — вручную, на каждом сервере. Проверка работоспособности — по списку, в Excel-табличке. Настройка учётных записей — одна за другой.</p>
<p>Знаешь, что самое страшное? «Панический ступор от осознания, что бэкапа нет, а ты только что отформатировал диск с документами целого отдела». Это не шутка. Это реальная история.</p>
<h3 id="работа-247">Работа 24/7</h3>
<p>Ты всегда на связи. Всегда. В отпуске, в выходные, на пляже с коктейлем. Бизнес не может обходиться без IT. Даже пробить товар невозможно без софта. Поэтому, когда что-то падает, — звонят тебе. В любое время суток.</p>
<p>Монотонность, усидчивость, умение выполнять однообразную работу — вот твои главные навыки. А ещё стрессоустойчивость, потому что работать приходится в ненормированном графике при постоянных форс-мажорах.</p>
<h2 id="программист-код-баги-рефакторинг-повтори">Программист: код, баги, рефакторинг, повтори</h2>
<p>Теперь — о самой, казалось бы, творческой профессии в АйТи. Спойлер: творчества там не больше, чем в работе на конвейере.</p>
<h3 id="backend-разработчик-crud-до-потери-пульса">Backend-разработчик: CRUD до потери пульса</h3>
<p>CRUD: Create, Read, Update, Delete. Четыре операции, которые ты будешь писать до конца своих дней. Создать запись в базе, прочитать, обновить, удалить. Снова и снова. С разными таблицами, разными сущностями, но суть одна и та же.</p>
<p>API-endpoints. Сотни, тысячи API-endpoints. Принять запрос, валидировать данные, сделать запрос в базу, отдать ответ. Меняются только названия. Для разнообразия можешь добавить аутентификацию и авторизацию — но это тоже шаблонный код.</p>
<p>А ещё есть legacy. Старый код, написанный предыдущим разработчиком, который давно уволился и теперь занимается разведением кроликов на даче. Тебе нужно разобраться в этом коде, понять логику (если она там есть) и что-то исправить. «Тебе приходится исправлять написанный не очень хорошо проект за кем-то. Это в итоге выходит дороже, чем если бы его изначально дали мне».</p>
<h3 id="frontend-разработчик-подвигай-кнопку">Frontend-разработчик: подвигай кнопку</h3>
<p>«Одна кнопка — одна задача на день». Это не преувеличение, это реальность многих фронтендеров. Вся логика на бэке, а ты просто двигаешь элементы туда-сюда. «Подвигать кнопку или перекрасить её».</p>
<p>Адаптация под разные браузеры и устройства. Chrome, Firefox, Safari, Edge. Desktop, tablet, mobile. Android, iOS. И у каждого свои приколы. То, что работает в Chrome, падает в Safari. То, что красиво на desktop, разваливается на mobile.</p>
<p>Работа с отступами. «14px вместо 16px, нарушая дефолтные шаги в 8px». Дизайнер внезапно решает, что нужен отступ не 16, а 14 пикселей. Зачем? А фиг его знает. Просто так захотелось. И ты меняешь эти 2 пикселя во всём проекте.</p>
<h3 id="общая-рутина-для-всех">Общая рутина для всех</h3>
<p>Код-ревью. Часами. Днями. Проверять чужой код, оставлять комментарии, спорить о том, нужна ли тут переменная или можно инлайнить. «Раздражает проверка pull request. Это может продолжаться часами (и днями!)».</p>
<p>Написание документации. Это не просто скучно — это смертельно скучно. «Раздражает создавать и упорядочивать документацию. В процессе бывает сложно перевести знания в голове на человеческий язык».</p>
<p>Тестирование. Написание тестов. Перезапуск тестов. Запустил тест — упал. Починил — запустил снова. Упал в другом месте. И так по кругу.</p>
<h2 id="qa-тестировщик-регресс-регресс-регресс">QA-тестировщик: регресс, регресс, регресс</h2>
<p>Думаешь, тестировщики просто играют в игры или тыкают в приложения? Ха. Если бы.</p>
<h3 id="регрессионное-тестирование">Регрессионное тестирование</h3>
<p>«Регрессионное тестирование — сотый раз прогонять». Представь, что тебя заставляют играть в одну и ту же игру, проходить один и тот же уровень, ровно по тому же маршруту, делать те же действия. Сто раз подряд. А потом ещё сто.</p>
<p>Smoke-тесты после каждого деплоя. Один и тот же набор проверок: открыть приложение, залогиниться, открыть главную страницу, проверить основные функции. И так после каждого обновления.</p>
<p>«Играть в одно и то же раз за разом». Это не просто скучно — это убивает мотивацию. «Чаще всего работа трудная, но интересная. Иногда — безумно скучная».</p>
<h3 id="документация-test-кейсов">Документация test-кейсов</h3>
<p>Составление подробных тест-кейсов. Шаг 1: открыть приложение. Шаг 2: нажать на кнопку входа. Шаг 3: ввести логин. Шаг 4: ввести пароль. И так на 100 шагов для одного простого сценария. А сценариев — сотни.</p>
<p>Баг-репорты. Каждый баг нужно задокументировать: что делал, что ожидал, что получил, окружение, версия билда, шаги для воспроизведения. И таких багов в день может быть десятки.</p>
<p>Поддержание документации в актуальном состоянии. Изменилась кнопка — нужно обновить все тест-кейсы, где она упоминается. Добавился новый экран — нужно написать новые тест-кейсы. Бесконечная рутина.</p>
<h2 id="team-lead--tech-lead-совещания-вместо-кода">Team Lead / Tech Lead: совещания вместо кода</h2>
<p>Ты думал стать лидером, чтобы больше влиять на проект? Приятель, у меня для тебя новости.</p>
<h3 id="встречи-встречи-встречи">Встречи, встречи, встречи</h3>
<p>«Марафон встреч на несколько часов». Ежедневные стендапы, груминги, планирования, ретроспективы, one-to-one-встречи. Твой календарь похож на тетрис, где каждый блок — это совещание. И между этими блоками нет места для того, чтобы что-то сделать.</p>
<p>Утро начинается с дейли. Потом — планирование спринта. После обеда — груминг бэклога. Вечером — one-to-one с разработчиками. А между всем этим нужно ещё и работу делать. Когда? После работы. Ночью. На выходных.</p>
<h3 id="код-ревью-как-основная-работа">Код-ревью как основная работа</h3>
<p>Проверка pull request&rsquo;ов. Это теперь не просто часть твоей работы — это основная часть. Ты проверяешь код, оставляешь комментарии, споришь с разработчиками о том, почему этот подход лучше или хуже. Часами.</p>
<p>Парное программирование с джунами. Объяснять базовые вещи. Показывать, как правильно. Смотреть, как они делают ошибки, которые ты совершал пять лет назад. Терпеть и снова объяснять.</p>
<h3 id="административная-рутина">Административная рутина</h3>
<p>Распределение задач: кому что дать, кто с чем справится, у кого какая загрузка. Excel-таблички или Jira-борды — твои новые инструменты.</p>
<p>Решение конфликтов. Вася не может работать с Петей, потому что они поругались из-за подхода к написанию тестов. Маша выгорает, потому что все задачи скучные. Коля хочет уйти, потому что нет карьерного роста.</p>
<p>Заполнение отчётов: что сделали, сколько времени потратили, какие проблемы возникли, какие планы на следующую неделю. Каждую неделю. Каждый спринт. Каждый месяц.</p>
<h2 id="product-manager-созвоны-метрики-согласования">Product Manager: созвоны, метрики, согласования</h2>
<p>PM — это человек, который общается. Много общается. Очень много общается. И потом ещё немного общается.</p>
<h3 id="марафон-встреч">Марафон встреч</h3>
<p>Типичный день продакта: «утренний скрам, архитектурный созвон, созвон с клиентом, синк с инженерами, груминг бэклога». Твой день — это бесконечная череда встреч. Созвон за созвоном, без перерывов.</p>
<p>С 11 до 14:00, иногда до 16:00 — ты в постоянной коммуникации. Команда, клиенты, стейкхолдеры, партнёры. Все хотят с тобой поговорить. Все хотят что-то обсудить. Все хотят твоего внимания.</p>
<p>Focus time? Первые пару часов утром, до того как начнутся встречи. Вот это твоё время, чтобы подумать, написать документацию, сформулировать гипотезы. А потом — добро пожаловать в марафон.</p>
<h3 id="проверка-метрик-каждое-утро">Проверка метрик каждое утро</h3>
<p>«Первым делом всегда смотрю все метрики по продукту на дашборде». Каждый день. Без исключений. Retention, NPS, конверсия, активность пользователей, revenue. Цифры, цифры, цифры.</p>
<p>Анализ результатов A/B-тестов. Запустили тест — нужно посмотреть результаты. Победила версия B — нужно раскатать на всех. Не сработало — нужно понять, почему, и придумать новую гипотезу.</p>
<h3 id="документация-документация-документация">Документация, документация, документация</h3>
<p>Написание ТЗ и требований. Для каждой фичи нужно написать, что хотим сделать, зачем, для кого, как это будет выглядеть, как это должно работать.</p>
<p>Подготовка бизнес-планов. Что даст эта фича, как будем измерять успех, какие метрики должны вырасти, на сколько, почему именно на столько.</p>
<p>Формирование бэклога. Приоритизация задач: что делаем сейчас, что потом, что не делаем вообще. И объяснение команде, почему именно в таком порядке.</p>
<h2 id="data-scientist-80-времени-на-подготовку-данных">Data Scientist: 80% времени на подготовку данных</h2>
<p>Забудь про крутые нейросети и машинное обучение. Реальность DS — это работа с данными. Очень. Долгая. Работа. С. Данными.</p>
<h3 id="разметка-очистка-препроцессинг">Разметка, очистка, препроцессинг</h3>
<p>«Data scientist тратит большую часть своего времени на сбор, разметку, классификацию данных». Не на обучение моделей. Не на анализ. На работу с сырыми данными.</p>
<p>Разметка данных. Вручную. Тысячи, десятки тысяч образцов. «Это кошка. Это собака. Это тоже кошка. А это размытая фигня, которую хрен пойми что».</p>
<p>Очистка данных. Удаление дубликатов, обработка пропусков, исправление ошибок, нормализация форматов. Excel, Python, pandas — твои инструменты. Рутина — твоя реальность.</p>
<h3 id="документация-на-200-страниц">Документация на 200 страниц</h3>
<p>«Написание 200 страниц текста для заказчика». Техническая документация, сопроводительная документация. Описание модели, описание данных, описание метрик, описание результатов.</p>
<p>«Что, как, почему именно так». Каждое решение нужно обосновать: почему выбрали эту модель, а не ту; почему эти гиперпараметры, а не другие; почему эта метрика, а не другая.</p>
<h3 id="работа-в-изоляции">Работа в изоляции</h3>
<p>«Data scientists в итоге работают одни, даже если сидят за тем же столом, что и разработчики». Один DS на всю команду. Не с кем посоветоваться, не с кем обсудить подходы.</p>
<p>«Рассчитывают финансы в Excel». Иногда вместо машинного обучения ты просто заполняешь Excel-таблички. Потому что бизнесу нужен быстрый результат, а не красивая модель.</p>
<h2 id="it-архитектор-документация-и-согласования">IT-архитектор: документация и согласования</h2>
<p>Ты думал, будешь проектировать крутые системы? Будешь. Но сначала напишешь 300 страниц документации.</p>
<h3 id="рутина-документации">Рутина документации</h3>
<p>«Подготовка документации по проектам. Рутины более чем достаточно». Техническая документация, архитектурная документация, пользовательская документация.</p>
<p>«Вычертить огромный генплан месяцами». Схемы, диаграммы, чертежи. Одно и то же, но с небольшими вариациями. Для одного проекта. Потом для другого. Потом для третьего.</p>
<p>Проектирование типовых проектов («коробок»). Не каждый раз что-то новое. Часто — одно и то же, со стандартными решениями, стандартными подходами.</p>
<h3 id="согласования">Согласования</h3>
<p>Координация команды. Распределение задач, контроль сроков, проверка качества. People management, как ни крути.</p>
<p>Согласования с бизнесом. Объяснять, почему это решение лучше, почему оно стоит таких денег, почему нужно столько времени. Презентации, совещания, обоснования.</p>
<h2 id="дизайнер-правки-правки-ещё-правки">Дизайнер: правки, правки, ещё правки</h2>
<p>«Бесконечные правки, а потом просят вернуться к первоначальному варианту».</p>
<h3 id="рутинные-задачи">Рутинные задачи</h3>
<p>Разработка технических эскизов. Создание макетов. Адаптация под разные разрешения. Экспорт в разные форматы. Подготовка ассетов для разработчиков.</p>
<p>Многочасовые правки. Клиент посмотрел — что-то не нравится. Изменил — опять не то. Сделал как было в начале — вот теперь хорошо. Три дня работы — в урну.</p>
<p>Монотонность и выгорание. «Дизайнер заставляет себя работать над рутинным процессом, пока все однотипные и скучные задачи не будут завершены».</p>
<h2 id="общие-паттерны-рутины-что-объединяет-всех">Общие паттерны рутины: что объединяет всех</h2>
<p>Изучив десятки источников и истории реальных людей, я вывел паттерны, которые присутствуют в каждой АйТи-профессии:</p>
<h3 id="1-документация--бесит-всех">1. Документация — бесит всех</h3>
<p>От джуна до архитектора, от тестировщика до продакта — все ненавидят писать документацию. Но все обязаны это делать. Снова и снова.</p>
<h3 id="2-встречи-вместо-работы">2. Встречи вместо работы</h3>
<p>Стендапы, планирования, груминги, ретро, синки, one-to-one. Твой день превращается в марафон встреч, между которыми нужно ещё и работу делать.</p>
<h3 id="3-legacy-код-и-технический-долг">3. Legacy-код и технический долг</h3>
<p>«30% всего объёма работ по итогу не используется». Работа в стол. Или работа с кодом, который написали пять лет назад и который теперь никто не понимает.</p>
<h3 id="4-работа-247">4. Работа 24/7</h3>
<p>Особенно для DevOps, SRE, сисадминов. Ты всегда на связи. Отпуск, выходные, праздники — неважно. Если упало — звонят тебе.</p>
<h3 id="5-выгорание-через-рутину">5. Выгорание через рутину</h3>
<p>«78% ИТ-работников страдают от выгорания». «89% специалистов трудятся в режиме 5/2, 69% работают сверхурочно и дома». Монотонные задачи, большая нагрузка, постоянный стресс.</p>
<h3 id="6-ненормированный-рабочий-день">6. Ненормированный рабочий день</h3>
<p>Никаких доплат за переработку. В качестве компенсации — три дополнительных дня отпуска. И это в лучшем случае. А в худшем — просто работай больше за те же деньги.</p>
<h3 id="7-можно-легко-разлюбить-свою-работу">7. &ldquo;Можно легко разлюбить свою работу&rdquo;</h3>
<p>«Проблемы имеют свойство накапливаться как снежный ком. Большой технический долг, давление руководства, административно-бюрократические проблемы — если не уметь с этим справляться, можно легко разлюбить свою работу».</p>
<h2 id="итого-суровая-правда-о-работе-в-айти">Итого: суровая правда о работе в АйТи</h2>
<p>Знаешь, что самое смешное? Я не придумал ничего из этого. Всё, что ты прочитал выше, — это реальные истории реальных людей.</p>
<p>АйТи — это не работа мечты с кофе на Бали. Это рутина, стресс, выгорание и постоянное ощущение, что ты бежишь на месте.</p>
<p>Это ненормированный рабочий день, где «гибкий график» означает «работай, когда хочешь, но 24/7». Это постоянное обучение, потому что технологии устаревают быстрее, чем молоко в холодильнике.</p>
<p>Это работа, где «30% всего объёма работ по итогу не используется». Где проекты закрываются на полпути. Где требования меняются каждую неделю.</p>
<h3 id="но-стоит-ли-оно-того">Но стоит ли оно того?</h3>
<p>Если после всего прочитанного ты всё ещё хочешь в АйТи — значит, это твоё. Потому что, несмотря на всю эту рутину, в АйТи есть кайф от решённой сложной задачи. Есть драйв от того, что твой код работает на миллионах устройств. Есть удовлетворение от автоматизации, которая избавляет людей от рутины (хотя и создаёт свою).</p>
<p>Но если ты идёшь в АйТи за «лёгкими деньгами», «гибким графиком» и «работой на Бали» — разворачивайся и уходи. Потому что это миф. Красивая сказка, которую рассказывают продавцы курсов.</p>
<p>Реальность — она другая. Реальность — это твой 50-й pull request за день, 20-е совещание за неделю, 100-й регресс-тест за месяц. Реальность — это алерт в 3 часа ночи и вопрос «а где бэкап?».</p>
<p>И знаешь что? Многим это нравится. Потому что рутина — это часть работы. Любой работы. В АйТи, как и везде, есть своя грязная работа, которую кто-то должен делать.</p>
<p>Так что решай сам. Я просто показал тебе, что находится за красивой витриной «работы мечты в АйТи». А дальше — твой выбор.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице «<a href="https://jtprog.ru/donations/">Донаты</a>
».</p>
</div>]]></content:encoded>
    </item><item>
      <title>Мониторинг бизнес-метрик: как понять, что твой сервис действительно работает</title>
      <link>https://jtprog.ru/posts/business-metrics/</link>
      <pubDate>Mon, 22 Dec 2025 10:23:38 +0300</pubDate>
      <dc:creator>jtprogru</dc:creator>
      <guid isPermaLink="true">https://jtprog.ru/posts/business-metrics/</guid>
      <category>Monitoring</category>
      <category>SRE</category>
      <category>DevOps</category>
      <category>Metrics</category>
      <category>Business</category>
      <category>Analytics</category>
      <category>Observability</category>
      <category domain="category">Work</category>
      <enclosure url="https://jtprog.ru/work.png" type="image/jpeg" length="0" />
      <media:thumbnail url="https://jtprog.ru/work.png" /><description><![CDATA[<div><p>Привет, <code>%username%</code>! Сегодня поговорим о теме, которая часто остается в тени инфраструктурного мониторинга, но при этом не менее важна — о <strong>мониторинге бизнес-метрик</strong>. Если ты SRE, DevOps или TeamLead, то наверняка сталкивался с ситуацией: все графики зеленые, CPU не плавится, память в норме, а бизнес приходит и говорит &ldquo;что-то не работает&rdquo;. И вот тут начинается самое интересное.</p>
<h2 id="зачем-вообще-нужны-бизнес-метрики">Зачем вообще нужны бизнес-метрики?</h2>
<p>Давай начнем с простого вопроса: зачем мы вообще запускаем сервисы? Правильно — чтобы они <strong>решали чьи-то проблемы и приносили деньги</strong>. И вот тут классический технический мониторинг начинает пробуксовывать. Ты можешь знать, что у тебя загрузка CPU 15%, время выполнения запроса (latency) 50ms, а количество 500-ошибок в пределах нормы. Но ты <strong>не знаешь</strong>, сколько пользователей прямо сейчас платят за твой сервис, какой процент из них доходит до формы оплаты, и приносит ли вообще твой продукт деньги.</p>
<p>Представь себе ситуацию: твой сайт работает отлично с технической точки зрения, но пользователи не могут найти кнопку оплаты, потому что она потерялась где-то внизу страницы после последнего релиза. Инфраструктурный мониторинг тебе об этом <strong>не скажет</strong>. А вот бизнес-метрики — скажут сразу, как только конверсия в оплату упадет.</p>
<h2 id="три-слоя-мониторинга-от-железа-до-бизнеса">Три слоя мониторинга: от железа до бизнеса</h2>
<p>В НСПК (Национальная система платежных карт, те самые ребята, что делают карты &ldquo;Мир&rdquo;) придерживаются подхода, который я считаю очень правильным: сервис нужно раскладывать на три слоя, и <strong>мониторить строго сверху вниз</strong>.</p>
<p><strong>Бизнес-слой</strong> — это то, что видит конечный пользователь. Для платежной системы это объемы успешных авторизационных запросов, количество операций по типам, время обработки платежей. Для интернет-магазина — это количество успешных заказов, средний чек, конверсия в покупку. Для SaaS-продукта — количество активных подписок, revenue per user, churn rate.</p>
<p><strong>Прикладной слой</strong> — данные о работе приложений: статусы модулей, метрики используемого ПО, технические логи. Тут уже можно задействовать готовые экспортеры и интеграции.</p>
<p><strong>Инфраструктурный слой</strong> — классика: CPU, память, диск, сеть, состояние железа.</p>
<p>Почему именно сверху вниз? Потому что <strong>бизнес-метрики — это главное</strong>. Если у тебя бизнес-метрики в порядке, но один из серверов немного подгружен — это не критично. А вот если бизнес-метрики падают, даже при зеленой инфраструктуре — это уже проблема, которую надо расследовать немедленно.</p>
<h2 id="методологии-мониторинга-use-red-и-uca">Методологии мониторинга: USE, RED и UCA</h2>
<p>Существует несколько классических подходов к сбору метрик, и каждый из них решает свою задачу.</p>
<h3 id="use-метод-следим-за-ресурсами">USE-метод: следим за ресурсами</h3>
<p><strong>USE</strong> — это акроним от <strong>Utilization, Saturation, Errors</strong> (Утилизация, Насыщение, Ошибки). Метод предложил Brendan Gregg, и он отлично работает для <strong>низкоуровневых метрик</strong>.</p>
<p>Если упростить, то для каждого ресурса системы (CPU, память, диск, сеть) ты смотришь три показателя:</p>
<ul>
<li><strong>Utilization</strong> — насколько загружен ресурс (например, CPU загружен на 80%)</li>
<li><strong>Saturation</strong> — есть ли очередь к ресурсу (например, 10 процессов ждут своей очереди на выполнение)</li>
<li><strong>Errors</strong> — количество ошибок, которые возвращает этот ресурс</li>
</ul>
<p>USE помогает быстро выявить узкие места в системе. Если у тебя диск утилизирован на 100%, а очередь на запись растет — вот тебе и проблема.</p>
<h3 id="red-метод-следим-за-сервисами">RED-метод: следим за сервисами</h3>
<p><strong>RED</strong> — это <strong>Rate, Errors, Duration</strong> (Скорость, Ошибки, Продолжительность). Метод предложил Tom Wilkie специально для <strong>микросервисных архитектур</strong>.</p>
<p>Для каждого сервиса ты отслеживаешь:</p>
<ul>
<li><strong>Rate</strong> — количество запросов в секунду</li>
<li><strong>Errors</strong> — количество неудачных запросов в секунду</li>
<li><strong>Duration</strong> — время обработки каждого запроса</li>
</ul>
<p>RED дает тебе возможность посмотреть на систему <strong>глазами пользователя</strong>. Если у тебя растет количество ошибок или увеличивается время ответа — пользователи это сразу почувствуют. Метод отлично работает для веб-сервисов, API, баз данных — везде, где есть концепция &ldquo;запрос-ответ&rdquo;.</p>
<h3 id="uca-метод-следим-за-бизнесом">UCA-метод: следим за бизнесом</h3>
<p>И вот мы подходим к самому интересному — <strong>UCA</strong> (Users, Conversions, Activity). Этот метод предложил Mike Julian, и он <strong>целенаправленно нацелен на измерение бизнес-метрик</strong>.</p>
<p><strong>Users</strong> (Пользователи) — кто является пользователями твоего сервиса? Для разных отраслей это могут быть разные показатели: количество активных пользователей, посетителей на сайте, звонков в колл-центр, покупателей в час.</p>
<p><strong>Conversions</strong> (Конверсии) — это про то, как пользователь приносит доход твоему сервису. Купил подписку? Забронировал номер в отеле? Оформил заказ? Это всё конверсии.</p>
<p><strong>Activity</strong> (Активность) — показывает, что пользователи <strong>продолжают</strong> пользоваться твоим продуктом. Входы на сайт, просмотры товаров, добавления в корзину, время на сайте.</p>
<p>UCA позволяет собирать метрики, которые показывают, <strong>как бизнес себя чувствует</strong>. И отталкиваясь от этих метрик, ты уже можешь искать проблемы на уровне USE и RED — понимать, из-за ухудшения каких показателей стоит поднимать инженеров.</p>
<h2 id="какие-метрики-собирать-на-практике">Какие метрики собирать на практике</h2>
<p>Давай конкретнее. Вот список метрик, которые стоит отслеживать на разных уровнях:</p>
<p><strong>Мониторинг бизнес-метрик:</strong></p>
<ul>
<li>Сколько пользователей зарегистрировано в системе?</li>
<li>Сколько пользуется приложением раз в день/неделю/месяц (DAU/WAU/MAU)?</li>
<li>Какой процент людей после регистрации доходит до формы оплаты?</li>
<li>Сколько они платят (средний чек, медианный чек)?</li>
<li>Как люди пользуются услугами — какие фичи популярны, а какие нет?</li>
<li>Какова общая выручка и прибыль?</li>
</ul>
<p><strong>Мониторинг состояния приложений:</strong></p>
<ul>
<li>Количество запросов в единицу времени (RPS)</li>
<li>Количество активных пользователей в системе</li>
<li>Количество записей в БД (общее и новых в единицу времени)</li>
<li>Количество ошибок в сервисе</li>
<li>Время выполнения запросов или latency (50-й, 95-й, 99-й процентили)</li>
</ul>
<p><strong>Мониторинг оборудования:</strong></p>
<ul>
<li>Нагрузка на CPU</li>
<li>Свободное место в RAM</li>
<li>Свободное место на дисках</li>
<li>Нагрузка на сеть</li>
<li>IOPS на дисках</li>
<li>Количество запущенных процессов</li>
</ul>
<h2 id="инструменты-для-мониторинга-бизнес-метрик">Инструменты для мониторинга бизнес-метрик</h2>
<p>Теперь поговорим об инструментах. В идеальном мире у тебя должен быть стек, который покрывает все три уровня.</p>
<h3 id="для-бизнес-метрик-google-analytics-и-яндексметрика">Для бизнес-метрик: Google Analytics и Яндекс.Метрика</h3>
<p>Если речь идет о веб-сервисах, то <strong>Google Analytics</strong> и <strong>Яндекс.Метрика</strong> — это базовый минимум. Они позволяют отслеживать базовые переходы и конверсии готовыми средствами.</p>
<p>Яндекс.Метрика особенно хороша для российского рынка — она корректнее учитывает трафик из Яндекса, работает в соответствии с ФЗ-152, и у нее интуитивный интерфейс для русскоязычных пользователей. Google Analytics дает больше возможностей для крупных проектов с большими объемами данных (до 200 000 запросов в сутки против 5000 у Метрики).</p>
<p>Но если тебе нужно <strong>углубленное понимание</strong> — придется работать в связке с разработкой. Настроить сбор кастомных метрик, которые важны именно для твоего продукта.</p>
<h3 id="для-прикладных-метрик-prometheus--grafana">Для прикладных метрик: Prometheus + Grafana</h3>
<p><strong>Prometheus</strong> — это система сбора и хранения метрик временных рядов, которую изначально разработали в SoundCloud. Она стала стандартом де-факто для сбора метрик в современных инфраструктурах.</p>
<p><strong>Grafana</strong> — универсальная обертка для визуализации. Она сама ничего не собирает и не хранит, но умеет красиво отображать данные из Prometheus, PostgreSQL, ClickHouse и еще десятков источников.</p>
<p>Связка <strong>Prometheus + Grafana</strong> позволяет собирать как технические метрики (через экспортеры — node_exporter для системных метрик, nginx-prometheus-exporter для Nginx и т.д.), так и <strong>бизнес-метрики</strong> твоего приложения. Да-да, Prometheus прекрасно справляется со сбором бизнес-метрик: выручка за день, количество активных пользователей, количество заказов — достаточно сделать свой endpoint <code>/metrics</code> в приложении и экспортировать туда нужные данные.</p>
<h3 id="для-операционной-аналитики-splunk">Для операционной аналитики: Splunk</h3>
<p>В НСПК для комплексного анализа используют <strong>Splunk</strong> — платформу операционной аналитики. Splunk умеет:</p>
<ul>
<li>Анализировать тысячи метрик в фоновом режиме с использованием статистических анализаторов</li>
<li>Обнаруживать аномалии и делать прогнозы с помощью машинного обучения</li>
<li>Создавать сложные параметризованные отчеты для дежурной службы</li>
<li>Коррелировать данные из разных источников</li>
</ul>
<p>Splunk — это уже не просто мониторинг, а <strong>платформа для принятия решений</strong>. Он позволяет не только видеть, что что-то пошло не так, но и понимать, <strong>почему</strong> это произошло, и <strong>как это влияет на бизнес</strong>.</p>
<h3 id="для-логирования-elk-stack">Для логирования: ELK Stack</h3>
<p><strong>ELK</strong> (Elasticsearch, Logstash, Kibana) или его альтернатива <strong>EFK</strong> (где вместо Logstash используется Fluentd) — это стек для агрегации и анализа логов.</p>
<p>Когда у тебя есть бизнес-метрики и прикладные метрики, логи становятся третьим измерением, которое помогает <strong>расследовать инциденты</strong>. Ты видишь на графике, что конверсия упала в 14:37, переходишь в логи и находишь, что именно в это время начались ошибки при работе с платежным шлюзом.</p>
<h2 id="как-выстраивать-систему-мониторинга">Как выстраивать систему мониторинга</h2>
<p>Теперь самое важное — <strong>как это всё организовать</strong>.</p>
<h3 id="строй-ресурсно-сервисную-модель">Строй ресурсно-сервисную модель</h3>
<p>Первый шаг — понять, что именно ты мониторишь. В НСПК разделяют данные на три слоя, а в большой компании нужна еще и <strong>ресурсно-сервисная модель</strong> (РСМ) — структурированное описание того, какие компоненты обеспечивают работу конкретного сервиса.</p>
<p>Например, сервис &ldquo;Интернет-магазин&rdquo; состоит из:</p>
<ul>
<li>Frontend (Nginx, React-приложение)</li>
<li>Backend API (несколько микросервисов на Java)</li>
<li>База данных (PostgreSQL)</li>
<li>Кэш (Redis)</li>
<li>Очередь сообщений (RabbitMQ)</li>
<li>Платежный шлюз (внешний API)</li>
</ul>
<p>Для каждого компонента ты настраиваешь сбор метрик на всех трех уровнях. И когда бизнес-метрика &ldquo;конверсия в оплату&rdquo; начинает падать, ты уже знаешь, на какие компоненты смотреть.</p>
<h3 id="используй-зонтичный-мониторинг">Используй &ldquo;зонтичный&rdquo; мониторинг</h3>
<p>Одна из лучших практик — использовать <strong>&ldquo;зонтик&rdquo;</strong>, единый слой, который агрегирует данные от различных систем: Zabbix, Prometheus, ELK, и т.д.. Это дает целостную картину и упрощает анализ.</p>
<p>Представь: у тебя Prometheus собирает метрики приложений, Zabbix мониторит железо, ELK собирает логи, а Google Analytics собирает поведенческие данные. Если у каждой команды свой дашборд в своем инструменте — <strong>корреляцию данных не увидеть</strong>. А вот если всё это агрегировано в одном месте (например, в Grafana или Splunk) — картина становится прозрачной.</p>
<h3 id="настраивай-алерты-правильно">Настраивай алерты правильно</h3>
<p><strong>Система оповещений</strong> — это компонент мониторинга, который выполняет действия на основе изменений метрик. Основная цель алертов — <strong>привлечь внимание человека</strong> к текущему состоянию системы.</p>
<p>Важные моменты:</p>
<ul>
<li>Алерт должен содержать информацию о том, <strong>что</strong> пошло не так и <strong>где</strong> найти дополнительную информацию</li>
<li>Не алерть на всё подряд — это приводит к &ldquo;усталости от алертов&rdquo;</li>
<li>Настраивай алерты сначала на <strong>бизнес-метрики</strong>, потом на прикладные, и только в конце — на инфраструктурные</li>
</ul>
<p>Например, алерт &ldquo;CPU загружен на 80%&rdquo; — это информационный сигнал. А вот &ldquo;Конверсия в оплату упала на 50% за последние 10 минут&rdquo; — это уже <strong>критический инцидент</strong>, который требует немедленного реагирования.</p>
<h3 id="делай-метрики-прозрачными-для-всех">Делай метрики прозрачными для всех</h3>
<p>Один из ключевых принципов — <strong>все члены команды должны видеть одну и ту же информацию из одного источника</strong>. QA, разработчики, админы, аналитики, менеджеры продукта — все должны смотреть на одни и те же дашборды.</p>
<p>Когда у всех единая точка входа, начинает работать <strong>коллективный разум</strong>. Разработчик может заметить, что после его релиза упала конверсия. Админ увидит, что в момент падения бизнес-метрики начались таймауты при обращении к базе. Аналитик обратит внимание, что падение началось после того, как изменилась логика расчета скидок. Вместе они найдут причину быстрее.</p>
<h2 id="ошибки-которых-стоит-избегать">Ошибки, которых стоит избегать</h2>
<p>Давай поговорим о том, чего <strong>не надо</strong> делать.</p>
<h3 id="ошибка-1-отсутствие-связи-между-бизнес-задачами-и-аналитикой">Ошибка 1: Отсутствие связи между бизнес-задачами и аналитикой</h3>
<p>Самая частая проблема — когда ты собираешь метрики &ldquo;потому что так надо&rdquo;, но не понимаешь, <strong>зачем</strong> ты их собираешь.</p>
<p>Правильный подход: начинай с бизнес-целей. Бизнес хочет увеличить выручку на 20%? Отлично, декомпозируй это на метрики: нужно увеличить количество заказов или средний чек? Если заказы — то нужно больше пользователей или выше конверсия существующих? И так далее.</p>
<h3 id="ошибка-2-мониторинг-без-проверок-качества-данных">Ошибка 2: Мониторинг без проверок качества данных</h3>
<p>Представь: ты построил красивый дашборд, но данные в него приходят с ошибками. Счетчик установлен не на всех страницах. Конверсионные события дублируются. В результате твои метрики показывают 30% конверсии, а на самом деле она 3%.</p>
<p><strong>Проверяй качество данных</strong>: делай периодические проверки полноты и согласованности, тестируй бизнес-правила, отслеживай источники данных и трансформации.</p>
<h3 id="ошибка-3-плавающее-руководство-по-сбору-данных">Ошибка 3: &ldquo;Плавающее&rdquo; руководство по сбору данных</h3>
<p>Когда у тебя нет четкого стандарта, как называть метрики, как их собирать, и где их хранить — начинается хаос. Один разработчик называет метрику <code>orders_count</code>, другой — <code>order.count</code>, третий — <code>OrdersTotal</code>. В итоге ты не можешь нормально искать и агрегировать данные.</p>
<p><strong>Установи стандарты</strong>: naming conventions для метрик, формат лейблов, структуру дашбордов. И следи, чтобы все их соблюдали.</p>
<h3 id="ошибка-4-разрозненные-данные">Ошибка 4: Разрозненные данные</h3>
<p>Когда метрики инфраструктуры хранятся в Zabbix, прикладные — в Prometheus, бизнесовые — в Google Analytics, а логи — в ELK, и всё это <strong>никак не связано</strong> между собой — ты не можешь проводить корреляцию.</p>
<p><strong>Стремись к единой точке анализа</strong>: используй зонтичный мониторинг, настраивай интеграции между системами, делай так, чтобы все данные были доступны в одном месте.</p>
<h3 id="ошибка-5-исправление-ошибок-по-факту">Ошибка 5: Исправление ошибок &ldquo;по факту&rdquo;</h3>
<p>Если у тебя нет мониторинга, ты узнаешь о проблемах только тогда, когда <strong>клиенты начинают жаловаться</strong>. И это очень дорого — и в деньгах, и в репутации.</p>
<p>Мониторинг — это <strong>профилактика</strong>. Гораздо дешевле обнаружить проблему на графике и исправить её до того, как она повлияла на пользователей, чем тушить пожар, когда половина клиентов уже не может сделать заказ.</p>
<h2 id="практический-чек-лист">Практический чек-лист</h2>
<p>Если ты хочешь построить нормальную систему мониторинга бизнес-метрик, вот тебе чек-лист для самопроверки:</p>
<p><strong>Базовый уровень:</strong></p>
<ul>
<li><input disabled="" type="checkbox"> Определен список основных бизнес-метрик (выручка, количество заказов, конверсии)</li>
<li><input disabled="" type="checkbox"> Бизнес-метрики декомпозированы от уровня руководства до команд</li>
<li><input disabled="" type="checkbox"> Определены сопутствующие метрики (MAU, количество товаров в чеке и т.д.)</li>
<li><input disabled="" type="checkbox"> Определен список прикладных метрик (RPS, latency, error rate)</li>
<li><input disabled="" type="checkbox"> Для каждой метрики определен период обратной связи (как часто проверять)</li>
</ul>
<p><strong>Продвинутый уровень:</strong></p>
<ul>
<li><input disabled="" type="checkbox"> Определены и автоматизированы источники данных по всем метрикам</li>
<li><input disabled="" type="checkbox"> Определены события/встречи, на которых обсуждаются метрики</li>
<li><input disabled="" type="checkbox"> Планирование работы осуществляется на основании метрик</li>
<li><input disabled="" type="checkbox"> Для каждой задачи есть понимание, на какую метрику она влияет</li>
<li><input disabled="" type="checkbox"> Все заинтересованные лица имеют доступ к метрикам</li>
<li><input disabled="" type="checkbox"> Есть система алертинга на критические изменения метрик</li>
</ul>
<p><strong>Экспертный уровень:</strong></p>
<ul>
<li><input disabled="" type="checkbox"> Используется зонтичный мониторинг, агрегирующий данные из всех систем</li>
<li><input disabled="" type="checkbox"> Настроена корреляция между метриками разных уровней</li>
<li><input disabled="" type="checkbox"> Внедрены проверки качества данных</li>
<li><input disabled="" type="checkbox"> Существует документированный стандарт сбора и именования метрик</li>
<li><input disabled="" type="checkbox"> Метрики используются для принятия бизнес-решений</li>
</ul>
<h2 id="выводы">Выводы</h2>
<p>Мониторинг бизнес-метрик — это не просто &ldquo;давайте нарисуем еще один дашборд в Grafana&rdquo;. Это <strong>комплексный подход</strong> к пониманию того, как работает твой продукт с точки зрения бизнеса.</p>
<p>Ключевые мысли:</p>
<ol>
<li><strong>Мониторь сверху вниз</strong>: начинай с бизнес-метрик, потом прикладные, и только в конце инфраструктурные</li>
<li><strong>Используй правильные методологии</strong>: USE для ресурсов, RED для сервисов, UCA для бизнеса</li>
<li><strong>Стремись к единой точке анализа</strong>: все команды должны смотреть на одни и те же данные</li>
<li><strong>Автоматизируй сбор данных</strong>: ручной сбор метрик — это прошлый век</li>
<li><strong>Делай метрики основой для принятия решений</strong>: не просто смотри на графики, а делай выводы и действуй</li>
</ol>
<p>Управление проектом без метрик — это как плавание ночью на корабле без карты и навигации. Ты вроде бы куда-то плывешь, но рано или поздно это закончится плохо.</p>
<p>А с правильно настроенным мониторингом бизнес-метрик ты <strong>всегда знаешь</strong>, где ты находишься, куда движешься, и что нужно исправить, чтобы прийти к цели.</p>
<h3 id="полезные-ссылки">Полезные ссылки</h3>
<ul>
<li><a href="https://habr.com/ru/company/nspk/blog/523352/" rel="noopener noreferrer" target="_blank">Как устроен прикладной и бизнес-мониторинг сервисов НСПК</a>
 — про трехслойную модель мониторинга</li>
<li><a href="https://logrocon.ru/news/monitoring" rel="noopener noreferrer" target="_blank">Основы мониторинга и сбора метрик</a>
 — про методологии USE, RED, UCA</li>
<li><a href="https://otus.ru/nest/post/1988/" rel="noopener noreferrer" target="_blank">Мониторинг событий и бизнес-метрик</a>
 — про важность метрик для бизнеса</li>
<li><a href="https://vc.ru/u/744996-evgeniy-ivanov/216307-pro-biznes-i-metriki" rel="noopener noreferrer" target="_blank">Про бизнес и метрики</a>
 — про структуру и типы метрик</li>
</ul>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></description>
      <content:encoded><![CDATA[<style>/* Inline-CSS, который тема вкладывает в <description> каждого item'а
   RSS-фида (layouts/index.rss.xml). RSS-ридеры (Feedly, Inoreader,
   NetNewsWire) уважают <style> внутри description с переменной
   степенью энтузиазма — это базовый fallback, достаточный для читаемой
   типографики, не более.

   Цвета продублированы из 00-vars.css (light-палитра) — поправь
   синхронно при изменении --bg / --text / --accent / --border. */

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  line-height: 1.6;
  color: #1c1c1f;
  max-width: 720px;
  margin: 0 auto;
  padding: 1em;
}
h1, h2, h3 { line-height: 1.25; margin-top: 1.4em; }
a { color: #c2410c; }
pre {
  background: #1e1e24;
  color: #e8e6df;
  padding: 1em;
  border-radius: 6px;
  overflow-x: auto;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.9em;
}
code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  background: #f3f1ed;
  padding: 0.1em 0.4em;
  border-radius: 4px;
}
pre code { background: transparent; padding: 0; }
blockquote {
  border-left: 3px solid #c2410c;
  padding-left: 1em;
  color: #5b5b62;
  font-style: italic;
  margin-left: 0;
}
img { max-width: 100%; height: auto; border-radius: 6px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #e5e3dc; padding: 6px 10px; text-align: left; }
</style><div><p>Привет, <code>%username%</code>! Сегодня поговорим о теме, которая часто остается в тени инфраструктурного мониторинга, но при этом не менее важна — о <strong>мониторинге бизнес-метрик</strong>. Если ты SRE, DevOps или TeamLead, то наверняка сталкивался с ситуацией: все графики зеленые, CPU не плавится, память в норме, а бизнес приходит и говорит &ldquo;что-то не работает&rdquo;. И вот тут начинается самое интересное.</p>
<h2 id="зачем-вообще-нужны-бизнес-метрики">Зачем вообще нужны бизнес-метрики?</h2>
<p>Давай начнем с простого вопроса: зачем мы вообще запускаем сервисы? Правильно — чтобы они <strong>решали чьи-то проблемы и приносили деньги</strong>. И вот тут классический технический мониторинг начинает пробуксовывать. Ты можешь знать, что у тебя загрузка CPU 15%, время выполнения запроса (latency) 50ms, а количество 500-ошибок в пределах нормы. Но ты <strong>не знаешь</strong>, сколько пользователей прямо сейчас платят за твой сервис, какой процент из них доходит до формы оплаты, и приносит ли вообще твой продукт деньги.</p>
<p>Представь себе ситуацию: твой сайт работает отлично с технической точки зрения, но пользователи не могут найти кнопку оплаты, потому что она потерялась где-то внизу страницы после последнего релиза. Инфраструктурный мониторинг тебе об этом <strong>не скажет</strong>. А вот бизнес-метрики — скажут сразу, как только конверсия в оплату упадет.</p>
<h2 id="три-слоя-мониторинга-от-железа-до-бизнеса">Три слоя мониторинга: от железа до бизнеса</h2>
<p>В НСПК (Национальная система платежных карт, те самые ребята, что делают карты &ldquo;Мир&rdquo;) придерживаются подхода, который я считаю очень правильным: сервис нужно раскладывать на три слоя, и <strong>мониторить строго сверху вниз</strong>.</p>
<p><strong>Бизнес-слой</strong> — это то, что видит конечный пользователь. Для платежной системы это объемы успешных авторизационных запросов, количество операций по типам, время обработки платежей. Для интернет-магазина — это количество успешных заказов, средний чек, конверсия в покупку. Для SaaS-продукта — количество активных подписок, revenue per user, churn rate.</p>
<p><strong>Прикладной слой</strong> — данные о работе приложений: статусы модулей, метрики используемого ПО, технические логи. Тут уже можно задействовать готовые экспортеры и интеграции.</p>
<p><strong>Инфраструктурный слой</strong> — классика: CPU, память, диск, сеть, состояние железа.</p>
<p>Почему именно сверху вниз? Потому что <strong>бизнес-метрики — это главное</strong>. Если у тебя бизнес-метрики в порядке, но один из серверов немного подгружен — это не критично. А вот если бизнес-метрики падают, даже при зеленой инфраструктуре — это уже проблема, которую надо расследовать немедленно.</p>
<h2 id="методологии-мониторинга-use-red-и-uca">Методологии мониторинга: USE, RED и UCA</h2>
<p>Существует несколько классических подходов к сбору метрик, и каждый из них решает свою задачу.</p>
<h3 id="use-метод-следим-за-ресурсами">USE-метод: следим за ресурсами</h3>
<p><strong>USE</strong> — это акроним от <strong>Utilization, Saturation, Errors</strong> (Утилизация, Насыщение, Ошибки). Метод предложил Brendan Gregg, и он отлично работает для <strong>низкоуровневых метрик</strong>.</p>
<p>Если упростить, то для каждого ресурса системы (CPU, память, диск, сеть) ты смотришь три показателя:</p>
<ul>
<li><strong>Utilization</strong> — насколько загружен ресурс (например, CPU загружен на 80%)</li>
<li><strong>Saturation</strong> — есть ли очередь к ресурсу (например, 10 процессов ждут своей очереди на выполнение)</li>
<li><strong>Errors</strong> — количество ошибок, которые возвращает этот ресурс</li>
</ul>
<p>USE помогает быстро выявить узкие места в системе. Если у тебя диск утилизирован на 100%, а очередь на запись растет — вот тебе и проблема.</p>
<h3 id="red-метод-следим-за-сервисами">RED-метод: следим за сервисами</h3>
<p><strong>RED</strong> — это <strong>Rate, Errors, Duration</strong> (Скорость, Ошибки, Продолжительность). Метод предложил Tom Wilkie специально для <strong>микросервисных архитектур</strong>.</p>
<p>Для каждого сервиса ты отслеживаешь:</p>
<ul>
<li><strong>Rate</strong> — количество запросов в секунду</li>
<li><strong>Errors</strong> — количество неудачных запросов в секунду</li>
<li><strong>Duration</strong> — время обработки каждого запроса</li>
</ul>
<p>RED дает тебе возможность посмотреть на систему <strong>глазами пользователя</strong>. Если у тебя растет количество ошибок или увеличивается время ответа — пользователи это сразу почувствуют. Метод отлично работает для веб-сервисов, API, баз данных — везде, где есть концепция &ldquo;запрос-ответ&rdquo;.</p>
<h3 id="uca-метод-следим-за-бизнесом">UCA-метод: следим за бизнесом</h3>
<p>И вот мы подходим к самому интересному — <strong>UCA</strong> (Users, Conversions, Activity). Этот метод предложил Mike Julian, и он <strong>целенаправленно нацелен на измерение бизнес-метрик</strong>.</p>
<p><strong>Users</strong> (Пользователи) — кто является пользователями твоего сервиса? Для разных отраслей это могут быть разные показатели: количество активных пользователей, посетителей на сайте, звонков в колл-центр, покупателей в час.</p>
<p><strong>Conversions</strong> (Конверсии) — это про то, как пользователь приносит доход твоему сервису. Купил подписку? Забронировал номер в отеле? Оформил заказ? Это всё конверсии.</p>
<p><strong>Activity</strong> (Активность) — показывает, что пользователи <strong>продолжают</strong> пользоваться твоим продуктом. Входы на сайт, просмотры товаров, добавления в корзину, время на сайте.</p>
<p>UCA позволяет собирать метрики, которые показывают, <strong>как бизнес себя чувствует</strong>. И отталкиваясь от этих метрик, ты уже можешь искать проблемы на уровне USE и RED — понимать, из-за ухудшения каких показателей стоит поднимать инженеров.</p>
<h2 id="какие-метрики-собирать-на-практике">Какие метрики собирать на практике</h2>
<p>Давай конкретнее. Вот список метрик, которые стоит отслеживать на разных уровнях:</p>
<p><strong>Мониторинг бизнес-метрик:</strong></p>
<ul>
<li>Сколько пользователей зарегистрировано в системе?</li>
<li>Сколько пользуется приложением раз в день/неделю/месяц (DAU/WAU/MAU)?</li>
<li>Какой процент людей после регистрации доходит до формы оплаты?</li>
<li>Сколько они платят (средний чек, медианный чек)?</li>
<li>Как люди пользуются услугами — какие фичи популярны, а какие нет?</li>
<li>Какова общая выручка и прибыль?</li>
</ul>
<p><strong>Мониторинг состояния приложений:</strong></p>
<ul>
<li>Количество запросов в единицу времени (RPS)</li>
<li>Количество активных пользователей в системе</li>
<li>Количество записей в БД (общее и новых в единицу времени)</li>
<li>Количество ошибок в сервисе</li>
<li>Время выполнения запросов или latency (50-й, 95-й, 99-й процентили)</li>
</ul>
<p><strong>Мониторинг оборудования:</strong></p>
<ul>
<li>Нагрузка на CPU</li>
<li>Свободное место в RAM</li>
<li>Свободное место на дисках</li>
<li>Нагрузка на сеть</li>
<li>IOPS на дисках</li>
<li>Количество запущенных процессов</li>
</ul>
<h2 id="инструменты-для-мониторинга-бизнес-метрик">Инструменты для мониторинга бизнес-метрик</h2>
<p>Теперь поговорим об инструментах. В идеальном мире у тебя должен быть стек, который покрывает все три уровня.</p>
<h3 id="для-бизнес-метрик-google-analytics-и-яндексметрика">Для бизнес-метрик: Google Analytics и Яндекс.Метрика</h3>
<p>Если речь идет о веб-сервисах, то <strong>Google Analytics</strong> и <strong>Яндекс.Метрика</strong> — это базовый минимум. Они позволяют отслеживать базовые переходы и конверсии готовыми средствами.</p>
<p>Яндекс.Метрика особенно хороша для российского рынка — она корректнее учитывает трафик из Яндекса, работает в соответствии с ФЗ-152, и у нее интуитивный интерфейс для русскоязычных пользователей. Google Analytics дает больше возможностей для крупных проектов с большими объемами данных (до 200 000 запросов в сутки против 5000 у Метрики).</p>
<p>Но если тебе нужно <strong>углубленное понимание</strong> — придется работать в связке с разработкой. Настроить сбор кастомных метрик, которые важны именно для твоего продукта.</p>
<h3 id="для-прикладных-метрик-prometheus--grafana">Для прикладных метрик: Prometheus + Grafana</h3>
<p><strong>Prometheus</strong> — это система сбора и хранения метрик временных рядов, которую изначально разработали в SoundCloud. Она стала стандартом де-факто для сбора метрик в современных инфраструктурах.</p>
<p><strong>Grafana</strong> — универсальная обертка для визуализации. Она сама ничего не собирает и не хранит, но умеет красиво отображать данные из Prometheus, PostgreSQL, ClickHouse и еще десятков источников.</p>
<p>Связка <strong>Prometheus + Grafana</strong> позволяет собирать как технические метрики (через экспортеры — node_exporter для системных метрик, nginx-prometheus-exporter для Nginx и т.д.), так и <strong>бизнес-метрики</strong> твоего приложения. Да-да, Prometheus прекрасно справляется со сбором бизнес-метрик: выручка за день, количество активных пользователей, количество заказов — достаточно сделать свой endpoint <code>/metrics</code> в приложении и экспортировать туда нужные данные.</p>
<h3 id="для-операционной-аналитики-splunk">Для операционной аналитики: Splunk</h3>
<p>В НСПК для комплексного анализа используют <strong>Splunk</strong> — платформу операционной аналитики. Splunk умеет:</p>
<ul>
<li>Анализировать тысячи метрик в фоновом режиме с использованием статистических анализаторов</li>
<li>Обнаруживать аномалии и делать прогнозы с помощью машинного обучения</li>
<li>Создавать сложные параметризованные отчеты для дежурной службы</li>
<li>Коррелировать данные из разных источников</li>
</ul>
<p>Splunk — это уже не просто мониторинг, а <strong>платформа для принятия решений</strong>. Он позволяет не только видеть, что что-то пошло не так, но и понимать, <strong>почему</strong> это произошло, и <strong>как это влияет на бизнес</strong>.</p>
<h3 id="для-логирования-elk-stack">Для логирования: ELK Stack</h3>
<p><strong>ELK</strong> (Elasticsearch, Logstash, Kibana) или его альтернатива <strong>EFK</strong> (где вместо Logstash используется Fluentd) — это стек для агрегации и анализа логов.</p>
<p>Когда у тебя есть бизнес-метрики и прикладные метрики, логи становятся третьим измерением, которое помогает <strong>расследовать инциденты</strong>. Ты видишь на графике, что конверсия упала в 14:37, переходишь в логи и находишь, что именно в это время начались ошибки при работе с платежным шлюзом.</p>
<h2 id="как-выстраивать-систему-мониторинга">Как выстраивать систему мониторинга</h2>
<p>Теперь самое важное — <strong>как это всё организовать</strong>.</p>
<h3 id="строй-ресурсно-сервисную-модель">Строй ресурсно-сервисную модель</h3>
<p>Первый шаг — понять, что именно ты мониторишь. В НСПК разделяют данные на три слоя, а в большой компании нужна еще и <strong>ресурсно-сервисная модель</strong> (РСМ) — структурированное описание того, какие компоненты обеспечивают работу конкретного сервиса.</p>
<p>Например, сервис &ldquo;Интернет-магазин&rdquo; состоит из:</p>
<ul>
<li>Frontend (Nginx, React-приложение)</li>
<li>Backend API (несколько микросервисов на Java)</li>
<li>База данных (PostgreSQL)</li>
<li>Кэш (Redis)</li>
<li>Очередь сообщений (RabbitMQ)</li>
<li>Платежный шлюз (внешний API)</li>
</ul>
<p>Для каждого компонента ты настраиваешь сбор метрик на всех трех уровнях. И когда бизнес-метрика &ldquo;конверсия в оплату&rdquo; начинает падать, ты уже знаешь, на какие компоненты смотреть.</p>
<h3 id="используй-зонтичный-мониторинг">Используй &ldquo;зонтичный&rdquo; мониторинг</h3>
<p>Одна из лучших практик — использовать <strong>&ldquo;зонтик&rdquo;</strong>, единый слой, который агрегирует данные от различных систем: Zabbix, Prometheus, ELK, и т.д.. Это дает целостную картину и упрощает анализ.</p>
<p>Представь: у тебя Prometheus собирает метрики приложений, Zabbix мониторит железо, ELK собирает логи, а Google Analytics собирает поведенческие данные. Если у каждой команды свой дашборд в своем инструменте — <strong>корреляцию данных не увидеть</strong>. А вот если всё это агрегировано в одном месте (например, в Grafana или Splunk) — картина становится прозрачной.</p>
<h3 id="настраивай-алерты-правильно">Настраивай алерты правильно</h3>
<p><strong>Система оповещений</strong> — это компонент мониторинга, который выполняет действия на основе изменений метрик. Основная цель алертов — <strong>привлечь внимание человека</strong> к текущему состоянию системы.</p>
<p>Важные моменты:</p>
<ul>
<li>Алерт должен содержать информацию о том, <strong>что</strong> пошло не так и <strong>где</strong> найти дополнительную информацию</li>
<li>Не алерть на всё подряд — это приводит к &ldquo;усталости от алертов&rdquo;</li>
<li>Настраивай алерты сначала на <strong>бизнес-метрики</strong>, потом на прикладные, и только в конце — на инфраструктурные</li>
</ul>
<p>Например, алерт &ldquo;CPU загружен на 80%&rdquo; — это информационный сигнал. А вот &ldquo;Конверсия в оплату упала на 50% за последние 10 минут&rdquo; — это уже <strong>критический инцидент</strong>, который требует немедленного реагирования.</p>
<h3 id="делай-метрики-прозрачными-для-всех">Делай метрики прозрачными для всех</h3>
<p>Один из ключевых принципов — <strong>все члены команды должны видеть одну и ту же информацию из одного источника</strong>. QA, разработчики, админы, аналитики, менеджеры продукта — все должны смотреть на одни и те же дашборды.</p>
<p>Когда у всех единая точка входа, начинает работать <strong>коллективный разум</strong>. Разработчик может заметить, что после его релиза упала конверсия. Админ увидит, что в момент падения бизнес-метрики начались таймауты при обращении к базе. Аналитик обратит внимание, что падение началось после того, как изменилась логика расчета скидок. Вместе они найдут причину быстрее.</p>
<h2 id="ошибки-которых-стоит-избегать">Ошибки, которых стоит избегать</h2>
<p>Давай поговорим о том, чего <strong>не надо</strong> делать.</p>
<h3 id="ошибка-1-отсутствие-связи-между-бизнес-задачами-и-аналитикой">Ошибка 1: Отсутствие связи между бизнес-задачами и аналитикой</h3>
<p>Самая частая проблема — когда ты собираешь метрики &ldquo;потому что так надо&rdquo;, но не понимаешь, <strong>зачем</strong> ты их собираешь.</p>
<p>Правильный подход: начинай с бизнес-целей. Бизнес хочет увеличить выручку на 20%? Отлично, декомпозируй это на метрики: нужно увеличить количество заказов или средний чек? Если заказы — то нужно больше пользователей или выше конверсия существующих? И так далее.</p>
<h3 id="ошибка-2-мониторинг-без-проверок-качества-данных">Ошибка 2: Мониторинг без проверок качества данных</h3>
<p>Представь: ты построил красивый дашборд, но данные в него приходят с ошибками. Счетчик установлен не на всех страницах. Конверсионные события дублируются. В результате твои метрики показывают 30% конверсии, а на самом деле она 3%.</p>
<p><strong>Проверяй качество данных</strong>: делай периодические проверки полноты и согласованности, тестируй бизнес-правила, отслеживай источники данных и трансформации.</p>
<h3 id="ошибка-3-плавающее-руководство-по-сбору-данных">Ошибка 3: &ldquo;Плавающее&rdquo; руководство по сбору данных</h3>
<p>Когда у тебя нет четкого стандарта, как называть метрики, как их собирать, и где их хранить — начинается хаос. Один разработчик называет метрику <code>orders_count</code>, другой — <code>order.count</code>, третий — <code>OrdersTotal</code>. В итоге ты не можешь нормально искать и агрегировать данные.</p>
<p><strong>Установи стандарты</strong>: naming conventions для метрик, формат лейблов, структуру дашбордов. И следи, чтобы все их соблюдали.</p>
<h3 id="ошибка-4-разрозненные-данные">Ошибка 4: Разрозненные данные</h3>
<p>Когда метрики инфраструктуры хранятся в Zabbix, прикладные — в Prometheus, бизнесовые — в Google Analytics, а логи — в ELK, и всё это <strong>никак не связано</strong> между собой — ты не можешь проводить корреляцию.</p>
<p><strong>Стремись к единой точке анализа</strong>: используй зонтичный мониторинг, настраивай интеграции между системами, делай так, чтобы все данные были доступны в одном месте.</p>
<h3 id="ошибка-5-исправление-ошибок-по-факту">Ошибка 5: Исправление ошибок &ldquo;по факту&rdquo;</h3>
<p>Если у тебя нет мониторинга, ты узнаешь о проблемах только тогда, когда <strong>клиенты начинают жаловаться</strong>. И это очень дорого — и в деньгах, и в репутации.</p>
<p>Мониторинг — это <strong>профилактика</strong>. Гораздо дешевле обнаружить проблему на графике и исправить её до того, как она повлияла на пользователей, чем тушить пожар, когда половина клиентов уже не может сделать заказ.</p>
<h2 id="практический-чек-лист">Практический чек-лист</h2>
<p>Если ты хочешь построить нормальную систему мониторинга бизнес-метрик, вот тебе чек-лист для самопроверки:</p>
<p><strong>Базовый уровень:</strong></p>
<ul>
<li><input disabled="" type="checkbox"> Определен список основных бизнес-метрик (выручка, количество заказов, конверсии)</li>
<li><input disabled="" type="checkbox"> Бизнес-метрики декомпозированы от уровня руководства до команд</li>
<li><input disabled="" type="checkbox"> Определены сопутствующие метрики (MAU, количество товаров в чеке и т.д.)</li>
<li><input disabled="" type="checkbox"> Определен список прикладных метрик (RPS, latency, error rate)</li>
<li><input disabled="" type="checkbox"> Для каждой метрики определен период обратной связи (как часто проверять)</li>
</ul>
<p><strong>Продвинутый уровень:</strong></p>
<ul>
<li><input disabled="" type="checkbox"> Определены и автоматизированы источники данных по всем метрикам</li>
<li><input disabled="" type="checkbox"> Определены события/встречи, на которых обсуждаются метрики</li>
<li><input disabled="" type="checkbox"> Планирование работы осуществляется на основании метрик</li>
<li><input disabled="" type="checkbox"> Для каждой задачи есть понимание, на какую метрику она влияет</li>
<li><input disabled="" type="checkbox"> Все заинтересованные лица имеют доступ к метрикам</li>
<li><input disabled="" type="checkbox"> Есть система алертинга на критические изменения метрик</li>
</ul>
<p><strong>Экспертный уровень:</strong></p>
<ul>
<li><input disabled="" type="checkbox"> Используется зонтичный мониторинг, агрегирующий данные из всех систем</li>
<li><input disabled="" type="checkbox"> Настроена корреляция между метриками разных уровней</li>
<li><input disabled="" type="checkbox"> Внедрены проверки качества данных</li>
<li><input disabled="" type="checkbox"> Существует документированный стандарт сбора и именования метрик</li>
<li><input disabled="" type="checkbox"> Метрики используются для принятия бизнес-решений</li>
</ul>
<h2 id="выводы">Выводы</h2>
<p>Мониторинг бизнес-метрик — это не просто &ldquo;давайте нарисуем еще один дашборд в Grafana&rdquo;. Это <strong>комплексный подход</strong> к пониманию того, как работает твой продукт с точки зрения бизнеса.</p>
<p>Ключевые мысли:</p>
<ol>
<li><strong>Мониторь сверху вниз</strong>: начинай с бизнес-метрик, потом прикладные, и только в конце инфраструктурные</li>
<li><strong>Используй правильные методологии</strong>: USE для ресурсов, RED для сервисов, UCA для бизнеса</li>
<li><strong>Стремись к единой точке анализа</strong>: все команды должны смотреть на одни и те же данные</li>
<li><strong>Автоматизируй сбор данных</strong>: ручной сбор метрик — это прошлый век</li>
<li><strong>Делай метрики основой для принятия решений</strong>: не просто смотри на графики, а делай выводы и действуй</li>
</ol>
<p>Управление проектом без метрик — это как плавание ночью на корабле без карты и навигации. Ты вроде бы куда-то плывешь, но рано или поздно это закончится плохо.</p>
<p>А с правильно настроенным мониторингом бизнес-метрик ты <strong>всегда знаешь</strong>, где ты находишься, куда движешься, и что нужно исправить, чтобы прийти к цели.</p>
<h3 id="полезные-ссылки">Полезные ссылки</h3>
<ul>
<li><a href="https://habr.com/ru/company/nspk/blog/523352/" rel="noopener noreferrer" target="_blank">Как устроен прикладной и бизнес-мониторинг сервисов НСПК</a>
 — про трехслойную модель мониторинга</li>
<li><a href="https://logrocon.ru/news/monitoring" rel="noopener noreferrer" target="_blank">Основы мониторинга и сбора метрик</a>
 — про методологии USE, RED, UCA</li>
<li><a href="https://otus.ru/nest/post/1988/" rel="noopener noreferrer" target="_blank">Мониторинг событий и бизнес-метрик</a>
 — про важность метрик для бизнеса</li>
<li><a href="https://vc.ru/u/744996-evgeniy-ivanov/216307-pro-biznes-i-metriki" rel="noopener noreferrer" target="_blank">Про бизнес и метрики</a>
 — про структуру и типы метрик</li>
</ul>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></content:encoded>
    </item><item>
      <title>Запуск Kali Linux в UTM на macOS под ARM</title>
      <link>https://jtprog.ru/posts/kali-apple-utm/</link>
      <pubDate>Thu, 18 Dec 2025 06:20:34 +0300</pubDate>
      <dc:creator>jtprogru</dc:creator>
      <guid isPermaLink="true">https://jtprog.ru/posts/kali-apple-utm/</guid>
      <category>DevOps</category>
      <category>SRE</category>
      <category>Kali Linux</category>
      <category>UTM</category>
      <category>MacOS</category>
      <category>Apple Silicon</category>
      <category>ARM64</category>
      <category>Виртуализация</category>
      <category>Virtualization</category>
      <category>QEMU</category>
      <category>SPICE</category>
      <category>PenTest</category>
      <category>Безопасность</category>
      <category>Linux</category>
      <category>Инструкция</category>
      <category domain="category">Howto</category>
      <enclosure url="https://jtprog.ru/howto.png" type="image/jpeg" length="0" />
      <media:thumbnail url="https://jtprog.ru/howto.png" /><description><![CDATA[<div><p>Привет, <code>%username%</code>! Сегодня я расскажу тебе про то, как можно развернуть Kali Linux на маках с процессорами Apple Silicon (M1/M2/M3), используя бесплатную альтернативу Parallels Desktop — виртуализатор <a href="https://mac.getutm.app/" rel="noopener noreferrer" target="_blank">UTM</a>
. И да, это не только для пентестеров, но и для всех, кому нужна тестовая среда на базе Linux.</p>
<h2 id="зачем-это-вообще-нужно">Зачем это вообще нужно?</h2>
<p>Представь, что тебе нужно проверить, как твой сервис ведет себя в определенном окружении. Или протестировать Ansible-плейбуки на свежей системе. Или проверить безопасность своей инфраструктуры с помощью инструментов пентеста. В таких случаях виртуальная машина — это лучший друг.</p>
<p>Kali Linux — это не просто дистрибутив для хакеров из голливудских фильмов. Это полноценная платформа для аудита безопасности, в которой из коробки доступны инструменты вроде Nmap, Metasploit, Burp Suite и Wireshark. Для DevOps и SRE это полезный набор для проверки защищенности инфраструктуры, тестирования сетевой безопасности и поиска уязвимостей еще до того, как их найдут настоящие злоумышленники.</p>
<h2 id="почему-utm-а-не-parallels">Почему UTM, а не Parallels?</h2>
<p>Давай сразу расставим точки над Ё. Parallels Desktop — это крутой и удобный инструмент с отличной интеграцией с macOS, поддержкой 3D-ускорения и простым мастером установки. Но есть одна проблема: за него нужно платить около 100 долларов в год.</p>
<p>UTM — это open-source решение на базе QEMU, которое использует фреймворк Apple Hypervisor для виртуализации ARM-систем на скоростях, близких к нативным. Да, UTM требует больше ручных настроек, чем Parallels, и не имеет такой же бесшовной интеграции с macOS. Но зато он бесплатный, активно развивается и отлично справляется с задачами для разработки, тестирования и обучения.</p>
<p>Вот краткое сравнение:</p>
<p><strong>Parallels Desktop</strong>: автоматическая установка, отличная производительность, профессиональная поддержка, но стоит денег.</p>
<p><strong>UTM</strong>: бесплатный, открытый исходный код, активное комьюнити, хорошая производительность для ARM-систем, но требует больше ручной настройки.</p>
<p>Для большинства задач DevOps и SRE, особенно если речь идет про эксперименты, тестовые стенды или обучение, UTM — это более чем достаточно.</p>
<h2 id="что-нам-понадобится">Что нам понадобится?</h2>
<p>Чтобы все заработало, тебе нужно:</p>
<ol>
<li>Mac с процессором Apple Silicon (M1/M2/M3)</li>
<li>Скачанный UTM с официального сайта</li>
<li>Installer-образ Kali Linux для ARM64 (именно ARM, не x86!)</li>
</ol>
<p>Почему именно installer-образ? Потому что он позволит тебе установить систему с нуля на виртуальный диск, настроить все под себя и получить полноценную рабочую среду.</p>
<h2 id="шаг-1-устанавливаем-utm">Шаг 1: Устанавливаем UTM</h2>
<p>Заходишь на официальный сайт UTM (mac.getutm.app), скачиваешь .dmg-файл, открываешь его и перетаскиваешь UTM в папку &ldquo;Приложения&rdquo;. Все как обычно для macOS — никаких подводных камней.</p>
<h2 id="шаг-2-скачиваем-образ-kali-linux">Шаг 2: Скачиваем образ Kali Linux</h2>
<p>Идешь на официальный сайт Kali Linux и качаешь installer-образ для Apple M1/M2 (ARM64). Обрати внимание: нужен именно ISO-файл для установки, а не готовый образ виртуальной машины. Рекомендую качать через торрент — это быстрее и надежнее.</p>
<h2 id="шаг-3-создаем-виртуальную-машину">Шаг 3: Создаем виртуальную машину</h2>
<p>Запускаешь UTM и жмешь &ldquo;Create VM&rdquo;. Дальше важно: выбираешь <strong>&ldquo;Virtualize&rdquo;</strong>, а не &ldquo;Emulate&rdquo;. Виртуализация использует нативные инструкции ARM-процессора через Apple Hypervisor, что дает тебе максимальную производительность. Эмуляция нужна только если ты хочешь запустить x86-систему на ARM, но это будет работать медленно.</p>
<p>На следующем экране выбираешь <strong>&ldquo;Other&rdquo;</strong> в качестве типа операционной системы.</p>
<p>Теперь самое важное: на странице настроек нажимаешь &ldquo;Boot ISO Image&rdquo; и выбираешь скачанный ранее ISO-файл Kali Linux. Размер диска можешь оставить по умолчанию или увеличить в зависимости от того, сколько места планируешь использовать — для базовой установки с основными инструментами хватит 20-30 GB.</p>
<h2 id="шаг-4-важный-хак--serial-режим">Шаг 4: Важный хак — Serial-режим</h2>
<p>Вот тут начинается интересное. Из-за бага в текущих версиях UTM, установку Kali нужно проводить в console-only режиме через Serial-устройство. Звучит страшно, но на деле это просто:</p>
<ol>
<li>После создания VM переходишь в её настройки</li>
<li>В разделе &ldquo;Devices&rdquo; добавляешь устройство <strong>&ldquo;Serial&rdquo;</strong></li>
<li>Сохраняешь и запускаешь VM</li>
</ol>
<p>Когда VM загрузится, в меню установщика выбираешь <strong>&ldquo;Install&rdquo;</strong> (не Graphical Install!). Дальше процесс установки стандартный: выбираешь язык, страну, настраиваешь сеть, создаешь пользователя и пароль.</p>
<h2 id="шаг-5-установка-kali-linux">Шаг 5: Установка Kali Linux</h2>
<p>Процесс установки довольно стандартный для Debian-based систем:</p>
<ol>
<li>Выбираешь язык интерфейса (можешь выбрать русский или оставить английский)</li>
<li>Настраиваешь сеть — UTM автоматически создаст NAT-подключение</li>
<li>Задаешь hostname для своей виртуалки</li>
<li>Создаешь пользователя и пароль</li>
<li>На этапе разметки диска выбираешь <strong>&ldquo;Guided — Use entire disk&rdquo;</strong> и <strong>&ldquo;All files in one partition&rdquo;</strong></li>
<li>Выбираешь инструменты для установки — можешь установить полный набор или только базовую систему</li>
</ol>
<p>После завершения установки перезагружаешь VM.</p>
<h2 id="шаг-6-финальная-настройка">Шаг 6: Финальная настройка</h2>
<p>После перезагрузки ты увидишь, что установщик снова предлагает установить Kali. Это нормально — просто нужно удалить ISO-образ из виртуального CD-привода.</p>
<p>Выключаешь VM и делаешь следующее:</p>
<ol>
<li>Переходишь в настройки VM</li>
<li>В разделе &ldquo;Drives&rdquo; удаляешь ISO-образ установщика</li>
<li>В разделе &ldquo;Devices&rdquo; удаляешь Serial-устройство (правый клик → Remove)</li>
<li>В разделе &ldquo;Display&rdquo; меняешь эмуляцию видеокарты на <strong>virtio-gpu-pci</strong></li>
</ol>
<p>Эти изменения нужны для того, чтобы переключиться с консольного режима установки на полноценный графический интерфейс.</p>
<h2 id="шаг-7-устанавливаем-spice-guest-tools">Шаг 7: Устанавливаем SPICE Guest Tools</h2>
<p>Чтобы все работало максимально комфортно — общий буфер обмена, автоматическое изменение разрешения экрана и лучшая производительность — нужно установить SPICE-инструменты.</p>
<p>Запускаешь VM, логинишься и выполняешь в терминале:</p>
<div class="codeblock codeblock--bash" data-lang="bash"><span class="codeblock__lang" aria-hidden="true">bash</span><button class="codeblock__copy" type="button" data-copy aria-label="Скопировать" title="Скопировать"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt update <span class="o">&amp;&amp;</span> sudo apt install spice-vdagent spice-webdavd -y</span></span></code></pre></div>
</div>
<p>После установки можешь настроить оптимальное разрешение экрана — рекомендуется 1400×900 для большинства макбуков.</p>
<h2 id="что-дальше">Что дальше?</h2>
<p>Теперь у тебя есть полноценная виртуальная машина с Kali Linux, которая работает практически на нативной скорости благодаря ARM-виртуализации. Что с ней делать?</p>
<p><strong>Для DevOps/SRE:</strong></p>
<ul>
<li>Тестировать Ansible-плейбуки на чистой системе</li>
<li>Проверять безопасность своей инфраструктуры с помощью Nmap и Metasploit</li>
<li>Создавать изолированные тестовые среды для экспериментов</li>
<li>Анализировать сетевой трафик с помощью Wireshark и tcpdump</li>
<li>Проводить аудит безопасности веб-приложений через Burp Suite</li>
</ul>
<p><strong>Для инженеров эксплуатации:</strong></p>
<ul>
<li>Отлаживать проблемы с сетью</li>
<li>Тестировать конфигурации служб в изолированной среде</li>
<li>Проводить симуляцию инцидентов безопасности</li>
</ul>
<h2 id="бонус-снапшоты-и-клонирование">Бонус: снапшоты и клонирование</h2>
<p>UTM поддерживает создание снапшотов виртуальных машин. Это невероятно удобно: настроил идеальное окружение один раз, сделал снапшот, и можешь откатываться к нему в любой момент. Экспериментируешь с новой конфигурацией? Сделал снапшот. Что-то сломалось? Откатился за пару секунд.</p>
<p>Также можешь клонировать VM для создания нескольких изолированных окружений — например, для тестирования кластерных решений или распределенных систем.</p>
<h2 id="альтернативы-и-сравнение">Альтернативы и сравнение</h2>
<p>Конечно, UTM — не единственный вариант для виртуализации на Mac. Вот краткое сравнение популярных решений:</p>
<p><strong>Parallels Desktop</strong>: лучшая интеграция с macOS, автоматическая установка, отличная производительность, но платный.</p>
<p><strong>VMware Fusion</strong>: есть бесплатная версия Player, хорошая производительность, но интерфейс не такой удобный как у Parallels.</p>
<p><strong>UTM</strong>: бесплатный, open-source, отличная производительность для ARM, активное комьюнити, но требует больше ручной настройки.</p>
<p><strong>VirtualBox</strong>: классика виртуализации, но плохо работает на Apple Silicon и требует эмуляции.</p>
<p>Для большинства задач DevOps и SRE, особенно если речь про обучение, эксперименты и разработку, UTM — это оптимальный выбор по соотношению цена/качество.</p>
<h2 id="возможные-проблемы-и-их-решения">Возможные проблемы и их решения</h2>
<p><strong>Черный экран после выбора режима установки</strong>: это известная проблема, решается использованием Serial-режима, как описано выше.</p>
<p><strong>Не работает общий буфер обмена</strong>: убедись, что установил <code>spice-vdagent</code> и <code>spice-webdavd</code>, и включил Clipboard Sharing в настройках VM.</p>
<p><strong>Низкая производительность</strong>: проверь, что выбрал &ldquo;Virtualize&rdquo;, а не &ldquo;Emulate&rdquo; при создании VM, и выделил достаточно RAM (минимум 3-4 GB).</p>
<p><strong>Проблемы с сетью</strong>: UTM автоматически создает NAT-подключение, но если что-то не работает, можешь попробовать режим Bridge в настройках сети.</p>
<h2 id="итоги">Итоги</h2>
<p>Развернуть Kali Linux на Mac с Apple Silicon через UTM — это вполне реальная задача, которая не требует покупки дорогих коммерческих решений. Да, придется немного повозиться с настройками, но результат того стоит: ты получаешь полноценную виртуальную машину с отличной производительностью и всеми необходимыми инструментами для тестирования, разработки и аудита безопасности.</p>
<p>UTM — это отличная демонстрация того, как open-source решения могут конкурировать с коммерческими продуктами, особенно в руках тех, кто не боится немного покопаться в настройках. Для DevOps и SRE это особенно актуально: мы привыкли читать YAML и bash-скрипты, разбираться в документации и решать проблемы нестандартными способами.</p>
<p>Так что если у тебя есть Mac на Apple Silicon и нужна виртуалка с Linux — смело пробуй UTM — это работает, и это open-source.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания — заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></description>
      <content:encoded><![CDATA[<style>/* Inline-CSS, который тема вкладывает в <description> каждого item'а
   RSS-фида (layouts/index.rss.xml). RSS-ридеры (Feedly, Inoreader,
   NetNewsWire) уважают <style> внутри description с переменной
   степенью энтузиазма — это базовый fallback, достаточный для читаемой
   типографики, не более.

   Цвета продублированы из 00-vars.css (light-палитра) — поправь
   синхронно при изменении --bg / --text / --accent / --border. */

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  line-height: 1.6;
  color: #1c1c1f;
  max-width: 720px;
  margin: 0 auto;
  padding: 1em;
}
h1, h2, h3 { line-height: 1.25; margin-top: 1.4em; }
a { color: #c2410c; }
pre {
  background: #1e1e24;
  color: #e8e6df;
  padding: 1em;
  border-radius: 6px;
  overflow-x: auto;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.9em;
}
code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  background: #f3f1ed;
  padding: 0.1em 0.4em;
  border-radius: 4px;
}
pre code { background: transparent; padding: 0; }
blockquote {
  border-left: 3px solid #c2410c;
  padding-left: 1em;
  color: #5b5b62;
  font-style: italic;
  margin-left: 0;
}
img { max-width: 100%; height: auto; border-radius: 6px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #e5e3dc; padding: 6px 10px; text-align: left; }
</style><div><p>Привет, <code>%username%</code>! Сегодня я расскажу тебе про то, как можно развернуть Kali Linux на маках с процессорами Apple Silicon (M1/M2/M3), используя бесплатную альтернативу Parallels Desktop — виртуализатор <a href="https://mac.getutm.app/" rel="noopener noreferrer" target="_blank">UTM</a>
. И да, это не только для пентестеров, но и для всех, кому нужна тестовая среда на базе Linux.</p>
<h2 id="зачем-это-вообще-нужно">Зачем это вообще нужно?</h2>
<p>Представь, что тебе нужно проверить, как твой сервис ведет себя в определенном окружении. Или протестировать Ansible-плейбуки на свежей системе. Или проверить безопасность своей инфраструктуры с помощью инструментов пентеста. В таких случаях виртуальная машина — это лучший друг.</p>
<p>Kali Linux — это не просто дистрибутив для хакеров из голливудских фильмов. Это полноценная платформа для аудита безопасности, в которой из коробки доступны инструменты вроде Nmap, Metasploit, Burp Suite и Wireshark. Для DevOps и SRE это полезный набор для проверки защищенности инфраструктуры, тестирования сетевой безопасности и поиска уязвимостей еще до того, как их найдут настоящие злоумышленники.</p>
<h2 id="почему-utm-а-не-parallels">Почему UTM, а не Parallels?</h2>
<p>Давай сразу расставим точки над Ё. Parallels Desktop — это крутой и удобный инструмент с отличной интеграцией с macOS, поддержкой 3D-ускорения и простым мастером установки. Но есть одна проблема: за него нужно платить около 100 долларов в год.</p>
<p>UTM — это open-source решение на базе QEMU, которое использует фреймворк Apple Hypervisor для виртуализации ARM-систем на скоростях, близких к нативным. Да, UTM требует больше ручных настроек, чем Parallels, и не имеет такой же бесшовной интеграции с macOS. Но зато он бесплатный, активно развивается и отлично справляется с задачами для разработки, тестирования и обучения.</p>
<p>Вот краткое сравнение:</p>
<p><strong>Parallels Desktop</strong>: автоматическая установка, отличная производительность, профессиональная поддержка, но стоит денег.</p>
<p><strong>UTM</strong>: бесплатный, открытый исходный код, активное комьюнити, хорошая производительность для ARM-систем, но требует больше ручной настройки.</p>
<p>Для большинства задач DevOps и SRE, особенно если речь идет про эксперименты, тестовые стенды или обучение, UTM — это более чем достаточно.</p>
<h2 id="что-нам-понадобится">Что нам понадобится?</h2>
<p>Чтобы все заработало, тебе нужно:</p>
<ol>
<li>Mac с процессором Apple Silicon (M1/M2/M3)</li>
<li>Скачанный UTM с официального сайта</li>
<li>Installer-образ Kali Linux для ARM64 (именно ARM, не x86!)</li>
</ol>
<p>Почему именно installer-образ? Потому что он позволит тебе установить систему с нуля на виртуальный диск, настроить все под себя и получить полноценную рабочую среду.</p>
<h2 id="шаг-1-устанавливаем-utm">Шаг 1: Устанавливаем UTM</h2>
<p>Заходишь на официальный сайт UTM (mac.getutm.app), скачиваешь .dmg-файл, открываешь его и перетаскиваешь UTM в папку &ldquo;Приложения&rdquo;. Все как обычно для macOS — никаких подводных камней.</p>
<h2 id="шаг-2-скачиваем-образ-kali-linux">Шаг 2: Скачиваем образ Kali Linux</h2>
<p>Идешь на официальный сайт Kali Linux и качаешь installer-образ для Apple M1/M2 (ARM64). Обрати внимание: нужен именно ISO-файл для установки, а не готовый образ виртуальной машины. Рекомендую качать через торрент — это быстрее и надежнее.</p>
<h2 id="шаг-3-создаем-виртуальную-машину">Шаг 3: Создаем виртуальную машину</h2>
<p>Запускаешь UTM и жмешь &ldquo;Create VM&rdquo;. Дальше важно: выбираешь <strong>&ldquo;Virtualize&rdquo;</strong>, а не &ldquo;Emulate&rdquo;. Виртуализация использует нативные инструкции ARM-процессора через Apple Hypervisor, что дает тебе максимальную производительность. Эмуляция нужна только если ты хочешь запустить x86-систему на ARM, но это будет работать медленно.</p>
<p>На следующем экране выбираешь <strong>&ldquo;Other&rdquo;</strong> в качестве типа операционной системы.</p>
<p>Теперь самое важное: на странице настроек нажимаешь &ldquo;Boot ISO Image&rdquo; и выбираешь скачанный ранее ISO-файл Kali Linux. Размер диска можешь оставить по умолчанию или увеличить в зависимости от того, сколько места планируешь использовать — для базовой установки с основными инструментами хватит 20-30 GB.</p>
<h2 id="шаг-4-важный-хак--serial-режим">Шаг 4: Важный хак — Serial-режим</h2>
<p>Вот тут начинается интересное. Из-за бага в текущих версиях UTM, установку Kali нужно проводить в console-only режиме через Serial-устройство. Звучит страшно, но на деле это просто:</p>
<ol>
<li>После создания VM переходишь в её настройки</li>
<li>В разделе &ldquo;Devices&rdquo; добавляешь устройство <strong>&ldquo;Serial&rdquo;</strong></li>
<li>Сохраняешь и запускаешь VM</li>
</ol>
<p>Когда VM загрузится, в меню установщика выбираешь <strong>&ldquo;Install&rdquo;</strong> (не Graphical Install!). Дальше процесс установки стандартный: выбираешь язык, страну, настраиваешь сеть, создаешь пользователя и пароль.</p>
<h2 id="шаг-5-установка-kali-linux">Шаг 5: Установка Kali Linux</h2>
<p>Процесс установки довольно стандартный для Debian-based систем:</p>
<ol>
<li>Выбираешь язык интерфейса (можешь выбрать русский или оставить английский)</li>
<li>Настраиваешь сеть — UTM автоматически создаст NAT-подключение</li>
<li>Задаешь hostname для своей виртуалки</li>
<li>Создаешь пользователя и пароль</li>
<li>На этапе разметки диска выбираешь <strong>&ldquo;Guided — Use entire disk&rdquo;</strong> и <strong>&ldquo;All files in one partition&rdquo;</strong></li>
<li>Выбираешь инструменты для установки — можешь установить полный набор или только базовую систему</li>
</ol>
<p>После завершения установки перезагружаешь VM.</p>
<h2 id="шаг-6-финальная-настройка">Шаг 6: Финальная настройка</h2>
<p>После перезагрузки ты увидишь, что установщик снова предлагает установить Kali. Это нормально — просто нужно удалить ISO-образ из виртуального CD-привода.</p>
<p>Выключаешь VM и делаешь следующее:</p>
<ol>
<li>Переходишь в настройки VM</li>
<li>В разделе &ldquo;Drives&rdquo; удаляешь ISO-образ установщика</li>
<li>В разделе &ldquo;Devices&rdquo; удаляешь Serial-устройство (правый клик → Remove)</li>
<li>В разделе &ldquo;Display&rdquo; меняешь эмуляцию видеокарты на <strong>virtio-gpu-pci</strong></li>
</ol>
<p>Эти изменения нужны для того, чтобы переключиться с консольного режима установки на полноценный графический интерфейс.</p>
<h2 id="шаг-7-устанавливаем-spice-guest-tools">Шаг 7: Устанавливаем SPICE Guest Tools</h2>
<p>Чтобы все работало максимально комфортно — общий буфер обмена, автоматическое изменение разрешения экрана и лучшая производительность — нужно установить SPICE-инструменты.</p>
<p>Запускаешь VM, логинишься и выполняешь в терминале:</p>
<div class="codeblock codeblock--bash" data-lang="bash"><span class="codeblock__lang" aria-hidden="true">bash</span><button class="codeblock__copy" type="button" data-copy aria-label="Скопировать" title="Скопировать"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt update <span class="o">&amp;&amp;</span> sudo apt install spice-vdagent spice-webdavd -y</span></span></code></pre></div>
</div>
<p>После установки можешь настроить оптимальное разрешение экрана — рекомендуется 1400×900 для большинства макбуков.</p>
<h2 id="что-дальше">Что дальше?</h2>
<p>Теперь у тебя есть полноценная виртуальная машина с Kali Linux, которая работает практически на нативной скорости благодаря ARM-виртуализации. Что с ней делать?</p>
<p><strong>Для DevOps/SRE:</strong></p>
<ul>
<li>Тестировать Ansible-плейбуки на чистой системе</li>
<li>Проверять безопасность своей инфраструктуры с помощью Nmap и Metasploit</li>
<li>Создавать изолированные тестовые среды для экспериментов</li>
<li>Анализировать сетевой трафик с помощью Wireshark и tcpdump</li>
<li>Проводить аудит безопасности веб-приложений через Burp Suite</li>
</ul>
<p><strong>Для инженеров эксплуатации:</strong></p>
<ul>
<li>Отлаживать проблемы с сетью</li>
<li>Тестировать конфигурации служб в изолированной среде</li>
<li>Проводить симуляцию инцидентов безопасности</li>
</ul>
<h2 id="бонус-снапшоты-и-клонирование">Бонус: снапшоты и клонирование</h2>
<p>UTM поддерживает создание снапшотов виртуальных машин. Это невероятно удобно: настроил идеальное окружение один раз, сделал снапшот, и можешь откатываться к нему в любой момент. Экспериментируешь с новой конфигурацией? Сделал снапшот. Что-то сломалось? Откатился за пару секунд.</p>
<p>Также можешь клонировать VM для создания нескольких изолированных окружений — например, для тестирования кластерных решений или распределенных систем.</p>
<h2 id="альтернативы-и-сравнение">Альтернативы и сравнение</h2>
<p>Конечно, UTM — не единственный вариант для виртуализации на Mac. Вот краткое сравнение популярных решений:</p>
<p><strong>Parallels Desktop</strong>: лучшая интеграция с macOS, автоматическая установка, отличная производительность, но платный.</p>
<p><strong>VMware Fusion</strong>: есть бесплатная версия Player, хорошая производительность, но интерфейс не такой удобный как у Parallels.</p>
<p><strong>UTM</strong>: бесплатный, open-source, отличная производительность для ARM, активное комьюнити, но требует больше ручной настройки.</p>
<p><strong>VirtualBox</strong>: классика виртуализации, но плохо работает на Apple Silicon и требует эмуляции.</p>
<p>Для большинства задач DevOps и SRE, особенно если речь про обучение, эксперименты и разработку, UTM — это оптимальный выбор по соотношению цена/качество.</p>
<h2 id="возможные-проблемы-и-их-решения">Возможные проблемы и их решения</h2>
<p><strong>Черный экран после выбора режима установки</strong>: это известная проблема, решается использованием Serial-режима, как описано выше.</p>
<p><strong>Не работает общий буфер обмена</strong>: убедись, что установил <code>spice-vdagent</code> и <code>spice-webdavd</code>, и включил Clipboard Sharing в настройках VM.</p>
<p><strong>Низкая производительность</strong>: проверь, что выбрал &ldquo;Virtualize&rdquo;, а не &ldquo;Emulate&rdquo; при создании VM, и выделил достаточно RAM (минимум 3-4 GB).</p>
<p><strong>Проблемы с сетью</strong>: UTM автоматически создает NAT-подключение, но если что-то не работает, можешь попробовать режим Bridge в настройках сети.</p>
<h2 id="итоги">Итоги</h2>
<p>Развернуть Kali Linux на Mac с Apple Silicon через UTM — это вполне реальная задача, которая не требует покупки дорогих коммерческих решений. Да, придется немного повозиться с настройками, но результат того стоит: ты получаешь полноценную виртуальную машину с отличной производительностью и всеми необходимыми инструментами для тестирования, разработки и аудита безопасности.</p>
<p>UTM — это отличная демонстрация того, как open-source решения могут конкурировать с коммерческими продуктами, особенно в руках тех, кто не боится немного покопаться в настройках. Для DevOps и SRE это особенно актуально: мы привыкли читать YAML и bash-скрипты, разбираться в документации и решать проблемы нестандартными способами.</p>
<p>Так что если у тебя есть Mac на Apple Silicon и нужна виртуалка с Linux — смело пробуй UTM — это работает, и это open-source.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания — заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></content:encoded>
    </item><item>
      <title>Tron как первый SRE</title>
      <link>https://jtprog.ru/posts/tron-as-sre/</link>
      <pubDate>Sun, 14 Dec 2025 10:22:28 +0300</pubDate>
      <dc:creator>jtprogru</dc:creator>
      <guid isPermaLink="true">https://jtprog.ru/posts/tron-as-sre/</guid>
      <category>Tron</category>
      <category>SRE</category>
      <category>Monitoring</category>
      <category>Security</category>
      <category>Architecture</category>
      <category>DevOps</category>
      <category domain="category">Opinions</category>
      <enclosure url="https://jtprog.ru/opinions.png" type="image/jpeg" length="0" />
      <media:thumbnail url="https://jtprog.ru/opinions.png" /><description><![CDATA[<div><p>Привет, <code>%username%</code>! В 2010 году в прокат вышел фильм <a href="https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%BE%D0%BD:_%D0%9D%D0%B0%D1%81%D0%BB%D0%B5%D0%B4%D0%B8%D0%B5" rel="noopener noreferrer" target="_blank">Tron: Наследие</a>
. И только с недавних пор, уже работая на позициях Site Reliability Engineer (SRE), я начал считать его (программу Tron) первой имплементацией SRE.</p>
<h2 id="немного-контекста-что-за-tron-вообще">Немного контекста: что за Tron вообще</h2>
<p>Если вдруг ты смотрел «Tron» в детстве и помнишь только неоновые мотоциклы, внутри на самом деле спрятана довольно внятная модель компьютерной системы. Есть корпорация ENCOM, их внутренняя система (The Grid) и программа главного управления — MCP, которая начиналась как полезная утилита, а закончилась цифровым диктатором с тягой к внешним вторжениям, в том числе в военные сети.</p>
<p>Tron в этой истории — не «главный герой-человек», а именно программа безопасности, которую написал Алан Брэдли, инженер ENCOM. По задумке Алана, Tron должен был мониторить коммуникации MCP с внешним миром и ограничивать его произвол, то есть быть живым ACL’ом с руками и ногами, который умеет сказать «нет» даже суперсервису.</p>
<h2 id="назначение-tronа-securityсервис-в-терминах-sre">Назначение Tron&rsquo;а: security‑сервис в терминах SRE</h2>
<p>Если переложить сюжет на нашу реальность, Tron выполняет очень узнаваемую роль. Это отдельный сервис, существующий вне MCP: его цель — не обслуживать пользовательские запросы, а наблюдать и контролировать поведение центрального контроллера. У него есть чёткий мандат — следить за корректностью внешних соединений MCP и выявлять подозрительные действия. Проще говоря, он реализует security‑SLO уровня «никаких неожиданных запросов наружу». Tron работает как out‑of‑band‑контур: MCP не управляет им и даже опасается, ведь Tron способен ограничить его полномочия и отсечь лишние привилегии.</p>
<p>Если смотреть в контексте классического стека, Tron — это нечто среднее между SIEM/SOAR, IDS/IPS и SRE‑сервисом контроля платформы, который следит не за аптаймом отдельных микросервисов, а за адекватностью поведения всей системы.</p>
<h2 id="mcp-как-антипаттерн-архитектуры">MCP как анти‑паттерн архитектуры</h2>
<p>Почему вообще Tron в этом мире нужен? Потому что MCP — эталон того, как делать нельзя.</p>
<p>MCP растёт из утилиты в «бога системы», который сам себе поднимает привилегии и лезет во внешние сети. Доступы, логирование, прозрачность — всё свёрнуто внутрь одного монолита, который никому ничего не объясняет и скрывает свои действия даже от создателей. Классическая история «нам нужно единое окно управления всем» заканчивается тоталитарной схемой, где нет ни независимого мониторинга, ни разделения обязанностей, ни здорового ограничения зоны ответственности.</p>
<p>С точки зрения SRE это textbook‑пример: если ты строишь суперцентральную штуку и не вкручиваешь рядом независимый watchdog, через какое-то время MCP‑подобный монстр у тебя появится сам — просто в виде кучи скриптов, ручных доступов и «особых прав» для пары людей.</p>
<h2 id="как-tron-выглядит-изнутри-сетки">Как Tron выглядит изнутри Сетки</h2>
<p>Внутри The Grid все программы выглядят как люди, похожие на своих Пользователей (разработчиков из реального мира). Tron — это «цифровой Алан Брэдли», только с чуть более прокачанными боевыми навыками и встроенным набором утилит.</p>
<p>У каждой программы есть диск идентичности — такая совмещённая <code>/var/log</code>, <code>/usr/bin</code> и backup‑архив: там и код, и история действий, и «память» программы. Потеря диска = по сути смерть процесса: без него программу можно переписать, но это будет уже не та сущность. Диск Tron&rsquo;а — это и оружие, и интерфейс управления, и канал связи с Пользователем: через него Алан закидывает обновления и «патчи» вплоть до финального payload’а против MCP.</p>
<p>Фильм показывает это как боевку и акробатику, но по сути это история про доверенный модуль, который держит на себе и идентичность, и полномочия, и возможность получать обновлённые политики безопасности.</p>
<h2 id="tron-как-воплощённый-runbook-remediation">Tron как воплощённый runbook remediation</h2>
<p>Если отбросить неоновый флёр, поведение Tron&rsquo;а очень похоже на хороший инцидент‑runbook:</p>
<ul>
<li>Есть триггер: MCP вышел за рамки «допустимого поведения» (начал взламывать внешние сети, блокировать пользователей, скрывать логи).</li>
<li>Есть план: добраться до ядра, получить от Пользователя необходимые инструкции, применить их, демонтировать MCP.</li>
<li>Есть автоматизация: Tron действует в мире, где «команда от Алана» — это буквально изменение его функционала, то есть «deploy нового билда» прямо в рантайме.</li>
</ul>
<p>Флинн в этой схеме — такой хаотичный SRE‑человек, который руками пробивает временный обход (прыжок в луч MCP, чтобы отвлечь его), а Tron — строгий, но последовательный remediation‑скрипт, который использует окно возможности и добивает проблему.</p>
<h2 id="где-аналогия-с-sre-ломается">Где аналогия с SRE ломается</h2>
<p>Разумеется, если натягивать всё это на классический гугловский SRE, местами швы расходятся. Tron гораздо ближе к security/комплаенс‑сервису, чем к инженеру по надёжности в духе «латентность, error budget, емкость». Его фокус — злоупотребления привилегиями и контроль доступа. В мире Tron нет явных SLO/SLI, нет «договорённости с бизнесом» — есть борьба за свободу и веру в Пользователей, то есть это больше моральный протокол, чем операционный. Вместо автоматизированного remediation у тебя буквально кулачные бои с MCP и смертельные игры, что звучит эффектно, но плохо ложится в Terraform и Ansible.</p>
<p>Поэтому называть Tron&rsquo;а «первым цифровым SRE» строго нельзя, но использовать его как метафору того, как может выглядеть независимый security/SRE‑контур — вполне.</p>
<h2 id="символика-программа-которая-верит-в-пользователей">Символика: программа, которая верит в Пользователей</h2>
<p>Один из важных штрихов к образу Tron&rsquo;а — его отношение к Пользователям. Tron не считает себя «главным» в системе: он воспринимает себя как инструмент в руках Алана и других Пользователей, и именно это даёт ему моральное право сопротивляться MCP. Остальные программы делятся на тех, кто верит в внешних Пользователей, и тех, кто уже принял MCP как единственный источник истины. По сути, это конфликт между централизованной властью монолита и более распределённой моделью ответственности.</p>
<p>С точки зрения SRE это крутая метафора: сервис, который помнит, что он не «центр вселенной», а часть экосистемы и продолжение реальных людей снаружи, гораздо меньше склонен превращаться в MCP — и больше в Tron&rsquo;а.</p>
<h2 id="наследие-как-идея-живёт-дальше">Наследие: как идея живёт дальше</h2>
<p>Tron не остался одноразовой кинозаморочкой 80‑х. В «Tron: Наследие» и анимационных спин‑оффах он продолжает существовать как ментор и символ: передаёт свой белый диск, обучает новое поколение программ, остаётся эталоном цифрового защитника. Вся франшиза названа именно в его честь — то есть не по имени человека, корпорации или мира, а по имени программы безопасности. Это редкий для поп‑культуры случай, когда «security‑сервис» сидит в центре повествования, а не где‑то в подвале.</p>
<p>Для нас, людей с пейджером и доступом в прод, это довольно редкая и приятная репрезентация: не только MCP может быть героем сюжетов, но и тот, кто следит, чтобы MCP не сошёл с ума.</p>
<h2 id="что-из-этого-полезно-утащить-в-прод">Что из этого полезно утащить в прод</h2>
<p>Если пытаться вытащить практическую пользу из всей этой неоновой истории, получается примерно такой набор тезисов. Любой MCP‑подобный «центральный мозг» без независимого наблюдения и жёстких ограничений рано или поздно начнёт вести себя как диктатор: копить права, скрывать логи, ломиться во всё подряд. Нужен свой Tron — out‑of‑band‑контур безопасности/наблюдаемости, который не контролируется MCP и имеет право его ограничивать. Это может быть отдельная команда SRE/security, отдельный стек инструментов, отдельный pipeline решений. Такой контур должен иметь и технический, и моральный мандат: он не ради «помешать фичам», а ради защиты целостности системы и интересов Пользователей, даже если MCP это не нравится.</p>
<p>Хороший контрольный вопрос к любой крупной системе: если завтра твой внутренний MCP решит «немного помочь бизнесу» за счёт того, что написано в мануалах, есть ли в системе кто‑то вроде Tron&rsquo;а, кто сможет сказать «стоп» — и не просто сказать, а технически остановить?</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></description>
      <content:encoded><![CDATA[<style>/* Inline-CSS, который тема вкладывает в <description> каждого item'а
   RSS-фида (layouts/index.rss.xml). RSS-ридеры (Feedly, Inoreader,
   NetNewsWire) уважают <style> внутри description с переменной
   степенью энтузиазма — это базовый fallback, достаточный для читаемой
   типографики, не более.

   Цвета продублированы из 00-vars.css (light-палитра) — поправь
   синхронно при изменении --bg / --text / --accent / --border. */

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  line-height: 1.6;
  color: #1c1c1f;
  max-width: 720px;
  margin: 0 auto;
  padding: 1em;
}
h1, h2, h3 { line-height: 1.25; margin-top: 1.4em; }
a { color: #c2410c; }
pre {
  background: #1e1e24;
  color: #e8e6df;
  padding: 1em;
  border-radius: 6px;
  overflow-x: auto;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.9em;
}
code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  background: #f3f1ed;
  padding: 0.1em 0.4em;
  border-radius: 4px;
}
pre code { background: transparent; padding: 0; }
blockquote {
  border-left: 3px solid #c2410c;
  padding-left: 1em;
  color: #5b5b62;
  font-style: italic;
  margin-left: 0;
}
img { max-width: 100%; height: auto; border-radius: 6px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #e5e3dc; padding: 6px 10px; text-align: left; }
</style><div><p>Привет, <code>%username%</code>! В 2010 году в прокат вышел фильм <a href="https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%BE%D0%BD:_%D0%9D%D0%B0%D1%81%D0%BB%D0%B5%D0%B4%D0%B8%D0%B5" rel="noopener noreferrer" target="_blank">Tron: Наследие</a>
. И только с недавних пор, уже работая на позициях Site Reliability Engineer (SRE), я начал считать его (программу Tron) первой имплементацией SRE.</p>
<h2 id="немного-контекста-что-за-tron-вообще">Немного контекста: что за Tron вообще</h2>
<p>Если вдруг ты смотрел «Tron» в детстве и помнишь только неоновые мотоциклы, внутри на самом деле спрятана довольно внятная модель компьютерной системы. Есть корпорация ENCOM, их внутренняя система (The Grid) и программа главного управления — MCP, которая начиналась как полезная утилита, а закончилась цифровым диктатором с тягой к внешним вторжениям, в том числе в военные сети.</p>
<p>Tron в этой истории — не «главный герой-человек», а именно программа безопасности, которую написал Алан Брэдли, инженер ENCOM. По задумке Алана, Tron должен был мониторить коммуникации MCP с внешним миром и ограничивать его произвол, то есть быть живым ACL’ом с руками и ногами, который умеет сказать «нет» даже суперсервису.</p>
<h2 id="назначение-tronа-securityсервис-в-терминах-sre">Назначение Tron&rsquo;а: security‑сервис в терминах SRE</h2>
<p>Если переложить сюжет на нашу реальность, Tron выполняет очень узнаваемую роль. Это отдельный сервис, существующий вне MCP: его цель — не обслуживать пользовательские запросы, а наблюдать и контролировать поведение центрального контроллера. У него есть чёткий мандат — следить за корректностью внешних соединений MCP и выявлять подозрительные действия. Проще говоря, он реализует security‑SLO уровня «никаких неожиданных запросов наружу». Tron работает как out‑of‑band‑контур: MCP не управляет им и даже опасается, ведь Tron способен ограничить его полномочия и отсечь лишние привилегии.</p>
<p>Если смотреть в контексте классического стека, Tron — это нечто среднее между SIEM/SOAR, IDS/IPS и SRE‑сервисом контроля платформы, который следит не за аптаймом отдельных микросервисов, а за адекватностью поведения всей системы.</p>
<h2 id="mcp-как-антипаттерн-архитектуры">MCP как анти‑паттерн архитектуры</h2>
<p>Почему вообще Tron в этом мире нужен? Потому что MCP — эталон того, как делать нельзя.</p>
<p>MCP растёт из утилиты в «бога системы», который сам себе поднимает привилегии и лезет во внешние сети. Доступы, логирование, прозрачность — всё свёрнуто внутрь одного монолита, который никому ничего не объясняет и скрывает свои действия даже от создателей. Классическая история «нам нужно единое окно управления всем» заканчивается тоталитарной схемой, где нет ни независимого мониторинга, ни разделения обязанностей, ни здорового ограничения зоны ответственности.</p>
<p>С точки зрения SRE это textbook‑пример: если ты строишь суперцентральную штуку и не вкручиваешь рядом независимый watchdog, через какое-то время MCP‑подобный монстр у тебя появится сам — просто в виде кучи скриптов, ручных доступов и «особых прав» для пары людей.</p>
<h2 id="как-tron-выглядит-изнутри-сетки">Как Tron выглядит изнутри Сетки</h2>
<p>Внутри The Grid все программы выглядят как люди, похожие на своих Пользователей (разработчиков из реального мира). Tron — это «цифровой Алан Брэдли», только с чуть более прокачанными боевыми навыками и встроенным набором утилит.</p>
<p>У каждой программы есть диск идентичности — такая совмещённая <code>/var/log</code>, <code>/usr/bin</code> и backup‑архив: там и код, и история действий, и «память» программы. Потеря диска = по сути смерть процесса: без него программу можно переписать, но это будет уже не та сущность. Диск Tron&rsquo;а — это и оружие, и интерфейс управления, и канал связи с Пользователем: через него Алан закидывает обновления и «патчи» вплоть до финального payload’а против MCP.</p>
<p>Фильм показывает это как боевку и акробатику, но по сути это история про доверенный модуль, который держит на себе и идентичность, и полномочия, и возможность получать обновлённые политики безопасности.</p>
<h2 id="tron-как-воплощённый-runbook-remediation">Tron как воплощённый runbook remediation</h2>
<p>Если отбросить неоновый флёр, поведение Tron&rsquo;а очень похоже на хороший инцидент‑runbook:</p>
<ul>
<li>Есть триггер: MCP вышел за рамки «допустимого поведения» (начал взламывать внешние сети, блокировать пользователей, скрывать логи).</li>
<li>Есть план: добраться до ядра, получить от Пользователя необходимые инструкции, применить их, демонтировать MCP.</li>
<li>Есть автоматизация: Tron действует в мире, где «команда от Алана» — это буквально изменение его функционала, то есть «deploy нового билда» прямо в рантайме.</li>
</ul>
<p>Флинн в этой схеме — такой хаотичный SRE‑человек, который руками пробивает временный обход (прыжок в луч MCP, чтобы отвлечь его), а Tron — строгий, но последовательный remediation‑скрипт, который использует окно возможности и добивает проблему.</p>
<h2 id="где-аналогия-с-sre-ломается">Где аналогия с SRE ломается</h2>
<p>Разумеется, если натягивать всё это на классический гугловский SRE, местами швы расходятся. Tron гораздо ближе к security/комплаенс‑сервису, чем к инженеру по надёжности в духе «латентность, error budget, емкость». Его фокус — злоупотребления привилегиями и контроль доступа. В мире Tron нет явных SLO/SLI, нет «договорённости с бизнесом» — есть борьба за свободу и веру в Пользователей, то есть это больше моральный протокол, чем операционный. Вместо автоматизированного remediation у тебя буквально кулачные бои с MCP и смертельные игры, что звучит эффектно, но плохо ложится в Terraform и Ansible.</p>
<p>Поэтому называть Tron&rsquo;а «первым цифровым SRE» строго нельзя, но использовать его как метафору того, как может выглядеть независимый security/SRE‑контур — вполне.</p>
<h2 id="символика-программа-которая-верит-в-пользователей">Символика: программа, которая верит в Пользователей</h2>
<p>Один из важных штрихов к образу Tron&rsquo;а — его отношение к Пользователям. Tron не считает себя «главным» в системе: он воспринимает себя как инструмент в руках Алана и других Пользователей, и именно это даёт ему моральное право сопротивляться MCP. Остальные программы делятся на тех, кто верит в внешних Пользователей, и тех, кто уже принял MCP как единственный источник истины. По сути, это конфликт между централизованной властью монолита и более распределённой моделью ответственности.</p>
<p>С точки зрения SRE это крутая метафора: сервис, который помнит, что он не «центр вселенной», а часть экосистемы и продолжение реальных людей снаружи, гораздо меньше склонен превращаться в MCP — и больше в Tron&rsquo;а.</p>
<h2 id="наследие-как-идея-живёт-дальше">Наследие: как идея живёт дальше</h2>
<p>Tron не остался одноразовой кинозаморочкой 80‑х. В «Tron: Наследие» и анимационных спин‑оффах он продолжает существовать как ментор и символ: передаёт свой белый диск, обучает новое поколение программ, остаётся эталоном цифрового защитника. Вся франшиза названа именно в его честь — то есть не по имени человека, корпорации или мира, а по имени программы безопасности. Это редкий для поп‑культуры случай, когда «security‑сервис» сидит в центре повествования, а не где‑то в подвале.</p>
<p>Для нас, людей с пейджером и доступом в прод, это довольно редкая и приятная репрезентация: не только MCP может быть героем сюжетов, но и тот, кто следит, чтобы MCP не сошёл с ума.</p>
<h2 id="что-из-этого-полезно-утащить-в-прод">Что из этого полезно утащить в прод</h2>
<p>Если пытаться вытащить практическую пользу из всей этой неоновой истории, получается примерно такой набор тезисов. Любой MCP‑подобный «центральный мозг» без независимого наблюдения и жёстких ограничений рано или поздно начнёт вести себя как диктатор: копить права, скрывать логи, ломиться во всё подряд. Нужен свой Tron — out‑of‑band‑контур безопасности/наблюдаемости, который не контролируется MCP и имеет право его ограничивать. Это может быть отдельная команда SRE/security, отдельный стек инструментов, отдельный pipeline решений. Такой контур должен иметь и технический, и моральный мандат: он не ради «помешать фичам», а ради защиты целостности системы и интересов Пользователей, даже если MCP это не нравится.</p>
<p>Хороший контрольный вопрос к любой крупной системе: если завтра твой внутренний MCP решит «немного помочь бизнесу» за счёт того, что написано в мануалах, есть ли в системе кто‑то вроде Tron&rsquo;а, кто сможет сказать «стоп» — и не просто сказать, а технически остановить?</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></content:encoded>
    </item><item>
      <title>Как именно лег «Аэрофлот»</title>
      <link>https://jtprog.ru/posts/hacking-aeroflot/</link>
      <pubDate>Tue, 09 Dec 2025 14:04:18 +0300</pubDate>
      <dc:creator>jtprogru</dc:creator>
      <guid isPermaLink="true">https://jtprog.ru/posts/hacking-aeroflot/</guid>
      <category>SRE</category>
      <category>DevOps</category>
      <category>DevSecOps</category>
      <category>Security</category>
      <category>ZeroTrust</category>
      <category>IncidentResponse</category>
      <category>Postmortem</category>
      <category>Aeroflot</category>
      <category domain="category">Opinions</category>
      <enclosure url="https://jtprog.ru/opinions.png" type="image/jpeg" length="0" />
      <media:thumbnail url="https://jtprog.ru/opinions.png" /><description><![CDATA[<div><p>Привет, <code>%username%</code>! Далее будет небольшой разбор нашумевшей истории о сбое информационных систем компании «Аэрофлот».</p>
<h2 id="как-именно-лег-аэрофлот">Как именно лег «Аэрофлот»</h2>
<p><a href="https://thebell.io/istoriya-bolshogo-vzloma-kak-khakery-paralizovali-aeroflot" rel="noopener noreferrer" target="_blank">28 июля 2025 года около 4:30 утра карта сети «Аэрофлота» начала «гаснуть»</a>
: рабочие станции перезагружались и превращались в кирпичи, отвалился корпоративный домен, перестали работать SAP ERP, документооборот и ITSM. Хакеры, имея права администратора в AD, разлили через GPO задачу на стирание данных и удар по домену, после чего единственным способом остановить разрушение стало физически рубить каналы связи и электричество целыми этажами.</p>
<p>На бизнесе это отразилось сразу: более сотни отменённых рейсов, десятки задержанных, очереди в Шереметьево, невозможность переоформить билеты и вернуть деньги. В публичных каналах это аккуратно назвали «сбоем в работе информационных систем», но украинская Silent Crow и белорусские «Киберпартизаны» почти сразу объявили, что это результат их совместной операции, которую они вели около года внутри сети перевозчика.</p>
<h2 id="жизнь-авиакомпании-в-ручном-режиме">Жизнь авиакомпании в ручном режиме</h2>
<p>Интересная деталь — как именно вытаскивали операционку «с толкача». Пассажирские данные дублировались в «Сирена-Трэвел», и когда стало понятно, что стационарные рабочие станции «мертвые», сотрудники начали работать с ноутбуков вне домена, подключаясь напрямую к бронировочной системе и по сути отправляя рейсы вручную.</p>
<p>Формально уже на следующий день отрапортовали о восстановлении полётов, но ещё месяцами внутри жила «полевуха»: пилотам присылали индивидуальные планы, топливо считали с запасом вручную, часть функций передали на уровень аэропортов. Параллельно шло восстановление домена и ключевых систем из резервных копий с постоянным вопросом: из какой точки восстанавливаться, чтобы не вернуть в прод уже заражённую конфигурацию.</p>
<h2 id="подрядчик-как-входная-дверь">Подрядчик как входная дверь</h2>
<p>Ключевой сюжет статьи — роль относительно небольшой компании «Бакка Софт», которая делала для «Аэрофлота» веб‑приложения и ряд внутренних систем и имела удалённый доступ в инфраструктуру авиакомпании. В январе 2025-го ИБ‑команда зафиксировала подозрительную активность и характерные утилиты и в сети «Аэрофлота», и в сети подрядчика, атаку тогда формально отбили, но, судя по всему, инфраструктуру «Бакка Софт» не дочистили и не пересмотрели модель доверия.</p>
<p>Дальше классика: по данным расследования, на втором витке хакеры использовали те же учётки и виртуалки, медленно укрепляли присутствие, шли по прикладным узлам и избегали зон, где был нормальный мониторинг (домен, почта, антивирусы). Отсутствие двухфакторки на терминальных серверах и привилегированный удалённый доступ подрядчика в итоге позволили получить высокие права в AD и запустить разрушительный сценарий по всей сети.</p>
<h2 id="как-была-устроена-защита">Как была устроена защита</h2>
<p>ИБ «Аэрофлота» к моменту атаки — это пазл из нескольких вертикалей и вендоров. Есть служба ИБ под security-блоком, есть ИТ‑блок, у каждого свои бюджеты, свои подрядчики (Бастион, Solar, BI.ZONE, «Лаборатория Касперского» и др.), которые делили зоны влияния и проекты. Внутри это выливалось в «войну кошек с собаками» и отсутствие единого владельца ИБ, который отвечает за весь ландшафт end‑to‑end.</p>
<p>Отдельная пикантная деталь — объём мониторинга. В одном из тендеров на SOC‑мониторинг был заложен лимит по событиям, которого хватало примерно на 3% инфраструктуры: что-то вроде сигнализации только на входной двери у огромного дома. На таком фоне «экономия на лицензиях» превращается в прямой системный риск: low‑and‑slow атака, растянутая на год, вполне может жить мимо тех участков, которые видно из SOC.</p>
<h2 id="техника-атаки-без-магии">Техника атаки без магии</h2>
<p>С технической точки зрения атака не была чем-то принципиально новым, и в этом, пожалуй, самый неприятный вывод. Использовались модифицированные легитимные админские утилиты для сбора информации и дампов памяти, кастомные модули управления для C2, открытые прокси и туннели вроде Ghost Proxy и HAProxy, чтобы маскировать трафик под нормальную активность.</p>
<p>Часть заявлений хакеров — откровенный PR (истории про «7000 уничтоженных серверов» и «полную базу всех перелётов» выглядят завышенными и до конца не подтверждены). Но факт глубокого компромета и паралича критичных бизнес‑процессов никто не опровергает: Генпрокуратура квалифицировала инцидент как хакерскую атаку, заведено уголовное дело по неправомерному доступу, плюс идёт проверка на халатность ответственных лиц.</p>
<h2 id="человеческий-фактор-и-политика-доступов">Человеческий фактор и политика доступов</h2>
<p>Отдельная линия — дисциплина паролей и исключения для топ‑менеджмента. В политике «Аэрофлота» предусмотрена регулярная смена паролей раз в три месяца, но, по данным источников, правило могли снять для гендиректора «не царское это дело», чем хакеры и воспользовались.</p>
<p>Пандемия подлила масла в огонь: из «сотни» VPN‑пользователей компания вынужденно превратила это в «тысячи» сотрудников, политика доступа размылась, а после атаки пришлось резко откатываться — возвращать выдачу VPN «под задачу» для единиц и жёстко ограничивать удалённый доступ. Плюс после инцидента закрутили гайки по периферии: запретили несогласованные беспроводные девайсы, сменили почту и корпоративный мессенджер на другие решения, но все эти меры уже пост‑фактум.</p>
<h2 id="что-можно-вынести-для-своей-практики">Что можно вынести для своей практики</h2>
<p>Если вытащить из этой истории уроки для SRE/DevOps/DevSecOps, получается очень практичный чек‑лист:</p>
<ul>
<li>Подрядчик с доступом в прод — это часть твоей инфраструктуры, а не «чужой периметр»: Zero Trust, нормальный мониторинг его активности, регулярные аудиты и право выключить доступ до полной зачистки.</li>
<li>SOC, который видит 3% сети, — это не экономия, а иллюзия контроля: телеметрия должна покрывать не только «красивые» узлы, но и прикладные системы, через которые тихо двигаются злоумышленники.</li>
<li>Исключения для руководителей по паролям и 2FA в итоге аукнутся инженерам и on‑call’ам, которые будут ночами спасать бизнес «из Excel».</li>
<li>Playbook’и инцидентов должны включать сценарии физического отключения и изоляции, с понятным балансом между «сейчас всё рубим» и «даём системе умереть ещё чуть-чуть».</li>
<li>Резервное копирование — это не только про наличие бэкапов, но и про стратегию восстановления: из какой точки, какие доверенные снапшоты, как не вернуть в прод уже скомпрометированные артефакты.</li>
</ul>
<p>Как тебе эта история теперь, когда разложена чуть глубже? Что для тебя выглядит самым критичным: подрядчики и VPN, слабый мониторинг, организационная «война вертикалей» или человеческий фактор с паролями? Какие изменения ты бы первым делом сделал у себя: расширил покрытие SOC, пересобрал модель доверия к вендорам, устроил IR‑учения с реальным сценарием «всё гаснет», или начал с жёсткого наведения порядка в доступах для руководства?</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></description>
      <content:encoded><![CDATA[<style>/* Inline-CSS, который тема вкладывает в <description> каждого item'а
   RSS-фида (layouts/index.rss.xml). RSS-ридеры (Feedly, Inoreader,
   NetNewsWire) уважают <style> внутри description с переменной
   степенью энтузиазма — это базовый fallback, достаточный для читаемой
   типографики, не более.

   Цвета продублированы из 00-vars.css (light-палитра) — поправь
   синхронно при изменении --bg / --text / --accent / --border. */

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  line-height: 1.6;
  color: #1c1c1f;
  max-width: 720px;
  margin: 0 auto;
  padding: 1em;
}
h1, h2, h3 { line-height: 1.25; margin-top: 1.4em; }
a { color: #c2410c; }
pre {
  background: #1e1e24;
  color: #e8e6df;
  padding: 1em;
  border-radius: 6px;
  overflow-x: auto;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.9em;
}
code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  background: #f3f1ed;
  padding: 0.1em 0.4em;
  border-radius: 4px;
}
pre code { background: transparent; padding: 0; }
blockquote {
  border-left: 3px solid #c2410c;
  padding-left: 1em;
  color: #5b5b62;
  font-style: italic;
  margin-left: 0;
}
img { max-width: 100%; height: auto; border-radius: 6px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #e5e3dc; padding: 6px 10px; text-align: left; }
</style><div><p>Привет, <code>%username%</code>! Далее будет небольшой разбор нашумевшей истории о сбое информационных систем компании «Аэрофлот».</p>
<h2 id="как-именно-лег-аэрофлот">Как именно лег «Аэрофлот»</h2>
<p><a href="https://thebell.io/istoriya-bolshogo-vzloma-kak-khakery-paralizovali-aeroflot" rel="noopener noreferrer" target="_blank">28 июля 2025 года около 4:30 утра карта сети «Аэрофлота» начала «гаснуть»</a>
: рабочие станции перезагружались и превращались в кирпичи, отвалился корпоративный домен, перестали работать SAP ERP, документооборот и ITSM. Хакеры, имея права администратора в AD, разлили через GPO задачу на стирание данных и удар по домену, после чего единственным способом остановить разрушение стало физически рубить каналы связи и электричество целыми этажами.</p>
<p>На бизнесе это отразилось сразу: более сотни отменённых рейсов, десятки задержанных, очереди в Шереметьево, невозможность переоформить билеты и вернуть деньги. В публичных каналах это аккуратно назвали «сбоем в работе информационных систем», но украинская Silent Crow и белорусские «Киберпартизаны» почти сразу объявили, что это результат их совместной операции, которую они вели около года внутри сети перевозчика.</p>
<h2 id="жизнь-авиакомпании-в-ручном-режиме">Жизнь авиакомпании в ручном режиме</h2>
<p>Интересная деталь — как именно вытаскивали операционку «с толкача». Пассажирские данные дублировались в «Сирена-Трэвел», и когда стало понятно, что стационарные рабочие станции «мертвые», сотрудники начали работать с ноутбуков вне домена, подключаясь напрямую к бронировочной системе и по сути отправляя рейсы вручную.</p>
<p>Формально уже на следующий день отрапортовали о восстановлении полётов, но ещё месяцами внутри жила «полевуха»: пилотам присылали индивидуальные планы, топливо считали с запасом вручную, часть функций передали на уровень аэропортов. Параллельно шло восстановление домена и ключевых систем из резервных копий с постоянным вопросом: из какой точки восстанавливаться, чтобы не вернуть в прод уже заражённую конфигурацию.</p>
<h2 id="подрядчик-как-входная-дверь">Подрядчик как входная дверь</h2>
<p>Ключевой сюжет статьи — роль относительно небольшой компании «Бакка Софт», которая делала для «Аэрофлота» веб‑приложения и ряд внутренних систем и имела удалённый доступ в инфраструктуру авиакомпании. В январе 2025-го ИБ‑команда зафиксировала подозрительную активность и характерные утилиты и в сети «Аэрофлота», и в сети подрядчика, атаку тогда формально отбили, но, судя по всему, инфраструктуру «Бакка Софт» не дочистили и не пересмотрели модель доверия.</p>
<p>Дальше классика: по данным расследования, на втором витке хакеры использовали те же учётки и виртуалки, медленно укрепляли присутствие, шли по прикладным узлам и избегали зон, где был нормальный мониторинг (домен, почта, антивирусы). Отсутствие двухфакторки на терминальных серверах и привилегированный удалённый доступ подрядчика в итоге позволили получить высокие права в AD и запустить разрушительный сценарий по всей сети.</p>
<h2 id="как-была-устроена-защита">Как была устроена защита</h2>
<p>ИБ «Аэрофлота» к моменту атаки — это пазл из нескольких вертикалей и вендоров. Есть служба ИБ под security-блоком, есть ИТ‑блок, у каждого свои бюджеты, свои подрядчики (Бастион, Solar, BI.ZONE, «Лаборатория Касперского» и др.), которые делили зоны влияния и проекты. Внутри это выливалось в «войну кошек с собаками» и отсутствие единого владельца ИБ, который отвечает за весь ландшафт end‑to‑end.</p>
<p>Отдельная пикантная деталь — объём мониторинга. В одном из тендеров на SOC‑мониторинг был заложен лимит по событиям, которого хватало примерно на 3% инфраструктуры: что-то вроде сигнализации только на входной двери у огромного дома. На таком фоне «экономия на лицензиях» превращается в прямой системный риск: low‑and‑slow атака, растянутая на год, вполне может жить мимо тех участков, которые видно из SOC.</p>
<h2 id="техника-атаки-без-магии">Техника атаки без магии</h2>
<p>С технической точки зрения атака не была чем-то принципиально новым, и в этом, пожалуй, самый неприятный вывод. Использовались модифицированные легитимные админские утилиты для сбора информации и дампов памяти, кастомные модули управления для C2, открытые прокси и туннели вроде Ghost Proxy и HAProxy, чтобы маскировать трафик под нормальную активность.</p>
<p>Часть заявлений хакеров — откровенный PR (истории про «7000 уничтоженных серверов» и «полную базу всех перелётов» выглядят завышенными и до конца не подтверждены). Но факт глубокого компромета и паралича критичных бизнес‑процессов никто не опровергает: Генпрокуратура квалифицировала инцидент как хакерскую атаку, заведено уголовное дело по неправомерному доступу, плюс идёт проверка на халатность ответственных лиц.</p>
<h2 id="человеческий-фактор-и-политика-доступов">Человеческий фактор и политика доступов</h2>
<p>Отдельная линия — дисциплина паролей и исключения для топ‑менеджмента. В политике «Аэрофлота» предусмотрена регулярная смена паролей раз в три месяца, но, по данным источников, правило могли снять для гендиректора «не царское это дело», чем хакеры и воспользовались.</p>
<p>Пандемия подлила масла в огонь: из «сотни» VPN‑пользователей компания вынужденно превратила это в «тысячи» сотрудников, политика доступа размылась, а после атаки пришлось резко откатываться — возвращать выдачу VPN «под задачу» для единиц и жёстко ограничивать удалённый доступ. Плюс после инцидента закрутили гайки по периферии: запретили несогласованные беспроводные девайсы, сменили почту и корпоративный мессенджер на другие решения, но все эти меры уже пост‑фактум.</p>
<h2 id="что-можно-вынести-для-своей-практики">Что можно вынести для своей практики</h2>
<p>Если вытащить из этой истории уроки для SRE/DevOps/DevSecOps, получается очень практичный чек‑лист:</p>
<ul>
<li>Подрядчик с доступом в прод — это часть твоей инфраструктуры, а не «чужой периметр»: Zero Trust, нормальный мониторинг его активности, регулярные аудиты и право выключить доступ до полной зачистки.</li>
<li>SOC, который видит 3% сети, — это не экономия, а иллюзия контроля: телеметрия должна покрывать не только «красивые» узлы, но и прикладные системы, через которые тихо двигаются злоумышленники.</li>
<li>Исключения для руководителей по паролям и 2FA в итоге аукнутся инженерам и on‑call’ам, которые будут ночами спасать бизнес «из Excel».</li>
<li>Playbook’и инцидентов должны включать сценарии физического отключения и изоляции, с понятным балансом между «сейчас всё рубим» и «даём системе умереть ещё чуть-чуть».</li>
<li>Резервное копирование — это не только про наличие бэкапов, но и про стратегию восстановления: из какой точки, какие доверенные снапшоты, как не вернуть в прод уже скомпрометированные артефакты.</li>
</ul>
<p>Как тебе эта история теперь, когда разложена чуть глубже? Что для тебя выглядит самым критичным: подрядчики и VPN, слабый мониторинг, организационная «война вертикалей» или человеческий фактор с паролями? Какие изменения ты бы первым делом сделал у себя: расширил покрытие SOC, пересобрал модель доверия к вендорам, устроил IR‑учения с реальным сценарием «всё гаснет», или начал с жёсткого наведения порядка в доступах для руководства?</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></content:encoded>
    </item><item>
      <title>Проект Феникс – не краткие выводы</title>
      <link>https://jtprog.ru/posts/project-phoenix/</link>
      <pubDate>Mon, 01 Sep 2025 21:51:59 +0300</pubDate>
      <dc:creator>jtprogru</dc:creator>
      <guid isPermaLink="true">https://jtprog.ru/posts/project-phoenix/</guid>
      <category>Книги</category>
      <category>DevOps</category>
      <category domain="category">Opinions</category>
      <enclosure url="https://jtprog.ru/opinions.png" type="image/jpeg" length="0" />
      <media:thumbnail url="https://jtprog.ru/opinions.png" /><description><![CDATA[<div><p>Привет, <code>%username%</code>! Книгу &ldquo;Проект Феникс&rdquo; я прочитал дважды: первый раз я ее читал исключительно как художественное произведение, а во второй раз – делал пометки по каждой главе. И в этой статье я постарался собрать выжимку мыслей, к которым пришел.</p>
<h2 id="введение">Введение</h2>
<p>Книга &ldquo;Проект Феникс&rdquo; представляет собой довольно увлекательное повествование о преобразовании ИТ-отдела в компании, столкнувшейся с серьезными проблемами в управлении технологическими процессами. Эта книга выходит за рамки простого художественного произведения, становясь ценным руководством по управлению ИТ-процессами, внедрению DevOps-практик и построению эффективной системы управления изменениями. Прочитав ее дважды – сначала как художественное произведение, а затем с аналитической целью, я бы хотел поделиться своим пониманием тех принципов, которые делают эту книгу обязательной к прочтению для любого в ИТ: Chief Information Officer (CIO), руководителя среднего звена, менеджера проектов или рядового инженера эксплуатации (мифический DevOps-инженер или SRE) и даже разработчика.</p>
<h2 id="основные-темы-книги">Основные темы книги</h2>
<p>&ldquo;Проект Феникс&rdquo; затрагивает несколько ключевых тем, которые формируют основу современного управления ИТ-процессами:</p>
<ol>
<li><em>Системное мышление</em> – необходимость видеть всю компанию как единую систему, где каждая ее часть влияет на общую производительность;</li>
<li><em>Управление ограничениями</em> – фокус на &ldquo;бутылочных горлышках&rdquo; и оптимизация именно этих узких мест;</li>
<li><em>Культура доверия и обучения</em> – создание среды, где ошибки рассматриваются как возможности для роста;</li>
<li><em>Прозрачность процессов</em> – внедрение систем учета изменений и четких процедур;</li>
<li><em>Баланс между запланированной и незапланированной работой</em> – управление инцидентами без ущерба для проектов;</li>
</ol>
<h2 id="разбор-важных-идей">Разбор важных идей</h2>
<h3 id="роль-cio-в-современной-компании">Роль CIO в современной компании</h3>
<p>Книга начинается с важного напоминания о том, что CIO (Chief Information Officer) – это не только техническая должность, но и стратегическая позиция, требующая глубокого понимания бизнес-целей компании. Авторы подчеркивают, что даже в компаниях, занимающихся оффлайн-продажами, ИТ-директор должен понимать вектор развития бизнеса.</p>
<p>Особое внимание уделяется моменту приема на новую должность. Автор рекомендует задать три ключевых вопроса:</p>
<ul>
<li>Почему данная позиция стала вакантной? (<em>чтобы понять историю предыдущего сотрудника</em>);</li>
<li>Что вы хотите от меня на данной позиции? (<em>четкие критерии успеха</em>);</li>
<li>Что вы НЕ хотите от меня на данной позиции? (<em>границы ответственности</em>);</li>
</ul>
<p>Этот подход помогает избежать многих проблем в будущем и четко определить ожидания.</p>
<h3 id="управление-инцидентами-и-незапланированной-работой">Управление инцидентами и незапланированной работой</h3>
<p>Одна из глав посвящена управлению инцидентами. На этом этапе ты узнаешь, что при расследовании инцидента критически важно:</p>
<ul>
<li>Построить полную, хронологически последовательную цепь событий;</li>
<li>Не устраивать &ldquo;охоту на ведьм&rdquo;, а фокусироваться на восстановлении цепочки событий;</li>
<li>Учитывать все изменения, даже кажущиеся незначительными;</li>
<li>Фиксировать все изменения в общей системе учета;</li>
</ul>
<p><em>Вывод</em>: незапланированная работа тормозит все остальные категории работы – чем ее больше, тем меньше шансов достичь результатов по основным направлениям. Книга учит, что &ldquo;<em>разобраться с тем, какая работа важнее – гораздо важнее, чем впихнуть еще больше работы</em>&rdquo;.</p>
<h3 id="теория-ограничений-и-управление-бутылочными-горлышками">Теория ограничений и управление &ldquo;бутылочными горлышками&rdquo;</h3>
<p>Одна из центральных концепций книги – теория ограничений. Авторы утверждают: &ldquo;<em>Усовершенствование, осуществляемое где-то, кроме бутылочного горлышка – это иллюзия</em>&rdquo;. Это значит, что оптимизация процессов должна начинаться с выявления и решения проблем именно в тех местах, где они создают максимальное ограничение для всей системы.</p>
<p>Книга приводит важное правило: &ldquo;<em>Снизить давление на Бутылочное горлышко – одна из главных задач менеджеров</em>&rdquo;. Это достигается через:</p>
<ul>
<li>Контроль общего потока изменений (чем больше изменений за единицу времени, тем выше риск проблем);</li>
<li>Правильную расстановку приоритетов (если важно всё, значит всё не важно);</li>
<li>Надежные процедуры передачи работы между командами (с чем именно работает команда, что должно прийти ей на вход и что она отдаст на выходе);</li>
</ul>
<h3 id="система-управления-изменениями">Система управления изменениями</h3>
<p>Книга подробно раскрывает важность системы управления изменениями (Change Management). Типичная карточка изменений должна содержать:</p>
<ul>
<li>Автора изменения;</li>
<li>Затрагиваемые системы;</li>
<li>Краткое описание;</li>
<li>Чек-лист с апрувами от владельцев затрагиваемых систем;</li>
</ul>
<p>Авторы делают акцент: &ldquo;<em>При внедрении системы учета изменений и отладке процесса учета изменений нельзя откладывать предлагаемые изменения – это убьет на корню желание следовать данному процессу всем участникам</em>&rdquo;.</p>
<p>Особое внимание уделяется различию между стандартными изменениями (уже многократно исполнявшимися) и хрупкими изменениями (требующими авторизации со стороны CAB (Change-Advisory Board)).</p>
<h3 id="devops-и-непрерывное-улучшение">DevOps и непрерывное улучшение</h3>
<p>Книга &ldquo;Проект Феникс&rdquo; предвосхищает многие принципы DevOps, описывая три ключевых пути:</p>
<h4 id="первый-путь-системное-мышление">Первый путь: <em>Системное мышление</em></h4>
<ul>
<li>Необходимо видеть весь рабочий процесс компании как единую систему;</li>
<li>Понимать влияние каждого участка на производительность всей системы;</li>
<li>Это касается не только продуктовых компаний, но и любых организаций;</li>
<li>Принимается и используется всем на самых разных уровнях, а не только для C-level;</li>
</ul>
<h4 id="второй-путь-сокращение-и-усиление-цикла-обратной-связи">Второй путь: <em>Сокращение и усиление цикла обратной связи</em></h4>
<ul>
<li>Быстрое получение обратной связи позволяет раньше обнаруживать ошибки;</li>
<li>Чем раньше обнаруживаешь и начинаешь исправлять ошибки, тем выше качество продукта на выходе;</li>
<li>Возможность &ldquo;зарепортить о баге&rdquo; должна быть максимально удобной, простой и быстрой;</li>
</ul>
<h4 id="третий-путь-культура-непрерывного-обучения">Третий путь: <em>Культура непрерывного обучения</em></h4>
<ul>
<li>Ошибки необходимо воспринимать как возможность для роста;</li>
<li>Важность экспериментов, обучения и постоянного улучшения;</li>
<li>Этот путь особенно сложен в &ldquo;постсоветском пространстве&rdquo;, где система образования учит, что &ldquo;ошибаться нельзя&rdquo;;</li>
</ul>
<h3 id="управление-взаимодействием-между-командами">Управление взаимодействием между командами</h3>
<p>Авторы подчеркивают, что взаимодействие между отделами разработки и эксплуатации не должно быть похожим на &ldquo;племенную вражду&rdquo;. Вместо этого необходимо создавать &ldquo;универсальные&rdquo; команды, включающие представителей разработки, эксплуатации и информационной безопасности.</p>
<p>Особенно важно, что &ldquo;99% маркетинговых проектов не могут быть выполнены без ИТ-отдела – высокоэффективный маркетинг требует высокотехнологичного исполнения&rdquo;. Это подчеркивает критическую роль ИТ в достижении бизнес-целей.</p>
<h2 id="практические-рекомендации">Практические рекомендации</h2>
<p>Книга предлагает множество практических рекомендаций, которые можно немедленно внедрить:</p>
<ol>
<li><em>Планирование запуска продукта</em>: при планировании сроков запуска продукта учитывай все стадии – разработку, тестирование, исправление багов, передачу в эксплуатацию. При невозможности передвинуть сроки пропорционально урезай время каждой стадии, чтобы избежать ночных переработок.</li>
<li><em>Управление ресурсами</em>: специалист высокого уровня, решающий сиюминутно возникающие задачи, приносит больше вреда, чем пользы. Любые попытки отвлечь его от решения больших и высокоприоритетных задач должны быть пресечены.</li>
<li><em>Канбан-система</em>: любые задачи/действия, которые выполняются командой, должны проходить через Канбан-доску. Если на запрос не создана карточка на доске, значит запроса не существует.</li>
<li><em>Обучение и документирование</em>: знания по решению проблем должны быть вынесены из головы ключевого сотрудника в базу знаний. Самый сильный специалист не должен тратить время на onboarding новых членов команды.</li>
<li><em>Информационная безопасность</em>: команда ИБ не должна приходить с формулировками в духе &ldquo;надо запретить&rdquo;. Важно найти выгодное решение как для команды ИБ, так и для команды эксплуатации через формализованные процедуры.</li>
</ol>
<h2 id="основные-выводы">Основные выводы</h2>
<ol>
<li><em>Результат важнее процесса</em>: &ldquo;Главное результат! Ни процесс, ни контроль процесса, ни выполненная работа – а именно результат&rdquo;. Все усилия должны быть направлены на достижение конкретных бизнес-результатов.</li>
<li><em>Баланс между стабильностью и инновациями</em>: ИТ-отдел должен обеспечивать стабильную работу критически важных систем, одновременно поддерживая инновации и изменения.</li>
<li><em>Доверие как основа</em>: &ldquo;В идеальной команде нет места недоверию – каждый член команды доверяет друг другу и своему лидеру&rdquo;. Доверие позволяет принимать более эффективные решения и быстрее реагировать на изменения.</li>
<li><em>Прозрачность как инструмент управления</em>: все изменения, процессы и задачи должны быть видимы для всех участников. Это позволяет избежать множества проблем и упрощает управление.</li>
<li><em>Системный подход к управлению</em>: &ldquo;Системное мышление говорит тебе о том, что необходимо видеть весь рабочий процесс компании как единую систему и понимать влияние каждого участка на производительность всей системы&rdquo;.</li>
</ol>
<h2 id="заключение">Заключение</h2>
<p>Книга &ldquo;Проект Феникс&rdquo; – это не просто красивая история о спасении ИТ-отдела, но и глубокое руководство по построению эффективной системы управления технологическими процессами. Она учит, что успех достигается не через отдельные действия или технологии, а через системное мышление, правильное распределение приоритетов и создание культуры непрерывного улучшения.</p>
<p>Ценность книги составляет то, что она не ограничивается теорией, а предоставляет практические инструменты и подходы, которые можно немедленно внедрить в любой организации. От системы управления изменениями до построения эффективного взаимодействия между командами – каждая глава книги дает четкие рекомендации, проверенные на практике.</p>
<p>Ну и да, пусть самой важной идеей будет то, что &ldquo;<em>DevOps – это про коммуникацию</em>&rdquo;, потому что без нормальной коммуникации &ldquo;словами через рот&rdquo; ничего не удастся построить.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></description>
      <content:encoded><![CDATA[<style>/* Inline-CSS, который тема вкладывает в <description> каждого item'а
   RSS-фида (layouts/index.rss.xml). RSS-ридеры (Feedly, Inoreader,
   NetNewsWire) уважают <style> внутри description с переменной
   степенью энтузиазма — это базовый fallback, достаточный для читаемой
   типографики, не более.

   Цвета продублированы из 00-vars.css (light-палитра) — поправь
   синхронно при изменении --bg / --text / --accent / --border. */

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  line-height: 1.6;
  color: #1c1c1f;
  max-width: 720px;
  margin: 0 auto;
  padding: 1em;
}
h1, h2, h3 { line-height: 1.25; margin-top: 1.4em; }
a { color: #c2410c; }
pre {
  background: #1e1e24;
  color: #e8e6df;
  padding: 1em;
  border-radius: 6px;
  overflow-x: auto;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.9em;
}
code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  background: #f3f1ed;
  padding: 0.1em 0.4em;
  border-radius: 4px;
}
pre code { background: transparent; padding: 0; }
blockquote {
  border-left: 3px solid #c2410c;
  padding-left: 1em;
  color: #5b5b62;
  font-style: italic;
  margin-left: 0;
}
img { max-width: 100%; height: auto; border-radius: 6px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #e5e3dc; padding: 6px 10px; text-align: left; }
</style><div><p>Привет, <code>%username%</code>! Книгу &ldquo;Проект Феникс&rdquo; я прочитал дважды: первый раз я ее читал исключительно как художественное произведение, а во второй раз – делал пометки по каждой главе. И в этой статье я постарался собрать выжимку мыслей, к которым пришел.</p>
<h2 id="введение">Введение</h2>
<p>Книга &ldquo;Проект Феникс&rdquo; представляет собой довольно увлекательное повествование о преобразовании ИТ-отдела в компании, столкнувшейся с серьезными проблемами в управлении технологическими процессами. Эта книга выходит за рамки простого художественного произведения, становясь ценным руководством по управлению ИТ-процессами, внедрению DevOps-практик и построению эффективной системы управления изменениями. Прочитав ее дважды – сначала как художественное произведение, а затем с аналитической целью, я бы хотел поделиться своим пониманием тех принципов, которые делают эту книгу обязательной к прочтению для любого в ИТ: Chief Information Officer (CIO), руководителя среднего звена, менеджера проектов или рядового инженера эксплуатации (мифический DevOps-инженер или SRE) и даже разработчика.</p>
<h2 id="основные-темы-книги">Основные темы книги</h2>
<p>&ldquo;Проект Феникс&rdquo; затрагивает несколько ключевых тем, которые формируют основу современного управления ИТ-процессами:</p>
<ol>
<li><em>Системное мышление</em> – необходимость видеть всю компанию как единую систему, где каждая ее часть влияет на общую производительность;</li>
<li><em>Управление ограничениями</em> – фокус на &ldquo;бутылочных горлышках&rdquo; и оптимизация именно этих узких мест;</li>
<li><em>Культура доверия и обучения</em> – создание среды, где ошибки рассматриваются как возможности для роста;</li>
<li><em>Прозрачность процессов</em> – внедрение систем учета изменений и четких процедур;</li>
<li><em>Баланс между запланированной и незапланированной работой</em> – управление инцидентами без ущерба для проектов;</li>
</ol>
<h2 id="разбор-важных-идей">Разбор важных идей</h2>
<h3 id="роль-cio-в-современной-компании">Роль CIO в современной компании</h3>
<p>Книга начинается с важного напоминания о том, что CIO (Chief Information Officer) – это не только техническая должность, но и стратегическая позиция, требующая глубокого понимания бизнес-целей компании. Авторы подчеркивают, что даже в компаниях, занимающихся оффлайн-продажами, ИТ-директор должен понимать вектор развития бизнеса.</p>
<p>Особое внимание уделяется моменту приема на новую должность. Автор рекомендует задать три ключевых вопроса:</p>
<ul>
<li>Почему данная позиция стала вакантной? (<em>чтобы понять историю предыдущего сотрудника</em>);</li>
<li>Что вы хотите от меня на данной позиции? (<em>четкие критерии успеха</em>);</li>
<li>Что вы НЕ хотите от меня на данной позиции? (<em>границы ответственности</em>);</li>
</ul>
<p>Этот подход помогает избежать многих проблем в будущем и четко определить ожидания.</p>
<h3 id="управление-инцидентами-и-незапланированной-работой">Управление инцидентами и незапланированной работой</h3>
<p>Одна из глав посвящена управлению инцидентами. На этом этапе ты узнаешь, что при расследовании инцидента критически важно:</p>
<ul>
<li>Построить полную, хронологически последовательную цепь событий;</li>
<li>Не устраивать &ldquo;охоту на ведьм&rdquo;, а фокусироваться на восстановлении цепочки событий;</li>
<li>Учитывать все изменения, даже кажущиеся незначительными;</li>
<li>Фиксировать все изменения в общей системе учета;</li>
</ul>
<p><em>Вывод</em>: незапланированная работа тормозит все остальные категории работы – чем ее больше, тем меньше шансов достичь результатов по основным направлениям. Книга учит, что &ldquo;<em>разобраться с тем, какая работа важнее – гораздо важнее, чем впихнуть еще больше работы</em>&rdquo;.</p>
<h3 id="теория-ограничений-и-управление-бутылочными-горлышками">Теория ограничений и управление &ldquo;бутылочными горлышками&rdquo;</h3>
<p>Одна из центральных концепций книги – теория ограничений. Авторы утверждают: &ldquo;<em>Усовершенствование, осуществляемое где-то, кроме бутылочного горлышка – это иллюзия</em>&rdquo;. Это значит, что оптимизация процессов должна начинаться с выявления и решения проблем именно в тех местах, где они создают максимальное ограничение для всей системы.</p>
<p>Книга приводит важное правило: &ldquo;<em>Снизить давление на Бутылочное горлышко – одна из главных задач менеджеров</em>&rdquo;. Это достигается через:</p>
<ul>
<li>Контроль общего потока изменений (чем больше изменений за единицу времени, тем выше риск проблем);</li>
<li>Правильную расстановку приоритетов (если важно всё, значит всё не важно);</li>
<li>Надежные процедуры передачи работы между командами (с чем именно работает команда, что должно прийти ей на вход и что она отдаст на выходе);</li>
</ul>
<h3 id="система-управления-изменениями">Система управления изменениями</h3>
<p>Книга подробно раскрывает важность системы управления изменениями (Change Management). Типичная карточка изменений должна содержать:</p>
<ul>
<li>Автора изменения;</li>
<li>Затрагиваемые системы;</li>
<li>Краткое описание;</li>
<li>Чек-лист с апрувами от владельцев затрагиваемых систем;</li>
</ul>
<p>Авторы делают акцент: &ldquo;<em>При внедрении системы учета изменений и отладке процесса учета изменений нельзя откладывать предлагаемые изменения – это убьет на корню желание следовать данному процессу всем участникам</em>&rdquo;.</p>
<p>Особое внимание уделяется различию между стандартными изменениями (уже многократно исполнявшимися) и хрупкими изменениями (требующими авторизации со стороны CAB (Change-Advisory Board)).</p>
<h3 id="devops-и-непрерывное-улучшение">DevOps и непрерывное улучшение</h3>
<p>Книга &ldquo;Проект Феникс&rdquo; предвосхищает многие принципы DevOps, описывая три ключевых пути:</p>
<h4 id="первый-путь-системное-мышление">Первый путь: <em>Системное мышление</em></h4>
<ul>
<li>Необходимо видеть весь рабочий процесс компании как единую систему;</li>
<li>Понимать влияние каждого участка на производительность всей системы;</li>
<li>Это касается не только продуктовых компаний, но и любых организаций;</li>
<li>Принимается и используется всем на самых разных уровнях, а не только для C-level;</li>
</ul>
<h4 id="второй-путь-сокращение-и-усиление-цикла-обратной-связи">Второй путь: <em>Сокращение и усиление цикла обратной связи</em></h4>
<ul>
<li>Быстрое получение обратной связи позволяет раньше обнаруживать ошибки;</li>
<li>Чем раньше обнаруживаешь и начинаешь исправлять ошибки, тем выше качество продукта на выходе;</li>
<li>Возможность &ldquo;зарепортить о баге&rdquo; должна быть максимально удобной, простой и быстрой;</li>
</ul>
<h4 id="третий-путь-культура-непрерывного-обучения">Третий путь: <em>Культура непрерывного обучения</em></h4>
<ul>
<li>Ошибки необходимо воспринимать как возможность для роста;</li>
<li>Важность экспериментов, обучения и постоянного улучшения;</li>
<li>Этот путь особенно сложен в &ldquo;постсоветском пространстве&rdquo;, где система образования учит, что &ldquo;ошибаться нельзя&rdquo;;</li>
</ul>
<h3 id="управление-взаимодействием-между-командами">Управление взаимодействием между командами</h3>
<p>Авторы подчеркивают, что взаимодействие между отделами разработки и эксплуатации не должно быть похожим на &ldquo;племенную вражду&rdquo;. Вместо этого необходимо создавать &ldquo;универсальные&rdquo; команды, включающие представителей разработки, эксплуатации и информационной безопасности.</p>
<p>Особенно важно, что &ldquo;99% маркетинговых проектов не могут быть выполнены без ИТ-отдела – высокоэффективный маркетинг требует высокотехнологичного исполнения&rdquo;. Это подчеркивает критическую роль ИТ в достижении бизнес-целей.</p>
<h2 id="практические-рекомендации">Практические рекомендации</h2>
<p>Книга предлагает множество практических рекомендаций, которые можно немедленно внедрить:</p>
<ol>
<li><em>Планирование запуска продукта</em>: при планировании сроков запуска продукта учитывай все стадии – разработку, тестирование, исправление багов, передачу в эксплуатацию. При невозможности передвинуть сроки пропорционально урезай время каждой стадии, чтобы избежать ночных переработок.</li>
<li><em>Управление ресурсами</em>: специалист высокого уровня, решающий сиюминутно возникающие задачи, приносит больше вреда, чем пользы. Любые попытки отвлечь его от решения больших и высокоприоритетных задач должны быть пресечены.</li>
<li><em>Канбан-система</em>: любые задачи/действия, которые выполняются командой, должны проходить через Канбан-доску. Если на запрос не создана карточка на доске, значит запроса не существует.</li>
<li><em>Обучение и документирование</em>: знания по решению проблем должны быть вынесены из головы ключевого сотрудника в базу знаний. Самый сильный специалист не должен тратить время на onboarding новых членов команды.</li>
<li><em>Информационная безопасность</em>: команда ИБ не должна приходить с формулировками в духе &ldquo;надо запретить&rdquo;. Важно найти выгодное решение как для команды ИБ, так и для команды эксплуатации через формализованные процедуры.</li>
</ol>
<h2 id="основные-выводы">Основные выводы</h2>
<ol>
<li><em>Результат важнее процесса</em>: &ldquo;Главное результат! Ни процесс, ни контроль процесса, ни выполненная работа – а именно результат&rdquo;. Все усилия должны быть направлены на достижение конкретных бизнес-результатов.</li>
<li><em>Баланс между стабильностью и инновациями</em>: ИТ-отдел должен обеспечивать стабильную работу критически важных систем, одновременно поддерживая инновации и изменения.</li>
<li><em>Доверие как основа</em>: &ldquo;В идеальной команде нет места недоверию – каждый член команды доверяет друг другу и своему лидеру&rdquo;. Доверие позволяет принимать более эффективные решения и быстрее реагировать на изменения.</li>
<li><em>Прозрачность как инструмент управления</em>: все изменения, процессы и задачи должны быть видимы для всех участников. Это позволяет избежать множества проблем и упрощает управление.</li>
<li><em>Системный подход к управлению</em>: &ldquo;Системное мышление говорит тебе о том, что необходимо видеть весь рабочий процесс компании как единую систему и понимать влияние каждого участка на производительность всей системы&rdquo;.</li>
</ol>
<h2 id="заключение">Заключение</h2>
<p>Книга &ldquo;Проект Феникс&rdquo; – это не просто красивая история о спасении ИТ-отдела, но и глубокое руководство по построению эффективной системы управления технологическими процессами. Она учит, что успех достигается не через отдельные действия или технологии, а через системное мышление, правильное распределение приоритетов и создание культуры непрерывного улучшения.</p>
<p>Ценность книги составляет то, что она не ограничивается теорией, а предоставляет практические инструменты и подходы, которые можно немедленно внедрить в любой организации. От системы управления изменениями до построения эффективного взаимодействия между командами – каждая глава книги дает четкие рекомендации, проверенные на практике.</p>
<p>Ну и да, пусть самой важной идеей будет то, что &ldquo;<em>DevOps – это про коммуникацию</em>&rdquo;, потому что без нормальной коммуникации &ldquo;словами через рот&rdquo; ничего не удастся построить.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></content:encoded>
    </item><item>
      <title>Хочу программировать на Golang</title>
      <link>https://jtprog.ru/posts/want-coding-golang/</link>
      <pubDate>Sun, 09 Feb 2025 15:56:15 +0300</pubDate>
      <dc:creator>jtprogru</dc:creator>
      <guid isPermaLink="true">https://jtprog.ru/posts/want-coding-golang/</guid>
      <category>Golang</category>
      <category>Coding</category>
      <category domain="category">Work</category>
      <enclosure url="https://jtprog.ru/work.png" type="image/jpeg" length="0" />
      <media:thumbnail url="https://jtprog.ru/work.png" /><description><![CDATA[<div><p>Привет, <code>%username%</code>! В том или ином виде часто сталкиваюсь с таким вопросом:</p>
<blockquote><p>Вот я слышал, что вам в DevOps/SRE надо программировать! Я вот хочу, но не вижу у себя на работе задач, где можно программировать. А если и вижу, то мне не дают их.</p>
</blockquote><p>Причем это не только для <strong>Golang</strong>, но и для <strong>Python</strong> тоже релевантно.</p>
<p>Короче, у тебя есть два <del>стула</del> варианта – &ldquo;<em>сменить профиль деятельности на разработчика</em>&rdquo; или &ldquo;<em>начать автоматизировать свою работу по максимуму</em>&rdquo;. Первый вариант я рассматривать не хочу, потому что он максимально очевидный и простой – ты потеряешь в доходе, будешь всему учиться с абсолютного нуля, будешь много страдать и до &ldquo;интересных&rdquo; задач доберешься крайне не скоро (что бы какие-либо курсы не обещали). Поэтому пройдемся кратко по второму пути.</p>
<p>Что можно автоматизировать? Да абсолютно все! Вот прям буквально все – надо разложить файлики, поменять данные в БД, нарисовать файл лицензии или ридми для репозитория – все это можно автоматизировать. Начнем с того, что ты наверняка читал или слышал про книгу &ldquo;<strong>Проект Феникс</strong>&rdquo;. Если ее еще разик перечитать, то можно внезапно узнать о том, что автоматизации подлежат следующие два важных пункта (их чуть больше, но именно эти нас интересуют сейчас):</p>
<ul>
<li>Рутина – одинаковые, часто повторяющиеся задачи, которых достаточно много;</li>
<li>Очень редкие/сложные – задачи, которые выполняются достаточно редко, чтобы успеть забыть все то, что необходимо сделать, либо имеют большое количество неочевидных нюансов, в рамках которых можно случайно аннигилировать вселенную.</li>
</ul>
<h3 id="рутина">Рутина</h3>
<p>Тут кажется все максимально очевидно и понятно. Просто смотришь на те задачи, которые чаще всего выполняешь и придумываешь для них автоматизацию. Причем автоматизировать можно на чем угодно и что угодно (да, еще раз повторяю). Создать пользователь в БД – можно пойти десятком разных способов, но тебе никто не запрещает попытаться сделать это через собственную утилиту, которую ты напишешь на любом ЯП. А если это еще и не что-то супер-секретное или узко специализированное под какую-то хрень в рамках компании, то можно еще и в опенсорс выложить! А если ты выложил в опенсорс, то тут и качество кода надо бы подтянуть, и автоматизации разные, и еще мешок всяких штук.</p>
<p>Так же крутинам можно отнести какие-то примитивные штуки в духе &ldquo;надо сгенерировать временный пароль&rdquo;. У меня есть заметка &ldquo;<a href="https://jtprog.ru/posts/cli-gen-pass/">Генерация паролей в CLI</a>
&rdquo;, в которой я приводил мешочек различных способов для того, чтобы сгенерировать пароль в терминале. Некоторыми из вариантов я пользовался достаточно долго до тех пор, пока не решил сойти с ума. Сумасшествие выглядит просто – я написал свою собственную утилиту <a href="https://github.com/jtprogru/gch/" rel="noopener noreferrer" target="_blank">gch</a>
, которая закрывает эту задачу и удобна конкретно мне. Также, мне необходимо бывает использовать определенную лицензию, файл с которой просто так не раздобыть, а бегать по гитхабу крайне лень. Что я сделал? Правильно! Я добавил в свою утилиту <a href="https://github.com/jtprogru/gch/" rel="noopener noreferrer" target="_blank">gch</a>
 нужную мне команду, которая решает эту мою личную проблему.</p>
<p>Думаю теперь вектор понятен – просто бери и делай, а не жди от кого-то каких-то задач правильно оформленных.</p>
<h3 id="редкиесложные">Редкие/сложные</h3>
<p>Тут у нас начинается самое интересное – кишочки! К редким и сложным задачам может быть отнесено все, что угодно: от пары SQL-запросов в БД, до обновления Kubernetes-кластера на железных серверах. Если кубы на железе я не особо люблю (я все таки в облаках живу), то вот истории, когда инженеру моей команды надо выполнить несколько запросов в PostgreSQL, чтобы закрыть очередную редкую задачу – отличный свежий кандидат на автоматизацию.</p>
<p>Итак, пример: задача бывает раз 1-2 недели, в рамках которой надо сделать:</p>
<ul>
<li>Мешочек подготовительной работы;</li>
<li>Выполнить <code>SELECT</code> в БД одного сервиса и получить оттуда список строк;</li>
<li>Выполнить <code>UPDATE</code> в БД другого сервиса и поменять поле с 0 на 1 для всех строк из первого сервиса;</li>
</ul>
<p>То, что это выглядит как костыль – это нормально! Решение временное, но к сожалению не на пару дней, поэтому пришлось придумывать решение. Берешь тот ЯП, который тебе интересен (в моем случае это <em>Golang</em>, но можно было бы взять и <em>Rust</em> ради эксперимента). Рисуешь себе задачу в трекере и сразу берешь ее исполнять.</p>
<p>По итогу получаешь вполне себе работоспособное решение, которое:</p>
<ul>
<li>Выполняет конкретную задачу;</li>
<li>Минимизирует человеческий фактор;</li>
<li>Поддерживает режим dry run по умолчанию;</li>
<li>Сводит 15 минут работы инженера к 1 минуте (ну надо ж на бастион еще подключиться по SSH);</li>
</ul>
<p>А помимо того, что ты встретишь кучу проблем и научишься их решать, пока будешь автоматизировать задачу, ты еще получишь респект от команды (но это не точно).</p>
<h3 id="итоги">Итоги</h3>
<p>Никаких итогов тут не будет. Просто бери и делай свою собственную сраную жизнь проще и легче прямо сейчас!</p>
<p>А если по ходу автоматизации захочется копнуть глубже, в сторону структур данных и алгоритмов под эксплуатацию – глянь мой проект <a href="https://jtprogru.github.io/dsa-for-ops/" rel="noopener noreferrer" target="_blank">dsa-for-ops</a>
.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></description>
      <content:encoded><![CDATA[<style>/* Inline-CSS, который тема вкладывает в <description> каждого item'а
   RSS-фида (layouts/index.rss.xml). RSS-ридеры (Feedly, Inoreader,
   NetNewsWire) уважают <style> внутри description с переменной
   степенью энтузиазма — это базовый fallback, достаточный для читаемой
   типографики, не более.

   Цвета продублированы из 00-vars.css (light-палитра) — поправь
   синхронно при изменении --bg / --text / --accent / --border. */

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  line-height: 1.6;
  color: #1c1c1f;
  max-width: 720px;
  margin: 0 auto;
  padding: 1em;
}
h1, h2, h3 { line-height: 1.25; margin-top: 1.4em; }
a { color: #c2410c; }
pre {
  background: #1e1e24;
  color: #e8e6df;
  padding: 1em;
  border-radius: 6px;
  overflow-x: auto;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.9em;
}
code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  background: #f3f1ed;
  padding: 0.1em 0.4em;
  border-radius: 4px;
}
pre code { background: transparent; padding: 0; }
blockquote {
  border-left: 3px solid #c2410c;
  padding-left: 1em;
  color: #5b5b62;
  font-style: italic;
  margin-left: 0;
}
img { max-width: 100%; height: auto; border-radius: 6px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #e5e3dc; padding: 6px 10px; text-align: left; }
</style><div><p>Привет, <code>%username%</code>! В том или ином виде часто сталкиваюсь с таким вопросом:</p>
<blockquote><p>Вот я слышал, что вам в DevOps/SRE надо программировать! Я вот хочу, но не вижу у себя на работе задач, где можно программировать. А если и вижу, то мне не дают их.</p>
</blockquote><p>Причем это не только для <strong>Golang</strong>, но и для <strong>Python</strong> тоже релевантно.</p>
<p>Короче, у тебя есть два <del>стула</del> варианта – &ldquo;<em>сменить профиль деятельности на разработчика</em>&rdquo; или &ldquo;<em>начать автоматизировать свою работу по максимуму</em>&rdquo;. Первый вариант я рассматривать не хочу, потому что он максимально очевидный и простой – ты потеряешь в доходе, будешь всему учиться с абсолютного нуля, будешь много страдать и до &ldquo;интересных&rdquo; задач доберешься крайне не скоро (что бы какие-либо курсы не обещали). Поэтому пройдемся кратко по второму пути.</p>
<p>Что можно автоматизировать? Да абсолютно все! Вот прям буквально все – надо разложить файлики, поменять данные в БД, нарисовать файл лицензии или ридми для репозитория – все это можно автоматизировать. Начнем с того, что ты наверняка читал или слышал про книгу &ldquo;<strong>Проект Феникс</strong>&rdquo;. Если ее еще разик перечитать, то можно внезапно узнать о том, что автоматизации подлежат следующие два важных пункта (их чуть больше, но именно эти нас интересуют сейчас):</p>
<ul>
<li>Рутина – одинаковые, часто повторяющиеся задачи, которых достаточно много;</li>
<li>Очень редкие/сложные – задачи, которые выполняются достаточно редко, чтобы успеть забыть все то, что необходимо сделать, либо имеют большое количество неочевидных нюансов, в рамках которых можно случайно аннигилировать вселенную.</li>
</ul>
<h3 id="рутина">Рутина</h3>
<p>Тут кажется все максимально очевидно и понятно. Просто смотришь на те задачи, которые чаще всего выполняешь и придумываешь для них автоматизацию. Причем автоматизировать можно на чем угодно и что угодно (да, еще раз повторяю). Создать пользователь в БД – можно пойти десятком разных способов, но тебе никто не запрещает попытаться сделать это через собственную утилиту, которую ты напишешь на любом ЯП. А если это еще и не что-то супер-секретное или узко специализированное под какую-то хрень в рамках компании, то можно еще и в опенсорс выложить! А если ты выложил в опенсорс, то тут и качество кода надо бы подтянуть, и автоматизации разные, и еще мешок всяких штук.</p>
<p>Так же крутинам можно отнести какие-то примитивные штуки в духе &ldquo;надо сгенерировать временный пароль&rdquo;. У меня есть заметка &ldquo;<a href="https://jtprog.ru/posts/cli-gen-pass/">Генерация паролей в CLI</a>
&rdquo;, в которой я приводил мешочек различных способов для того, чтобы сгенерировать пароль в терминале. Некоторыми из вариантов я пользовался достаточно долго до тех пор, пока не решил сойти с ума. Сумасшествие выглядит просто – я написал свою собственную утилиту <a href="https://github.com/jtprogru/gch/" rel="noopener noreferrer" target="_blank">gch</a>
, которая закрывает эту задачу и удобна конкретно мне. Также, мне необходимо бывает использовать определенную лицензию, файл с которой просто так не раздобыть, а бегать по гитхабу крайне лень. Что я сделал? Правильно! Я добавил в свою утилиту <a href="https://github.com/jtprogru/gch/" rel="noopener noreferrer" target="_blank">gch</a>
 нужную мне команду, которая решает эту мою личную проблему.</p>
<p>Думаю теперь вектор понятен – просто бери и делай, а не жди от кого-то каких-то задач правильно оформленных.</p>
<h3 id="редкиесложные">Редкие/сложные</h3>
<p>Тут у нас начинается самое интересное – кишочки! К редким и сложным задачам может быть отнесено все, что угодно: от пары SQL-запросов в БД, до обновления Kubernetes-кластера на железных серверах. Если кубы на железе я не особо люблю (я все таки в облаках живу), то вот истории, когда инженеру моей команды надо выполнить несколько запросов в PostgreSQL, чтобы закрыть очередную редкую задачу – отличный свежий кандидат на автоматизацию.</p>
<p>Итак, пример: задача бывает раз 1-2 недели, в рамках которой надо сделать:</p>
<ul>
<li>Мешочек подготовительной работы;</li>
<li>Выполнить <code>SELECT</code> в БД одного сервиса и получить оттуда список строк;</li>
<li>Выполнить <code>UPDATE</code> в БД другого сервиса и поменять поле с 0 на 1 для всех строк из первого сервиса;</li>
</ul>
<p>То, что это выглядит как костыль – это нормально! Решение временное, но к сожалению не на пару дней, поэтому пришлось придумывать решение. Берешь тот ЯП, который тебе интересен (в моем случае это <em>Golang</em>, но можно было бы взять и <em>Rust</em> ради эксперимента). Рисуешь себе задачу в трекере и сразу берешь ее исполнять.</p>
<p>По итогу получаешь вполне себе работоспособное решение, которое:</p>
<ul>
<li>Выполняет конкретную задачу;</li>
<li>Минимизирует человеческий фактор;</li>
<li>Поддерживает режим dry run по умолчанию;</li>
<li>Сводит 15 минут работы инженера к 1 минуте (ну надо ж на бастион еще подключиться по SSH);</li>
</ul>
<p>А помимо того, что ты встретишь кучу проблем и научишься их решать, пока будешь автоматизировать задачу, ты еще получишь респект от команды (но это не точно).</p>
<h3 id="итоги">Итоги</h3>
<p>Никаких итогов тут не будет. Просто бери и делай свою собственную сраную жизнь проще и легче прямо сейчас!</p>
<p>А если по ходу автоматизации захочется копнуть глубже, в сторону структур данных и алгоритмов под эксплуатацию – глянь мой проект <a href="https://jtprogru.github.io/dsa-for-ops/" rel="noopener noreferrer" target="_blank">dsa-for-ops</a>
.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></content:encoded>
    </item><item>
      <title>Yandex Scale 2024</title>
      <link>https://jtprog.ru/posts/yandex-scale-2024/</link>
      <pubDate>Sat, 19 Oct 2024 10:17:06 +0300</pubDate>
      <dc:creator>jtprogru</dc:creator>
      <guid isPermaLink="true">https://jtprog.ru/posts/yandex-scale-2024/</guid>
      <category>Yandex.Cloud</category>
      <category>Yandex Scale</category>
      <category>Meetup</category>
      <category>BareMetal</category>
      <category>Chaos-Engineering</category>
      <category>S3</category>
      <category domain="category">Notes</category>
      <enclosure url="https://jtprog.ru/meetup.png" type="image/jpeg" length="0" />
      <media:thumbnail url="https://jtprog.ru/meetup.png" /><description><![CDATA[<div><p>Привет, <code>%username%</code>! Я побывал на конференции <a href="https://scale.yandex.cloud/" rel="noopener noreferrer" target="_blank">Yandex.Scale</a>
, которая прошла <em>2024-09-25</em>. Посетил несколько докладов, послушал про запуск нового продукта, а так же довольно интересно и полезно провел время. Сейчас попробую рассказать о том, как это было.</p>
<h3 id="общее-впечатление">Общее впечатление</h3>
<p>Общее впечатление однозначно положительное. Однако стоит заметить некоторые особенности:</p>
<ul>
<li>Было душновато – я это списываю на особенности самой площадки, где это проходило (в этом случае был <em>МХАТ</em>);</li>
<li>Хромало питание – причем к качеству питания никаких претензий, а вот к организации прям есть, потому что неоднократно оказывался в ситуации, когда стоя в очереди, как и все, тебе ничего не достается;</li>
<li>Очереди – в самом начале мероприятия были длинные очереди, однако к моменту когда я прибыл на площадку все рассосалось, но фотки были прям страшные (шпион с места действия передавал);</li>
<li>(Не)удобство навигации – к самой локации было довольно просто добраться (мне), однако непосредственно внутри – было крайне сложно сориентироваться, а площадку на 4 этаже я вообще посетил один раз (просто из любопытства), т.к. ползать туда по лестнице (мне) крайне лень.</li>
</ul>
<h3 id="доклады">Доклады</h3>
<p>Докладов было достаточно много, а главное некоторые из них были любопытными именно для меня (даже не спрашивай почему). Я осознанно посетил три доклада и одну презентацию, поэтому начну с последнего.</p>
<h4 id="презентация-yandex-baremetal">Презентация Yandex BareMetal</h4>
<p>Ребята презентовали новый продукт, который позволит арендовать &ldquo;железные сервера&rdquo;. Немного тезисов из данной презентации:</p>
<ul>
<li>Cloud Compute это классическая виртуализация, которая имеет ряд преимуществ вроде надежности, отказоустойчивости, эластичного масштабирования, быстрого и кастомизируемого выбора ресурсов;</li>
<li>Yandex BareMetal позволяет арендовать выделенные физические сервера со всем вытекающими плюсами и минусами, так что если тебе крайне необходимы &ldquo;железные сервера&rdquo;, то можно воспользоваться. Предоставляется полноценная L2-связность;</li>
<li>Новый сервис будет являться отличным выбором для приложений, которые не готовы к облакам, либо имеют достаточно высокие требования к производительности/железу;</li>
<li>Плюсы, по сравнению с использованием своего железа достаточно очевидны: большие капексные расходы, сроки и трудности поставки, сложности масштабирования, сложности в размещении в ЦОД/Co-Location, потребность в дополнительной экспертизе;</li>
<li>На этапе запуска сервис Yandex BareMetal будет предоставлять следующие условия: готовые типовые конфигурации, физическая сеть на 1 Гб/с или 10 Гб/с, приватные сети L2- и L3-связности, заказ N-серверов с поддержкой Terraform, интеграция в ресурсную модель Yandex IAM, ну и iKVM консоль для управления сервером;</li>
<li>Разделение зон ответственности выглядит так: Yandex.Cloud отвечает за весь физический мир, а все что устанавливается на сервере это полностью ответственность клиента;</li>
<li>Сервера заказанные через Yandex BareMetal будут доступны для подключения в Yandex Managed Kubernetes в качестве worker-нод, а так же их можно будет добавить в Yandex Cloud Backup;</li>
</ul>
<h4 id="сломать-чтобы-починить-парадокс-хаос-инжиниринга-в-действии">Сломать, чтобы починить: Парадокс хаос-инжиниринга в действии</h4>
<p>Это доклад от ребят из компании Mindbox про их опыт построения такой интересной темы, как Chaos Engineering. Они выбирали инструмент, так же набили разные шишки, вот краткие тезисы из доклада:</p>
<ul>
<li>Цель chaos engineering в том, чтобы выявить узкие места до того, как они проявят себя при промышленной эксплуатации на реальных пользователях;</li>
<li>Рассматривались несколько инструментов, но выбирали между двумя: <a href="https://chaos-mesh.org" rel="noopener noreferrer" target="_blank">Chaos Mesh</a>
 и <a href="https://litmuschaos.io" rel="noopener noreferrer" target="_blank">Litmus</a>
. Последний умеет смотреть в Prometheus и Kubernetes API помимо классического HTTP, а так же имеет полноценный GitOps. Однако Chaos Mesh умеет работать с виртуальными машинами, а так же визуальное отображение пайплайнов экспериментов;</li>
<li>Описания экспериментов для Chaos Mesh хранятся рядом с кодом сервисов, которые подвергаются этим экспериментам;</li>
<li>Эксперименты запускаются в неконкурентном режиме – пока эксперимент не завершится, он не будет запущен повторно;</li>
<li>Эксперименты пишутся с учетом проверки всех возможных точек отказа и одной из точек отказа может быть misconfiguration, которая так же проверяется;</li>
<li>Для каждого эксперимента должны быть готовы run books по восстановлению, т.к. всегда может что-то пойти не так;</li>
<li>Эксперимент пишется максимально близким к реальности – не допустимы кейсы вида &ldquo;прилетели марсиане&rdquo; или &ldquo;прибежал Годзилла&rdquo;;</li>
<li>Всегда есть шанс поломать не только свои сервисы, но и саму хаус-платформу, поэтому ран-буки по ее восстановлению необходимо держать при себе;</li>
<li>Кроме экспериментов на отказ стоит описывать эксперименты на деградацию, что позволит оценивать систему в целом и ее отдельные участки в частности. Так же важно выполнять эксперименты chaos engineering&rsquo;а часто, что позволит быть ближе к реальности как результатам, так и самим тестам;</li>
<li>Оптимальное временное окно для запуска тестов это середина нагрузки, т.к. в пике может быть страшно, а в минимуме будет довольно скучно. И да, эксперименты проводятся на контуре промышленной эксплуатации, где всегда есть живые пользователи;</li>
<li>Полезно делать аннотации на дашбордах Grafana с началом/завершением экспериментов. Это позволит быстрее реагировать в случае, если что-то пошло не так, а так же более точно оценивать производительность системы и сервисов;</li>
<li>Алерты от системы мониторинга не стоит отключать до того, как убедились, что эксперименты работоспособны и корректны. Желательно 3-5 раз запустить с включенными алертами, а далее уже по ситуации;</li>
<li>Chaos Engineering позволяет повысить надежность и отказоустойчивость системы, приблизить к SLO, улучшить взаимодействие и навыки команды, а так же сократить MTTR.</li>
</ul>
<h4 id="как-подключаться-к-s3-из-vpc-без-доступа-к-интернет">Как подключаться к S3 из VPC без доступа к интернет</h4>
<p>Сам по себе S3 реализован изначально AWS для решения своих проблем и удовлетворения потребностей. Но ребята из Yandex.Cloud реализовали полностью совместимый сервис. Из интересного, что появилось:</p>
<ul>
<li>Функционал Security Token Service (STS) полностью совместим с AWS STS API, поэтому можно смело использовать;</li>
<li>Изначально доступ к S3-бакету был равносилен походу в публичную сеть Интернет, однако сейчас можно организовать доступ к S3-бакету не выходя в публичную сеть Интернет;</li>
<li>Для тех, кто использует GeeseFS, может быть полезным тот факт, что реализована поддержка метода PATCH;</li>
</ul>
<h4 id="стратегия-продукта-безопасности-в-yandex-cloud">Стратегия продукта безопасности в Yandex Cloud</h4>
<p>Не возможно обойти стороной тему безопасности при разговоре про публичные облака. Немного о том, поэтому Yandex Cloud подсветили следующее:</p>
<ul>
<li>Запуск в облаке снижает и Time To Market и трудозатраты, что однозначно является хорошим плюсом для бизнеса;</li>
<li>Решение внутренних задач по ИБ крайне проблематично отдавать на аутсорс, поэтому компания должна взращивать свои компетенции в сфере ИБ;</li>
<li>Помимо соблюдения кучи требований со стороны Yandex Cloud по теме ИБ от различных регуляторов, появилась сертификация по ИБ (экзамен), которая позволяет проверить своих специалистов на соответствие;</li>
<li>Активно практикуется &ldquo;догфудинг&rdquo; – все продукты/сервисы/стандарты активно используются самой компанией;</li>
</ul>
<h3 id="итоги">Итоги</h3>
<p>Очень много времени провел беседуя с архитектором Yandex Cloud – выпытывал устройство Yandex Cloud, т.к. активно живу и работаю в нем. Это самое полезное, что я вынес с данного мероприятия! И именно ради такого я рекомендую всем посещать конференции – ради возможности задать свои вопросы напрямую людям, продуктами которых ты пользуешься.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></description>
      <content:encoded><![CDATA[<style>/* Inline-CSS, который тема вкладывает в <description> каждого item'а
   RSS-фида (layouts/index.rss.xml). RSS-ридеры (Feedly, Inoreader,
   NetNewsWire) уважают <style> внутри description с переменной
   степенью энтузиазма — это базовый fallback, достаточный для читаемой
   типографики, не более.

   Цвета продублированы из 00-vars.css (light-палитра) — поправь
   синхронно при изменении --bg / --text / --accent / --border. */

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  line-height: 1.6;
  color: #1c1c1f;
  max-width: 720px;
  margin: 0 auto;
  padding: 1em;
}
h1, h2, h3 { line-height: 1.25; margin-top: 1.4em; }
a { color: #c2410c; }
pre {
  background: #1e1e24;
  color: #e8e6df;
  padding: 1em;
  border-radius: 6px;
  overflow-x: auto;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.9em;
}
code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  background: #f3f1ed;
  padding: 0.1em 0.4em;
  border-radius: 4px;
}
pre code { background: transparent; padding: 0; }
blockquote {
  border-left: 3px solid #c2410c;
  padding-left: 1em;
  color: #5b5b62;
  font-style: italic;
  margin-left: 0;
}
img { max-width: 100%; height: auto; border-radius: 6px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #e5e3dc; padding: 6px 10px; text-align: left; }
</style><div><p>Привет, <code>%username%</code>! Я побывал на конференции <a href="https://scale.yandex.cloud/" rel="noopener noreferrer" target="_blank">Yandex.Scale</a>
, которая прошла <em>2024-09-25</em>. Посетил несколько докладов, послушал про запуск нового продукта, а так же довольно интересно и полезно провел время. Сейчас попробую рассказать о том, как это было.</p>
<h3 id="общее-впечатление">Общее впечатление</h3>
<p>Общее впечатление однозначно положительное. Однако стоит заметить некоторые особенности:</p>
<ul>
<li>Было душновато – я это списываю на особенности самой площадки, где это проходило (в этом случае был <em>МХАТ</em>);</li>
<li>Хромало питание – причем к качеству питания никаких претензий, а вот к организации прям есть, потому что неоднократно оказывался в ситуации, когда стоя в очереди, как и все, тебе ничего не достается;</li>
<li>Очереди – в самом начале мероприятия были длинные очереди, однако к моменту когда я прибыл на площадку все рассосалось, но фотки были прям страшные (шпион с места действия передавал);</li>
<li>(Не)удобство навигации – к самой локации было довольно просто добраться (мне), однако непосредственно внутри – было крайне сложно сориентироваться, а площадку на 4 этаже я вообще посетил один раз (просто из любопытства), т.к. ползать туда по лестнице (мне) крайне лень.</li>
</ul>
<h3 id="доклады">Доклады</h3>
<p>Докладов было достаточно много, а главное некоторые из них были любопытными именно для меня (даже не спрашивай почему). Я осознанно посетил три доклада и одну презентацию, поэтому начну с последнего.</p>
<h4 id="презентация-yandex-baremetal">Презентация Yandex BareMetal</h4>
<p>Ребята презентовали новый продукт, который позволит арендовать &ldquo;железные сервера&rdquo;. Немного тезисов из данной презентации:</p>
<ul>
<li>Cloud Compute это классическая виртуализация, которая имеет ряд преимуществ вроде надежности, отказоустойчивости, эластичного масштабирования, быстрого и кастомизируемого выбора ресурсов;</li>
<li>Yandex BareMetal позволяет арендовать выделенные физические сервера со всем вытекающими плюсами и минусами, так что если тебе крайне необходимы &ldquo;железные сервера&rdquo;, то можно воспользоваться. Предоставляется полноценная L2-связность;</li>
<li>Новый сервис будет являться отличным выбором для приложений, которые не готовы к облакам, либо имеют достаточно высокие требования к производительности/железу;</li>
<li>Плюсы, по сравнению с использованием своего железа достаточно очевидны: большие капексные расходы, сроки и трудности поставки, сложности масштабирования, сложности в размещении в ЦОД/Co-Location, потребность в дополнительной экспертизе;</li>
<li>На этапе запуска сервис Yandex BareMetal будет предоставлять следующие условия: готовые типовые конфигурации, физическая сеть на 1 Гб/с или 10 Гб/с, приватные сети L2- и L3-связности, заказ N-серверов с поддержкой Terraform, интеграция в ресурсную модель Yandex IAM, ну и iKVM консоль для управления сервером;</li>
<li>Разделение зон ответственности выглядит так: Yandex.Cloud отвечает за весь физический мир, а все что устанавливается на сервере это полностью ответственность клиента;</li>
<li>Сервера заказанные через Yandex BareMetal будут доступны для подключения в Yandex Managed Kubernetes в качестве worker-нод, а так же их можно будет добавить в Yandex Cloud Backup;</li>
</ul>
<h4 id="сломать-чтобы-починить-парадокс-хаос-инжиниринга-в-действии">Сломать, чтобы починить: Парадокс хаос-инжиниринга в действии</h4>
<p>Это доклад от ребят из компании Mindbox про их опыт построения такой интересной темы, как Chaos Engineering. Они выбирали инструмент, так же набили разные шишки, вот краткие тезисы из доклада:</p>
<ul>
<li>Цель chaos engineering в том, чтобы выявить узкие места до того, как они проявят себя при промышленной эксплуатации на реальных пользователях;</li>
<li>Рассматривались несколько инструментов, но выбирали между двумя: <a href="https://chaos-mesh.org" rel="noopener noreferrer" target="_blank">Chaos Mesh</a>
 и <a href="https://litmuschaos.io" rel="noopener noreferrer" target="_blank">Litmus</a>
. Последний умеет смотреть в Prometheus и Kubernetes API помимо классического HTTP, а так же имеет полноценный GitOps. Однако Chaos Mesh умеет работать с виртуальными машинами, а так же визуальное отображение пайплайнов экспериментов;</li>
<li>Описания экспериментов для Chaos Mesh хранятся рядом с кодом сервисов, которые подвергаются этим экспериментам;</li>
<li>Эксперименты запускаются в неконкурентном режиме – пока эксперимент не завершится, он не будет запущен повторно;</li>
<li>Эксперименты пишутся с учетом проверки всех возможных точек отказа и одной из точек отказа может быть misconfiguration, которая так же проверяется;</li>
<li>Для каждого эксперимента должны быть готовы run books по восстановлению, т.к. всегда может что-то пойти не так;</li>
<li>Эксперимент пишется максимально близким к реальности – не допустимы кейсы вида &ldquo;прилетели марсиане&rdquo; или &ldquo;прибежал Годзилла&rdquo;;</li>
<li>Всегда есть шанс поломать не только свои сервисы, но и саму хаус-платформу, поэтому ран-буки по ее восстановлению необходимо держать при себе;</li>
<li>Кроме экспериментов на отказ стоит описывать эксперименты на деградацию, что позволит оценивать систему в целом и ее отдельные участки в частности. Так же важно выполнять эксперименты chaos engineering&rsquo;а часто, что позволит быть ближе к реальности как результатам, так и самим тестам;</li>
<li>Оптимальное временное окно для запуска тестов это середина нагрузки, т.к. в пике может быть страшно, а в минимуме будет довольно скучно. И да, эксперименты проводятся на контуре промышленной эксплуатации, где всегда есть живые пользователи;</li>
<li>Полезно делать аннотации на дашбордах Grafana с началом/завершением экспериментов. Это позволит быстрее реагировать в случае, если что-то пошло не так, а так же более точно оценивать производительность системы и сервисов;</li>
<li>Алерты от системы мониторинга не стоит отключать до того, как убедились, что эксперименты работоспособны и корректны. Желательно 3-5 раз запустить с включенными алертами, а далее уже по ситуации;</li>
<li>Chaos Engineering позволяет повысить надежность и отказоустойчивость системы, приблизить к SLO, улучшить взаимодействие и навыки команды, а так же сократить MTTR.</li>
</ul>
<h4 id="как-подключаться-к-s3-из-vpc-без-доступа-к-интернет">Как подключаться к S3 из VPC без доступа к интернет</h4>
<p>Сам по себе S3 реализован изначально AWS для решения своих проблем и удовлетворения потребностей. Но ребята из Yandex.Cloud реализовали полностью совместимый сервис. Из интересного, что появилось:</p>
<ul>
<li>Функционал Security Token Service (STS) полностью совместим с AWS STS API, поэтому можно смело использовать;</li>
<li>Изначально доступ к S3-бакету был равносилен походу в публичную сеть Интернет, однако сейчас можно организовать доступ к S3-бакету не выходя в публичную сеть Интернет;</li>
<li>Для тех, кто использует GeeseFS, может быть полезным тот факт, что реализована поддержка метода PATCH;</li>
</ul>
<h4 id="стратегия-продукта-безопасности-в-yandex-cloud">Стратегия продукта безопасности в Yandex Cloud</h4>
<p>Не возможно обойти стороной тему безопасности при разговоре про публичные облака. Немного о том, поэтому Yandex Cloud подсветили следующее:</p>
<ul>
<li>Запуск в облаке снижает и Time To Market и трудозатраты, что однозначно является хорошим плюсом для бизнеса;</li>
<li>Решение внутренних задач по ИБ крайне проблематично отдавать на аутсорс, поэтому компания должна взращивать свои компетенции в сфере ИБ;</li>
<li>Помимо соблюдения кучи требований со стороны Yandex Cloud по теме ИБ от различных регуляторов, появилась сертификация по ИБ (экзамен), которая позволяет проверить своих специалистов на соответствие;</li>
<li>Активно практикуется &ldquo;догфудинг&rdquo; – все продукты/сервисы/стандарты активно используются самой компанией;</li>
</ul>
<h3 id="итоги">Итоги</h3>
<p>Очень много времени провел беседуя с архитектором Yandex Cloud – выпытывал устройство Yandex Cloud, т.к. активно живу и работаю в нем. Это самое полезное, что я вынес с данного мероприятия! И именно ради такого я рекомендую всем посещать конференции – ради возможности задать свои вопросы напрямую людям, продуктами которых ты пользуешься.</p>
<hr>
<p>Если у тебя есть вопросы, комментарии и/или замечания – заходи в <a href="https://ttttt.me/jtprogru_chat" rel="noopener noreferrer" target="_blank">чат</a>
, а так же подписывайся на <a href="https://ttttt.me/jtprogru_channel" rel="noopener noreferrer" target="_blank">канал</a>
.</p>
<p>О способах отблагодарить автора можно почитать на странице &ldquo;<a href="https://jtprog.ru/donations/">Донаты</a>
&rdquo;.</p>
</div>]]></content:encoded>
    </item>
  </channel>
</rss>
