revise August 2024 feature flag articles
Build and deploy / deploy (push) Successful in 18s

This commit is contained in:
2026-07-31 16:27:37 +03:00
parent c8bb90f435
commit 04dbb60f16
7 changed files with 1005 additions and 1 deletions
@@ -0,0 +1,66 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 1100" role="img" aria-labelledby="title desc">
<title id="title">Синтетическая временная схема rollout, rollback и cleanup feature flag</title>
<desc id="desc">Схема показывает синтетические этапы rollout ноль, пять, двадцать пять и сто процентов. При stop condition выполняется rollback к fallback. После стабильного финального варианта отдельный cleanup gate требует удалить ветки и конфигурацию.</desc>
<defs>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="5" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L10,5 L0,10 Z" fill="#74d5c0"/>
</marker>
<marker id="arrow-warn" markerWidth="10" markerHeight="10" refX="8" refY="5" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L10,5 L0,10 Z" fill="#e9b45f"/>
</marker>
</defs>
<rect width="720" height="1100" rx="28" fill="#0f1d2e"/>
<rect x="28" y="26" width="664" height="112" rx="20" fill="#16334b" stroke="#3f6680"/>
<text x="58" y="72" fill="#f5fbff" font-family="Arial, sans-serif" font-size="28" font-weight="700">Выключить — не значит удалить риск</text>
<text x="58" y="105" fill="#b8cedd" font-family="Arial, sans-serif" font-size="18">0 → 5 → 25 → 100% — fixed synthetic teaching model.</text>
<text x="70" y="183" fill="#89abc1" font-family="Arial, sans-serif" font-size="17" font-weight="700">ROLLOUT: один cohort key и заранее записанная stop condition</text>
<path d="M144 252 L576 252" fill="none" stroke="#74d5c0" stroke-width="4" marker-end="url(#arrow)"/>
<circle cx="144" cy="252" r="18" fill="#1d4a44" stroke="#74d5c0" stroke-width="3"/>
<circle cx="288" cy="252" r="18" fill="#1d4a44" stroke="#74d5c0" stroke-width="3"/>
<circle cx="432" cy="252" r="18" fill="#1d4a44" stroke="#74d5c0" stroke-width="3"/>
<circle cx="576" cy="252" r="18" fill="#1d4a44" stroke="#74d5c0" stroke-width="3"/>
<text x="116" y="215" fill="#e7fff7" font-family="Arial, sans-serif" font-size="23" font-weight="700">0%</text>
<text x="258" y="215" fill="#e7fff7" font-family="Arial, sans-serif" font-size="23" font-weight="700">5%</text>
<text x="394" y="215" fill="#e7fff7" font-family="Arial, sans-serif" font-size="23" font-weight="700">25%</text>
<text x="534" y="215" fill="#e7fff7" font-family="Arial, sans-serif" font-size="23" font-weight="700">100%</text>
<text x="82" y="297" fill="#b9eadc" font-family="Arial, sans-serif" font-size="16">baseline</text>
<text x="226" y="297" fill="#b9eadc" font-family="Arial, sans-serif" font-size="16">observe</text>
<text x="364" y="297" fill="#b9eadc" font-family="Arial, sans-serif" font-size="16">compare</text>
<text x="530" y="297" fill="#b9eadc" font-family="Arial, sans-serif" font-size="16">freeze?</text>
<rect x="72" y="338" width="576" height="112" rx="18" fill="#16334b" stroke="#3f6680" stroke-width="2"/>
<text x="102" y="378" fill="#f5fbff" font-family="Arial, sans-serif" font-size="21" font-weight="700">На каждом этапе: проверить заранее выбранные сигналы</text>
<text x="102" y="407" fill="#c2d9e8" font-family="Arial, sans-serif" font-size="17">outcome · error ratio · fallback path · effective config version</text>
<text x="102" y="434" fill="#86acc2" font-family="Arial, sans-serif" font-size="15">Схема не задаёт безопасный процент, окно наблюдения или production SLO.</text>
<path d="M360 450 L360 502" fill="none" stroke="#e9b45f" stroke-width="3" marker-end="url(#arrow-warn)"/>
<rect x="152" y="516" width="416" height="86" rx="18" fill="#513f25" stroke="#e9b45f" stroke-width="2"/>
<text x="182" y="551" fill="#fff1cf" font-family="Arial, sans-serif" font-size="22" font-weight="700">Stop condition сработала?</text>
<text x="182" y="579" fill="#f2d5a1" font-family="Arial, sans-serif" font-size="16">Решение фиксируется до включения следующей стадии.</text>
<path d="M152 559 L90 559 L90 688" fill="none" stroke="#e08091" stroke-width="3" marker-end="url(#arrow-warn)"/>
<text x="99" y="540" fill="#f4c979" font-family="Arial, sans-serif" font-size="17" font-weight="700">да</text>
<rect x="40" y="704" width="240" height="156" rx="18" fill="#4b2932" stroke="#e08091" stroke-width="2"/>
<text x="66" y="745" fill="#ffe9ed" font-family="Arial, sans-serif" font-size="21" font-weight="700">Rollback / fallback</text>
<text x="66" y="777" fill="#f7c6cf" font-family="Arial, sans-serif" font-size="16">Вернуть аудиторию к 0%.</text>
<text x="66" y="802" fill="#f7c6cf" font-family="Arial, sans-serif" font-size="16">Сохранить старый путь.</text>
<text x="66" y="827" fill="#f7c6cf" font-family="Arial, sans-serif" font-size="16">Расследовать отдельно.</text>
<text x="66" y="850" fill="#f1aab7" font-family="Arial, sans-serif" font-size="14">Disable — mitigation, не cleanup.</text>
<path d="M568 559 L630 559 L630 688" fill="none" stroke="#74d5c0" stroke-width="3" marker-end="url(#arrow)"/>
<text x="570" y="540" fill="#9ee9d8" font-family="Arial, sans-serif" font-size="17" font-weight="700">нет</text>
<rect x="440" y="704" width="240" height="156" rx="18" fill="#1d4a44" stroke="#74d5c0" stroke-width="2"/>
<text x="466" y="745" fill="#e7fff7" font-family="Arial, sans-serif" font-size="21" font-weight="700">Cleanup gate</text>
<text x="466" y="777" fill="#b9eadc" font-family="Arial, sans-serif" font-size="16">final variant frozen</text>
<text x="466" y="802" fill="#b9eadc" font-family="Arial, sans-serif" font-size="16">branches removed</text>
<text x="466" y="827" fill="#b9eadc" font-family="Arial, sans-serif" font-size="16">config removed</text>
<text x="466" y="850" fill="#9ee9d8" font-family="Arial, sans-serif" font-size="14">behaviour test остаётся.</text>
<path d="M560 860 L560 916" fill="none" stroke="#74d5c0" stroke-width="3" marker-end="url(#arrow)"/>
<rect x="72" y="930" width="576" height="136" rx="18" fill="#24415c" stroke="#a6d6ff" stroke-width="2"/>
<text x="102" y="970" fill="#eff9ff" font-family="Arial, sans-serif" font-size="22" font-weight="700">Только после gate: удалить runtime dependency</text>
<text x="102" y="998" fill="#c4e7ff" font-family="Arial, sans-serif" font-size="17">кодовые ветки · configuration references</text>
<text x="102" y="1023" fill="#c4e7ff" font-family="Arial, sans-serif" font-size="17">flag-specific tests</text>
<text x="102" y="1049" fill="#91bbd7" font-family="Arial, sans-serif" font-size="15">Результат: одна проверяемая ветка поведения.</text>
</svg>

After

Width:  |  Height:  |  Size: 6.8 KiB

@@ -0,0 +1,52 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 1060" role="img" aria-labelledby="title desc">
<title id="title">Дерево решения для release feature flag</title>
<desc id="desc">Схема показывает, что до создания release-флага нужно заполнить карточку контракта. Без карточки работа уходит на review. После карточки отдельно выбираются server-side protected decision, client-side presentation и cleanup path.</desc>
<defs>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="5" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L10,5 L0,10 Z" fill="#74d5c0"/>
</marker>
</defs>
<rect width="720" height="1060" rx="28" fill="#0f1d2e"/>
<rect x="28" y="26" width="664" height="112" rx="20" fill="#16334b" stroke="#3f6680"/>
<text x="58" y="72" fill="#f5fbff" font-family="Arial, sans-serif" font-size="28" font-weight="700">Фича-флаг — контракт выпуска</text>
<text x="58" y="105" fill="#b8cedd" font-family="Arial, sans-serif" font-size="18">Сначала граница решения и removal path, потом boolean.</text>
<rect x="72" y="174" width="576" height="88" rx="18" fill="#4b2932" stroke="#e08091" stroke-width="2"/>
<text x="102" y="211" fill="#ffe9ed" font-family="Arial, sans-serif" font-size="22" font-weight="700">Симптом</text>
<text x="102" y="239" fill="#f7c6cf" font-family="Arial, sans-serif" font-size="18">Временный switch создан без срока и владельца.</text>
<path d="M360 262 L360 304" fill="none" stroke="#74d5c0" stroke-width="3" marker-end="url(#arrow)"/>
<rect x="152" y="316" width="416" height="94" rx="18" fill="#174760" stroke="#74d5c0" stroke-width="2"/>
<text x="182" y="354" fill="#eafff9" font-family="Arial, sans-serif" font-size="23" font-weight="700">Есть карточка контракта?</text>
<text x="182" y="383" fill="#b5e6da" font-family="Arial, sans-serif" font-size="17">owner · audience · fallback · expiry · delete</text>
<path d="M152 364 L96 364 L96 468" fill="none" stroke="#e9b45f" stroke-width="3" marker-end="url(#arrow)"/>
<text x="105" y="347" fill="#f4c979" font-family="Arial, sans-serif" font-size="17" font-weight="700">нет</text>
<rect x="42" y="480" width="212" height="130" rx="18" fill="#513f25" stroke="#e9b45f" stroke-width="2"/>
<text x="66" y="520" fill="#fff1cf" font-family="Arial, sans-serif" font-size="21" font-weight="700">Review, не флаг</text>
<text x="66" y="551" fill="#f2d5a1" font-family="Arial, sans-serif" font-size="16">Назначить owner,</text>
<text x="66" y="575" fill="#f2d5a1" font-family="Arial, sans-serif" font-size="16">описать fallback и</text>
<text x="66" y="599" fill="#f2d5a1" font-family="Arial, sans-serif" font-size="16">дату removal review.</text>
<path d="M568 364 L624 364 L624 468" fill="none" stroke="#74d5c0" stroke-width="3" marker-end="url(#arrow)"/>
<text x="571" y="347" fill="#9ee9d8" font-family="Arial, sans-serif" font-size="17" font-weight="700">да</text>
<rect x="466" y="480" width="212" height="130" rx="18" fill="#1d4a44" stroke="#74d5c0" stroke-width="2"/>
<text x="490" y="520" fill="#e7fff7" font-family="Arial, sans-serif" font-size="20" font-weight="700">Граница решения</text>
<text x="490" y="551" fill="#b9eadc" font-family="Arial, sans-serif" font-size="16">protected input?</text>
<text x="490" y="575" fill="#b9eadc" font-family="Arial, sans-serif" font-size="16">server decision</text>
<text x="490" y="599" fill="#b9eadc" font-family="Arial, sans-serif" font-size="16">presentation → client</text>
<path d="M572 610 L572 662" fill="none" stroke="#74d5c0" stroke-width="3" marker-end="url(#arrow)"/>
<rect x="112" y="676" width="496" height="150" rx="18" fill="#16334b" stroke="#3f6680" stroke-width="2"/>
<text x="142" y="718" fill="#f5fbff" font-family="Arial, sans-serif" font-size="22" font-weight="700">Наблюдение — отдельная обязанность</text>
<text x="142" y="750" fill="#c2d9e8" font-family="Arial, sans-serif" font-size="17">version ответа · outcome · render error · fallback path</text>
<text x="142" y="780" fill="#c2d9e8" font-family="Arial, sans-serif" font-size="17">Не превращать provider event в доказательство exposure.</text>
<text x="142" y="808" fill="#86acc2" font-family="Arial, sans-serif" font-size="15">Сигналы выбирает команда; схема не измеряет production.</text>
<path d="M360 826 L360 878" fill="none" stroke="#74d5c0" stroke-width="3" marker-end="url(#arrow)"/>
<rect x="72" y="892" width="576" height="136" rx="18" fill="#24415c" stroke="#a6d6ff" stroke-width="2"/>
<text x="102" y="934" fill="#eff9ff" font-family="Arial, sans-serif" font-size="22" font-weight="700">Cleanup path записан до enable</text>
<text x="102" y="964" fill="#c4e7ff" font-family="Arial, sans-serif" font-size="17">freeze final variant → remove branches</text>
<text x="102" y="989" fill="#c4e7ff" font-family="Arial, sans-serif" font-size="17">remove config → keep behaviour test</text>
<text x="102" y="1014" fill="#91bbd7" font-family="Arial, sans-serif" font-size="15">Disable уменьшает риск; только cleanup удаляет зависимость.</text>
</svg>

After

Width:  |  Height:  |  Size: 5.4 KiB

@@ -0,0 +1,47 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 980" role="img" aria-labelledby="title desc">
<title id="title">Поток решения feature flag между сервером и клиентом</title>
<desc id="desc">Схема отделяет защищенный серверный контекст, evaluation, ответ с presentation value и configuration version, от клиентского rendering и candidate exposure event. Пунктирная линия подчёркивает отсутствие exactly-once гарантии.</desc>
<defs>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="5" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L10,5 L0,10 Z" fill="#74d5c0"/>
</marker>
</defs>
<rect width="720" height="980" rx="28" fill="#0f1d2e"/>
<rect x="28" y="26" width="664" height="112" rx="20" fill="#16334b" stroke="#3f6680"/>
<text x="58" y="72" fill="#f5fbff" font-family="Arial, sans-serif" font-size="28" font-weight="700">Где принимается решение?</text>
<text x="58" y="105" fill="#b8cedd" font-family="Arial, sans-serif" font-size="18">Eligibility живёт рядом с protected input; UI получает результат.</text>
<text x="80" y="181" fill="#89abc1" font-family="Arial, sans-serif" font-size="17" font-weight="700">SERVER BOUNDARY</text>
<rect x="54" y="202" width="612" height="184" rx="20" fill="#16334b" stroke="#3f6680" stroke-width="2"/>
<rect x="82" y="234" width="242" height="118" rx="16" fill="#4d2a33" stroke="#e08091" stroke-width="2"/>
<text x="106" y="271" fill="#ffe9ed" font-family="Arial, sans-serif" font-size="20" font-weight="700">Защищённый context</text>
<text x="106" y="300" fill="#f7c6cf" font-family="Arial, sans-serif" font-size="16">entitlement, risk rule,</text>
<text x="106" y="323" fill="#f7c6cf" font-family="Arial, sans-serif" font-size="16">стабильный cohort key</text>
<path d="M324 293 L384 293" fill="none" stroke="#74d5c0" stroke-width="3" marker-end="url(#arrow)"/>
<rect x="394" y="234" width="244" height="118" rx="16" fill="#1d4a44" stroke="#74d5c0" stroke-width="2"/>
<text x="418" y="271" fill="#e7fff7" font-family="Arial, sans-serif" font-size="20" font-weight="700">Evaluator</text>
<text x="418" y="300" fill="#b9eadc" font-family="Arial, sans-serif" font-size="16">flag key + context</text>
<text x="418" y="323" fill="#b9eadc" font-family="Arial, sans-serif" font-size="16">→ variant + config version</text>
<path d="M516 386 L516 442" fill="none" stroke="#74d5c0" stroke-width="3" marker-end="url(#arrow)"/>
<rect x="142" y="456" width="436" height="96" rx="18" fill="#24415c" stroke="#a6d6ff" stroke-width="2"/>
<text x="172" y="494" fill="#eff9ff" font-family="Arial, sans-serif" font-size="21" font-weight="700">Ответ клиенту</text>
<text x="172" y="524" fill="#c4e7ff" font-family="Arial, sans-serif" font-size="17">presentation value + effective config version</text>
<path d="M360 552 L360 608" fill="none" stroke="#74d5c0" stroke-width="3" marker-end="url(#arrow)"/>
<text x="80" y="641" fill="#89abc1" font-family="Arial, sans-serif" font-size="17" font-weight="700">CLIENT BOUNDARY</text>
<rect x="54" y="660" width="612" height="146" rx="20" fill="#16334b" stroke="#3f6680" stroke-width="2"/>
<rect x="82" y="692" width="242" height="82" rx="16" fill="#24415c" stroke="#a6d6ff" stroke-width="2"/>
<text x="106" y="726" fill="#eff9ff" font-family="Arial, sans-serif" font-size="20" font-weight="700">Render</text>
<text x="106" y="752" fill="#c4e7ff" font-family="Arial, sans-serif" font-size="16">видит returned value</text>
<path d="M324 733 L384 733" fill="none" stroke="#e9b45f" stroke-width="3" stroke-dasharray="9 8" marker-end="url(#arrow)"/>
<rect x="394" y="692" width="244" height="82" rx="16" fill="#513f25" stroke="#e9b45f" stroke-width="2"/>
<text x="418" y="726" fill="#fff1cf" font-family="Arial, sans-serif" font-size="19" font-weight="700">Exposure candidate</text>
<text x="418" y="752" fill="#f2d5a1" font-family="Arial, sans-serif" font-size="16">event id + version</text>
<path d="M516 806 L516 838" fill="none" stroke="#e9b45f" stroke-width="3" stroke-dasharray="9 8" marker-end="url(#arrow)"/>
<rect x="108" y="850" width="504" height="104" rx="18" fill="#4b2932" stroke="#e08091" stroke-width="2"/>
<text x="138" y="883" fill="#ffe9ed" font-family="Arial, sans-serif" font-size="20" font-weight="700">Delivery boundary: retry possible</text>
<text x="138" y="908" fill="#ffe9ed" font-family="Arial, sans-serif" font-size="20" font-weight="700">exactly-once не обещан</text>
<text x="138" y="935" fill="#f7c6cf" font-family="Arial, sans-serif" font-size="16">Приёмник делает dedupe только там, где это нужно.</text>
</svg>

After

Width:  |  Height:  |  Size: 4.8 KiB