A/B-тест с кэшем без ключа по варианту: эффект измеряете, но данные уже перемешаны

Классика: выкатываем эксперимент, метрики “плывут”, график странный, сегменты не сходятся. Начинают спорить про сезонность и статистику, а проблема проще: один и тот же кэш отдаёт разным вариантам одинаковый ответ. Вы в реальности тестируете не фичу, а хаос маршрутизации.

Почему это ломает измерение: эксперимент держится на стабильной экспозиции. Один пользователь должен последовательно видеть один вариант в рамках окна, а разные варианты не должны “делить” артефакты (HTML, JSON, прайс, список рекомендаций). Кэш как раз создан, чтобы стирать различия. Если вы не зафиксировали эти различия в ключах и TTL, он тихо сделает “усреднение”.

6 мест, где чаще всего происходит смешивание: CDN, бекенд-кэш, кэш в приложении, кэш результата фича-флага/сегментации, прогрев кэша до старта, TTL который пересекает смену варианта или этапы рампа.

Минимальный стандарт, чтобы эксперименту можно было доверять:

  1. Вариант должен участвовать в кэш-ключе везде, где кэшируется контент: CDN и бекенд. Не “где-то в заголовке”, а именно в ключе (через Vary/headers, cookie, query, отдельные пути) и одинаково для всех маршрутов.
  2. TTL и окно экспозиции должны дружить. Если вариант может меняться (перерандомизация, переобучение сегмента, рамп), то кэш с долгим TTL превращается в машинку по перетеканию между вариантами.
  3. Определение варианта нельзя кэшировать “по пользователю” без явной версии. Кэшируете результат фича-флага или сегментации? Добавьте версионирование правил, иначе после изменения раскатки старые решения живут дольше, чем эксперимент.
  4. Прогрев кэша и префетч должны быть вариант-специфичными. Иначе вы прогреваете один вариант, а второй получает “чужие” ответы с высоким hit rate с первой минуты.
  5. Проверяйте по логам, а не по ощущениям. В каждом запросе для экспериментных ручек должны быть: user id или anon id, experiment id, variant, признак cache hit/miss, cache key (хотя бы хэш), возраст объекта, источник (CDN/апп/бекенд). Если видите один и тот же cache key при разных variant или прыгающий variant при неизменной экспозиции — тест уже токсичный.

В правильной практике кэш становится частью дизайна эксперимента: вы заранее описываете, что именно кэшируется, где проходит граница между вариантами, и как это будет наблюдаться в логах. Исключение одно: если эксперимент вообще не влияет на кэшируемые ответы и маршрутизацию, тогда риск ниже, но это нужно доказать трассировкой, а не верой.