Назад к блогу

Cloudflare Workers KV Instant: плейбук по чтению игровых конфигов за 1,62 мс

Опубликовано 2 октября 2026 г.
Cloudflare Workers KV Instant: плейбук по чтению игровых конфигов за 1,62 мс Создано с помощью ИИ

Коротко о главном

Узнайте, как Cloudflare Workers KV Instant даёт чтение игровых конфигов за 1,62 мс, устраняет устаревание данных и когда использовать управляемый сервис.

Когда ваша команда live-ops публикует критическое обновление конфигурации — исправление эксплойта экономики, экстренное изменение расписания события, флаг окна технического обслуживания — игроки на противоположной стороне планеты не должны читать устаревшие данные в течение 4,38 секунды. Это время репликации записи на уровне p99 для классического Cloudflare Workers KV. Для статической маркетинговой страницы это неважно. Для живой игры, где на кону реальные деньги или честность соревнований, эта задержка распространения — проблема.

Cloudflare только что анонсировала Workers KV Instant — новый режим для Workers KV на базе их внутреннего хранилища Quicksilver v2. Тот же знакомый API get(), put(), list(), delete(). Под капотом совершенно другой движок — тот же движок, который обрабатывает поиск конфигурации для каждого запроса по всей глобальной сети Cloudflare. Результат: чтение на уровне p99 за 1,62 мс и репликация записи на уровне p99 за 256 мс в 300+ edge-локаций.

Этот плейбук описывает, что именно изменилось, как определить, что ваша игра сталкивается с режимами отказа из-за устаревших конфигов, пошаговую реализацию для размещённой на edge игровой конфигурации, жёсткие ограничения, из-за которых KV Instant не подходит для некоторых нагрузок, и когда управляемый сервис удалённой конфигурации имеет больше смысла, чем создание собственного решения.


Что именно изменилось: KV Instant против KV Classic

Workers KV Classic — это хранилище с конечной согласованностью (eventually consistent). Вы записываете ключ, и Cloudflare асинхронно реплицирует его в свои edge-локации. В этом окне читатели могут получать устаревшие значения. Модель согласованности — «последняя запись побеждает с инвалидацией кэша на основе TTL». Это работает для статических ресурсов и пользовательских предпочтений — данных, которые записываются нечасто и могут терпеть секунды устаревания.

KV Instant использует Quicksilver v2 — внутреннее хранилище, которое Cloudflare создала для собственного распространения конфигурации. Каждый запрос Cloudflare уже обращается к Quicksilver — для правил маршрутизации, конфигураций файрвола, порогов ограничения скорости. Он проверен в бою в масштабах, которые большинство игровых бэкендов никогда не достигнут.

Вот конкретное сравнение производительности:

Метрика KV Instant KV Classic
p99 чтения (все) 1.62 ms 287 ms
p99 репликация записи 256 ms 4,380 ms
Медианная репликация записи 107 ms < 1 с (без субсекундной точности)

Это улучшение задержки чтения в 177 раз и улучшение репликации записи в 17 раз. Эти цифры взяты из собственного бенчмаркинга Cloudflare по всем 300+ edge-локациям.

Для игрового бэкенда вывод прямой: вы можете читать конфиг в каждом запросе игрока — при входе, при старте матча, при получении инвентаря, при открытии магазина — и стоимость чтения составляет менее 2 мс даже на p99. Не нужно ждать TTL. Нет окна когерентности кэша, в котором игрок A видит исправление эксплойта, а игрок B — нет.


Плейбук: обнаружение сбоев из-за устаревших конфигов в вашей игре

Прежде чем мигрировать что-либо, нужно понять, есть ли у вас эта проблема. Вот режимы отказа, как их обнаружить и во что они вам обходятся.

Режим отказа 1: устаревшие чтения с истёкшим TTL

Что ломается: Ваше хранилище конфигов использует кэширование на основе TTL. Фича-флаг обновляется, но игроки в Токио всё ещё читают старое значение в течение 30–60 секунд, пока не истечёт срок действия edge-кэша.

Как это обнаружить:

  • Логируйте хэш версии конфига, возвращаемый каждому клиенту, вместе с временной меткой записи, когда конфиг был последний раз обновлён.
  • Запрашивайте клиентов, получающих версию конфига, которая старше 2 секунд после записи.
  • Соберите дашборд: count of (stale_reads) / count (total_reads). Всё, что выше 0% во время пуша конфига, — это окно устаревших чтений.

Быстрый диагностический паттерн запроса (адаптируйте под ваш стек логирования):

SELECT
  received_config_version,
  expected_config_version,
  COUNT(*) AS stale_count,
  MAX(received_at - config_updated_at) AS max_staleness
FROM config_read_log
WHERE config_updated_at > NOW() - INTERVAL '1 hour'
  AND received_config_version != expected_config_version
GROUP BY received_config_version, expected_config_version
ORDER BY max_staleness DESC;

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

Режим отказа 2: чтение конфигов на горячем пути вызывает скачки задержки

Что ломается: Задержка чтения вашего хранилища конфигов достаточно высока (100–300 мс), и вы не можете позволить себе читать его в каждом запросе. Вместо этого вы кэшируете его на стороне клиента или в быстром, но устаревающем локальном кэше. Кэш корректен в 99% случаев, но когда он ошибается, он ошибается очень сильно.

Как это обнаружить:

  • Измеряйте p50, p95 и p99 задержки вызова чтения конфига. Если p99 выше 50 мс, это слишком медленно для проверок в каждом запросе.
  • Отслеживайте процент попаданий в кэш. Если вы кэшируете конфиг на стороне клиента, чтобы не обращаться к хранилищу, вы уже приняли устаревание как компромисс.
  • Следите за инцидентами, когда плохое значение конфига сохраняется после пуша — проследите его до TTL клиентского кэша.

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

Режим отказа 3: усиление записи при инциденте

Что ломается: Вам нужно отправить экстренное обновление конфига — отключить функцию, включить режим обслуживания, пометить сломанную экономику — а записи медленные или ограничены по скорости. Классический Workers KV позволяет одну запись на ключ в секунду, а репликация занимает секунды.

Как это обнаружить:

  • Отслеживайте задержку от записи до видимости во время реагирования на инцидент. Если ваша ops-команда рассчитывает, что «конфиг должен распространиться за несколько секунд», а это занимает 10+, ваше хранилище конфигов становится узким местом инцидента.
  • Мониторьте ошибки записи и ответы с кодом 429 (rate-limit) во время срочных пушей.

Если вы сталкиваетесь со всеми тремя режимами отказа, KV Instant стоит оценить.


Внедрение KV Instant для игровой конфигурации: пошагово

KV Instant сейчас находится в закрытой бете (private beta). Вы можете подать заявку через форму беты Cloudflare. Реализация проста, потому что API идентичен классическому Workers KV — отличается только создание namespace.

Шаг 1: создайте namespace KV Instant

Передайте атрибут mode: "instant" при создании namespace:

wrangler kv namespace create "GAME_CONFIG" --mode instant

Это создаст привязку namespace. Обновите ваш wrangler.toml:

[[kv_namespaces]]
binding = "GAME_CONFIG"
id = "&lt;your-namespace-id>"

Шаг 2: запишите вашу игровую конфигурацию

Namespaces KV Instant ограничены 10 000 пар ключ-значение с общим размером namespace 1 МБ. Каждый ключ может быть до 300 байт. Это мало — и это намеренно. Он предназначен для флагов конфигурации и настроек, а не для данных игроков.

Структурируйте ключи для конфигурационного слоя вашей игры:

// In a Cloudflare Worker that manages config
async function updateGameConfig(env) {
  const config = {
    maintenanceMode: false,
    maintenanceMessage: "Servers are updating. Back in 5 min.",
    eventSchedule: {
      currentEvent: "summer_showdown_2025",
      startTime: "2025-07-15T18:00:00Z",
      endTime: "2025-07-22T18:00:00Z",
    },
    economyTuning: {
      xpMultiplier: 1.5,
      goldDropRate: 0.85,
      shopRefreshHours: 6,
    },
    featureFlags: {
      newMatchmaking: true,
      rankedModeV2: false,
      socialLobby: true,
    },
    buildVersion: {
      minimumClient: "1.4.2",
      forceUpdate: false,
    },
  };

  await env.GAME_CONFIG.put("active_config", JSON.stringify(config));
  // Propagates to 300+ edge locations in ~256ms at p99
}

Лимит частоты записи: одна запись на namespace в секунду. Это проектное ограничение, а не баг — оно делает порядок обновлений детерминированным. Для конфига, который меняется несколько раз в час (или за инцидент), это не узкое место.

Шаг 3: отдавайте конфиг с edge

Создайте Cloudflare Worker, который читает конфиг в каждом запросе и отдаёт его вашему игровому клиенту:

export default {
  async fetch(request, env, ctx) {
    // Every player request reads fresh config — 1.62ms p99
    const raw = await env.GAME_CONFIG.get("active_config");
    if (!raw) {
      return new Response(JSON.stringify({ error: "config_missing" }), {
        status: 503,
        headers: { "Content-Type": "application/json" },
      });
    }

    const config = JSON.parse(raw);

    // Conditional logic at the edge — maintenance mode check
    if (config.maintenanceMode) {
      return new Response(
        JSON.stringify({
          status: "maintenance",
          message: config.maintenanceMessage,
        }),
        {
          status: 503,
          headers: { "Content-Type": "application/json" },
        }
      );
    }

    // Return relevant config slice for the client
    const clientConfig = {
      event: config.eventSchedule,
      economy: config.economyTuning,
      features: config.featureFlags,
      build: config.buildVersion,
    };

    return new Response(JSON.stringify(clientConfig), {
      headers: {
        "Content-Type": "application/json",
        "Cache-Control": "public, max-age=5", // Short cache for freshness
      },
    });
  },
};

Шаг 4: используйте конфиг в игровом клиенте

На стороне клиента загружайте конфиг во время инициализации или начала сессии. Вот пример на GDScript для игры на Godot:

extends Node

var config_url: String = "https://config.yourgame.com/api/config"
var current_config: Dictionary = {}

func _ready():
    fetch_config()

func fetch_config():
    var http = HTTPRequest.new()
    add_child(http)
    http.request_completed.connect(_on_config_received)
    http.request(config_url)

func _on_config_received(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray):
    if response_code != 200:
        push_warning("Config fetch failed: %d" % response_code)
        return

    var json = JSON.new()
    var parse_result = json.parse(body.get_string_from_utf8())
    if parse_result != OK:
        push_warning("Config parse error")
        return

    current_config = json.data
    _apply_config(current_config)

func _apply_config(config: Dictionary):
    # Apply feature flags
    if config.has("features"):
        if config["features"].get("rankedModeV2", false):
            enable_ranked_mode()
        if config["features"].get("newMatchmaking", false):
            enable_new_matchmaking()

    # Check build version
    if config.has("build"):
        var min_version = config["build"].get("minimumClient", "0.0.0")
        if version_compare(get_app_version(), min_version) &lt; 0 and config["build"].get("forceUpdate", false):
            show_force_update_screen()

    # Apply economy tuning
    if config.has("economy"):
        EconomyManager.set_xp_multiplier(config["economy"].get("xpMultiplier", 1.0))
        EconomyManager.set_gold_drop_rate(config["economy"].get("goldDropRate", 1.0))

    print("Config applied successfully — all players now on same state")

Поскольку чтение занимает менее 2 мс и нет устаревания по TTL, вы можете вызывать fetch_config() при каждом начале сессии, при каждом входе в очередь матча или при каждом значимом действии клиента, не беспокоясь о накладных расходах на задержку или когерентности кэша.


Что KV Instant не может делать (жёсткие ограничения)

KV Instant мощный в своей нише, но ограничения реальны. Оцените их, прежде чем браться за реализацию:

Общий размер namespace 1 МБ. Вы не можете хранить данные игроков, снимки лидербордов, инвентарь или что-либо, что растёт вместе с числом игроков. Это чисто для конфигурации и флагов, применяемых глобально.

Максимум 10 000 пар ключ-значение. Достаточно для сотен фича-флагов и объектов конфигурации. Недостаточно для чего-либо в расчёте на игрока.

Одна запись на namespace в секунду. Если вам нужна частота записи менее секунды, это не ваше хранилище. Для игрового конфига, который обновляется ежечасно или во время инцидентов, это нормально. Для синхронизации игрового состояния в реальном времени ищите другое.

Нет поддержки метаданных. getWithMetadata возвращает null. Вы не можете прикреплять пользовательские метаданные к ключам. Если вы полагаетесь на метаданные для версионирования или тегирования, вам нужно встраивать их в само значение.

Нет пагинации в list. Каждый вызов list возвращает все подходящие ключи в namespace. Для 10 000 ключей это большой ответ. Осознанно подходите к именованию ключей и использованию префиксов, чтобы ограничивать область вызовов list.

Асимметрия стоимости. Хранение стоит $100/МБ/мес (против $0,50/ГБ/мес для Classic). Операции записи класса A — $0,10 за каждую (против $5,00 за миллион для Classic). Эти цифры запретительны для нагрузок с высокой частотой записи. Но чтение стоит $0,20 за миллион — на 60% дешевле, чем Classic. Модель ценообразования сильно перекошена в сторону «пиши редко, читай постоянно» — а это ровно паттерн игрового конфига.


Лучшие практики для игрового конфига на KV Instant

  1. Именуйте ключи в namespace осознанно. Используйте префиксы вроде ff_ для фича-флагов, econ_ для настройки экономики, evt_ для расписаний событий. Это делает вызовы list удобными для просмотра и позволяет создавать UI управления конфигом, которые работают с конкретными категориями, не читая весь namespace.

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

  3. Отделяйте конфиг от состояния. KV Instant хранит конфигурацию — правила, флаги, настройки, расписания. Он не хранит состояние — инвентари игроков, результаты матчей, рейтинги лидербордов. Проектируйте их как две отдельные системы с разными бэкендами хранения. Если ваш namespace «config» растёт более чем на несколько КБ в неделю, поместите эти данные в другое место.

  4. Обрабатывайте случай 503. Если GAME_CONFIG.get() возвращает null, ваш worker должен корректно завершаться. Возвращайте режим обслуживания или аварийный рубильник. Отсутствующий ключ конфига никогда не должен ронять игровой клиент. Встраивайте запасной вариант в edge-воркер, а не в клиент.

  5. Тестируйте порядок записи под нагрузкой. Одна запись в секунду на namespace означает, что конкурентные записи будут сериализованы. Если два инженера отправляют изменения конфига в одну и ту же секунду, побеждает последняя запись. Создайте очередь изменений конфига с явным порядком, а не полагайтесь на конкурентные записи.


Когда вместо этого использовать управляемый сервис конфигурации

Создание пайплайна распространения конфигов на KV Instant — это разумное инженерное решение, если у вашей команды есть ресурсы, чтобы владеть edge-воркером, UI управления конфигами, схемой версионирования, клиентской логикой загрузки и процедурами реагирования на инциденты. Это настоящая инфраструктурная работа — по отдельности не сложная, но в сумме она растягивается на весь срок разработки.

Для команд, которые хотят распространение конфигов без управления всей инфраструктурой, horizOn предоставляет Remote Configuration как управляемый сервис. Вы определяете фича-флаги, игровые настройки и параметры тюнинга через дашборд или API, а платформа занимается распространением до ваших игровых клиентов. Не нужно писать или поддерживать edge-воркеры, не нужно думать об ограничениях размера KV namespace — но и контроля над базовым движком репликации и профилем задержек меньше.

Компромисс — это классическая ось «создать против купить». KV Instant даёт вам сырую производительность на edge с полным контролем. Управляемый сервис даёт более быстрое время интеграции и меньшую операционную поверхность. Выбирайте, исходя из того, является ли распространение конфигов ключевой компетенцией вашей студии или инфраструктурными накладными расходами.

Если вам нужно обнаруживать устаревание конфигов на распределённых игровых клиентах, описанные выше в разделе плейбука паттерны логирования и запросов работают независимо от того, какой бэкенд конфигов вы выберете. Диагностический слой не зависит от транспорта.


Итоги: чтение конфигов, которое успевает за вашей игрой

KV Instant — это значимое обновление для конкретного паттерна «небольшие, критические, глобально читаемые данные конфигурации». Для игровых бэкендов этот паттерн напрямую соответствует фича-флагам, настройке экономики, расписаниям событий, переключателям обслуживания и шлюзам версий сборки.

Цифры — не маркетинговое округление: чтение на p99 за 1,62 мс и репликация записи на p99 за 256 мс в 300+ edge-локациях. API идентичен классическому Workers KV. Ограничения (1 МБ, 10 000 ключей, 1 запись/секунду) чётко определены и соответствуют варианту использования.

Если ваша игра сейчас читает конфиг из централизованного хранилища и кэширует его на стороне клиента, чтобы избежать задержек, оцените, приемлемо ли это окно устаревания. Для соревновательных игр и live-сервисов с настройкой экономики в реальном времени ответ всё чаще — нет.

Запишитесь в закрытую бету KV Instant, создайте тестовый namespace с вашим самым чувствительным к задержкам конфигом и измерьте запас по распространению, который вы получаете. Если цифры совпадут с тем, что сообщает Cloudflare, у вас есть чёткий путь к полному устранению одного класса инцидентов с устаревшими конфигами.

Нужен второй взгляд на вашу архитектуру конфигов или топологию бэкенда? Загляните в документацию horizOn — платформа берёт на себя распространение конфигов, отчёты о сбоях и управление игровыми сессиями, чтобы вы могли сосредоточиться на выпуске геймплея, а не на инфраструктурных плейбуках.


Источник: Представляем Workers KV Instant — на базе Quicksilver