Представляем Cloudflare K2: бессерверные потоки событий
- Cloudflare открыла бета-доступ к K2 для платных аккаунтов Workers; во время беты использование бесплатно.
- K2 хранит события упорядоченным журналом поверх R2 и позволяет нескольким потребителям читать их независимо; задержка записи — около 1 секунды на 99-м перцентиле.
- В бета-версии действуют лимиты: 10 ГБ хранилища и 30 МБ/с записи на поток.
Почему это важно: K2 развязывает производителей и потребителей: независимые читатели могут обрабатывать события в собственном темпе, а данные не теряются при длительном простое потребителей.

В традиционных архитектурах удалённого вызова процедур (RPC) есть одна ключевая проблема: производители и потребители должны соответствовать друг другу по масштабу и времени. Если производители отправляют больше данных, чем могут обработать потребители, или если потребители либо нижестоящие сервисы становятся недоступны, события теряются. Проблема усугубляется, если данные должны независимо обрабатывать несколько потребителей. Например, серверная часть интернет-магазина может генерировать события после завершения транзакций, которые нужно передать системе аналитики и сервису обнаружения мошенничества.
Решить эту проблему можно, развязав производителей и потребителей — добавив между ними сервис, который принимает записи и позволяет независимым читателям обрабатывать данные в собственном темпе.
Сегодня мы запускаем Cloudflare K2 в открытой бета-версии, чтобы решить эту проблему. K2 — это надёжный примитив потоковой передачи событий на платформе для разработчиков. Вы отправляете события в поток K2, где они хранятся в виде упорядоченного журнала. Потребители могут читать их разными способами: например, распределять чтение между группой потребителей или доставлять все сообщения каждому потребителю. Сервис полностью бессерверный, масштабируется для работы с огромными объёмами данных и поддерживает долгосрочное хранение, поэтому данные не теряются даже при длительном простое потребителей.
В основе K2 лежит секционированный надёжный журнал поверх объектного хранилища R2, благодаря чему сервис может масштабироваться для хранения огромных объёмов данных.
Чтобы начать работу, создайте первый поток за несколько секунд, следуя инструкции здесь.
Потоки на периферии сети
Мы создали K2, потому что нам самим понадобился надёжный буфер на периферии сети — изначально он должен был служить слоем приёма данных для Basin Pipelines. В основе Pipelines лежит система потоковой обработки, работающая по модели pull-запросов. Это означает, что какая-то другая система должна хранить события до того, как их прочитают, преобразуют и запишут в R2. А поскольку мы гарантируем, что события не будут потеряны после приёма в поток Pipelines, хранилище должно быть надёжным — то есть не терять данные — даже на протяжении потенциально длительных периодов времени.
Большинство компаний в такой ситуации развернули бы Apache Kafka. Однако Pipelines работает на периферии сети Cloudflare, охватывающей огромное количество серверов в более чем 335 городах. Наша уникальная архитектура означает, что мы часто не можем использовать традиционное программное обеспечение для распределённых систем, например Kafka, и должны переосмыслить принципы их создания и эксплуатации.
Глобальная инфраструктура Cloudflare создаёт определённые сложности, особенно для сервисов с сохранением состояния: нам доступны сравнительно небольшие части машин, сами машины существуют относительно недолго, а взаимодействие по сети часто происходит через публичный Интернет. Но у нашей инфраструктуры есть и особые преимущества: она находится рядом с пользователями по всему миру и обладает исключительными возможностями горизонтального масштабирования.
Разрабатывая систему надёжной буферизации, которая впоследствии стала K2, мы решили использовать уже имеющийся у нас мощный примитив хранения состояния — R2. Объектные хранилища, такие как R2, сочетают исключительно надёжное хранение (11 девяток! ) с API со строгой согласованностью. Передав репликацию и достижение консенсуса на уровень хранилища, мы смогли сделать уровень приложения (в данном случае K2) гораздо проще, дешевле и производительнее. Ещё одно преимущество — разделение вычислительных ресурсов и хранения, благодаря которому их можно масштабировать независимо друг от друга. Это позволяет недорого хранить огромные объёмы исторических данных.
Как построить журнал поверх объектного хранилища? Сразу возникает проблема: R2, как и другие объектные хранилища, не поддерживает добавление данных в конец файла — стандартную операцию для журнала. Вместо этого мы должны записывать целые файлы, или сегменты, достаточно большого размера, чтобы оправдать затраты на запись и чтение каждого из них. Для этого мы сначала накапливаем записи в памяти периферийного сервиса. Выждав немного, чтобы поступили данные, мы записываем все события в файл-сегмент. Упорядоченность и строго возрастающие смещения обеспечиваются атомарными операциями R2, поэтому отдельный сервис координации не нужен.
Использование R2 даёт множество преимуществ, но есть и один недостаток: повышенная задержка при записи данных. Запись в объектное хранилище медленнее, чем на локальный диск, к тому же перед её началом нужно дождаться накопления локального пакета данных. В первой версии K2 это приводит к задержке записи около 1 секунды на 99-м перцентиле времени ответа.
В ближайшее время мы подробнее расскажем об устройстве K2 в отдельном техническом разборе.
Потоки, очереди или конвейеры?
У Cloudflare уже есть несколько примитивов для асинхронной доставки данных, в том числе Queues и Basin Pipelines. В каких случаях стоит выбрать K2, а не эти продукты?
На первый взгляд, Queues и потоки K2 похожи: оба сервиса принимают события, надёжно хранят их и доставляют потребителям. Queues предназначен для отслеживания отдельных задач, требующих значительных затрат или времени и выполняемых асинхронно. Например, приложение для обработки изображений может поместить запрос пользователя в очередь, чтобы его обработал сам сервис обработки изображений. Queues поддерживает сложную логику для каждой отдельной задачи — например, повторные попытки, задержки и очереди недоставленных сообщений для неудачных попыток.
K2, напротив, предназначен для перемещения больших объёмов данных, долгосрочного хранения и доставки сообщений нескольким потребителям. Сообщения записываются и считываются пакетами — это повышает эффективность обработки, но не позволяет повторно отправлять отдельные сообщения. Пакетная обработка также приводит к более высокой задержке при записи, чем в Queues.
Basin Pipelines — это бессерверный сервис приёма данных. В него можно отправлять события в формате JSON, которые затем можно преобразовать и записать в R2 или каталог Basin. Мы рекомендуем Pipelines, если в итоге нужно записать события в объектное хранилище или таблицы Iceberg, а K2 — для пользовательской обработки или записи в другие места назначения.
Начало работы
Чтобы начать работать с K2, сначала нужно создать поток. В аккаунте можно создать множество потоков для разных задач или типов событий. Потоки можно создавать с помощью cf, Wrangler, панели управления или API.
Рассмотрим пример сбора и обработки аналитических данных о продукте. Сначала создадим поток с помощью cf:
$ cf k2 streams create --name app_events --http-enabled
{
"id": "d78b09ee1f50430e9ec92a8af92b0231",
"name": "app_events",
"retention_seconds": 604800,
"endpoint": "https://d78b09ee1f50430e9ec92a8af92b0231.k2.cloudflarestorage.com",
"http": {
"enabled": true,
"authentication": false
},
"worker_binding": {
"enabled": true
},
"created_at": "2026-09-28T15:14:39.053Z",
"modified_at": "2026-09-28T15:14:39.053Z"
}
Создав поток, мы можем начать отправлять в него данные через HTTP API или привязку Worker. Например, из Worker:
const result = await env.EVENTS.send([
{
content: new TextEncoder().encode(
JSON.stringify({
event: "page_view",
path: new URL(request.url).pathname,
timestamp: Date.now(),
}),
),
headers: { "content-type": "application/json" },
},
]);
if (!result.success) {
console.error(`Produce failed: ${result.error.message}`);
return new Response("Failed to record event", {
status: result.error.retryable ? 503 : 500,
});
}K2 представляет данные в виде байтов, поэтому можно использовать любой формат или кодировку, подходящие для вашего приложения.
Когда события уже поступают в поток, можно создать подписку. Подписки распределяют работу между потребителями, обеспечивая параллельное чтение — возможность масштабироваться за счёт нескольких читателей и обрабатывать больший объём данных, чем под силу одному серверу.
Подписку можно создать через HTTP API.
$ curl -X POST "https://d78b09ee1f50430e9ec92a8af92b0231.k2.cloudflarestorage.com/subscriptions" \
-H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
-H "Content-Type: application/json" \
--data '{
"name": "analytics_processor",
"start_at": { "type": "earliest" }
}'{
"result": { "id": "ee13f761783d3823a447a47b572ebf76" },
"success": true,
"errors": [],
"messages": []
}
Создав подписку, можно опрашивать её из каждого потребителя:
$ curl -X POST \"https://4d8f5394e3e733debdeca9c65c5b7439.k2.cloudflarestorage.com/subscriptions/ee13f761783d3823a447a47b572ebf76/consume" \
-H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
-H "Content-Type: application/json" \
--data '{
"worker_id": "analytics-1",
"max_records": 100
}' {
"result": {
"batch_id": "b7e4c9210a3f468d95c2e1068fdb734a",
"leased_until_ms": 1790633929437,
"records": [
{
"timestamp_ms": 1790633629168,
"content": "eyJldmVudCI6InBhZ2VfdmlldyJ9",
"headers": {
"content-type": "application/json"
}
},
...
]
},
"success": true,
"errors": [],
"messages": []
}Когда клиент вызывает consume, он получает аренду на эту конкретную партию событий сроком на 5 минут. Клиент может выполнить одно из трёх действий:
- подтвердить (ack) получение партии — она помечается как обработанная и больше не доставляется повторно
- отклонить (nack) её (отрицательное подтверждение), сообщив, что обработать партию не удалось и её нужно доставить повторно
- продлить срок аренды, если для завершения обработки требуется больше времени
$ curl -X POST "https://d78b09ee1f50430e9ec92a8af92b0231.k2.cloudflarestorage.com/subscriptions/ee13f761783d3823a447a47b572ebf76/batches/b7e4c9210a3f468d95c2e1068fdb734a/ack" \
-H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
-H "Content-Type: application/json" \
--data '{ "worker_id": "analytics-1" }'Это один из способов читать данные из K2: распределить работу между несколькими потребителями, чтобы каждый получал свою часть данных. Другой вариант — создать отдельную подписку для каждого потребителя, используя модель pub/sub; тогда каждый потребитель получает все сообщения. Можно также сочетать оба подхода, создав несколько независимых групп потребителей.
Полное описание API см. в документации K2.
Стоимость и доступность
Сегодня K2 доступен в открытой бета-версии для аккаунтов с платными подписками Workers. Действуют следующие ограничения:
- Максимальный объём используемого хранилища — 10 ГБ
- Скорость записи — 30 МБ/с на поток
Если вам нужны более высокие лимиты, свяжитесь с командой в Discord или заполните форму запроса на повышение лимитов.
В период бета-тестирования плата за использование K2 взиматься не будет. После начала тарификации мы планируем установить следующие цены:
Стоимость | |
Записанные данные | 0,04 доллара / ГБ |
Прочитанные данные | 0,04 доллара / ГБ |
Хранимые данные | 0,02 доллара / ГБ / месяц |
Что дальше
В ближайшие месяцы мы планируем активно развивать K2. В числе нововведений:
- Повышение параллелизма записи — пропускная способность потоков до нескольких ГБ/с
- Ключи сообщений и гарантии упорядочивания на основе ключей
- Потребители-воркеры с push-моделью
- Тариф Express с меньшей задержкой при записи и сквозной задержкой
- Совместимость с клиентами Apache Kafka без необходимости их доработки
Нам не терпится увидеть, что вы создадите с помощью K2! Делитесь отзывами в Discord-сообществе Cloudflare.
