У 2026 році Kafka Streams виповнюється десять років. Фреймворк потокової обробки, що є частиною проєкту Apache Kafka під егідою Apache Software Foundation, давно став критично важливим для великих компаній. У свіжому епізоді Confluent Developer Podcast інженер Confluent Маттіас Й. Сакс розповідає, куди рухається Streams далі. Один із найцікавіших векторів — еволюція state stores: від простого key–value до повноцінних записів із часовими мітками, заголовками та покращеною обробкою помилок.

Від простого key–value до подій із часом: як влаштовані state stores
Kafka Streams з самого початку будувався як бібліотека для розробників, а не як окремий кластерний сервіс. Уся «пам’ять» потокових обчислень — це локальні state stores, які живуть поряд із застосунком. Під капотом для цих сховищ використовується RocksDB — вбудована, високопродуктивна key–value база, оптимізована для роботи на диску.
Історично state stores у Kafka Streams були максимально простими: ключ і значення. Для багатьох сценаріїв цього було достатньо — наприклад, для агрегацій за ключем чи збереження проміжних результатів join-операцій. Але щойно розробники почали масово переходити до подійно-орієнтованих архітектур із чітким поділом на event time та processing time, стало очевидно: цього мінімуму замало.
Щоб коректно працювати з подіями, які можуть приходити із запізненням, потрібна надійна опора на часову мітку самої події, а не лише на момент її обробки. Саме тому одним із ранніх великих кроків у розвитку Kafka Streams стало розширення state stores підтримкою timestamp. Тепер кожен запис у сховищі міг містити не лише key та value, а й час події, що дозволило суттєво покращити event-time семантику.
Це наблизило модель зберігання в state stores до того, як виглядає запис у самому Kafka-топіку: ключ, значення, час. Але до повної відповідності ще бракувало одного важливого елемента — заголовків.
Чому заголовки мають значення для потокової обробки
У Kafka заголовки (headers) давно стали стандартним інструментом для збагачення повідомлень метаданими. Вони дозволяють передавати службову інформацію, не торкаючись основного payload: ідентифікатори трасування, тип події, версію схеми, технічні маркери маршрутизації, ознаки повторної доставки тощо.
Поки дані «летять» через топіки, заголовки зберігаються разом із повідомленням. Але щойно потік заходить у Kafka Streams і частина даних осідає в state stores, виникає розрив: історично ці сховища зберігали лише ключ, значення та, згодом, timestamp. Заголовки губилися.
Це створювало низку практичних обмежень. Якщо застосунок хотів, наприклад, зберегти кореляційний ID чи інформацію для трасування разом із проміжним станом, доводилося вбудовувати ці дані в саме значення. Для цього розробники створювали власні типи, дублювали структуру «payload + метадані» у value, писали додатковий код серіалізації та десеріалізації. Формально це працювало, але суперечило самій ідеї заголовків як окремого каналу метаданих і додавало багато шаблонного коду.
Особливо це відчувалося для тих, хто працює не лише з високорівневою DSL, а й із Processor API, де взаємодія зі state stores більш явна. Там розробники могли вручну моделювати зберігання «значення плюс заголовки» у власних структурах, але це означало ще більше boilerplate і більший ризик помилок.
Потреба у «повноцінних» записах у state stores, які зберігають усе те саме, що й повідомлення в Kafka-топіку, включно із заголовками, накопичувалася роками. Це була давня, добре відома вимога користувачів, яка довго залишалася у беклозі.
Kafka Streams 4.3: state stores з повноцінними заголовками
У релізі Kafka Streams 4.3 ситуація змінюється принципово. У state stores з’являється підтримка заголовків: тепер вони можуть зберігатися поряд із ключем, значенням і часовою міткою. Це означає, що запис у state store логічно стає максимально схожим на запис у Kafka-топіку: key, value, timestamp, headers.
Технічно все це, як і раніше, лежить у RocksDB, але для розробника це прозора деталь реалізації. На рівні API state store тепер працює з повноцінним набором полів, а не змушує розробника «упаковувати» заголовки в значення. Можна читати й записувати значення разом із timestamp та колекцією headers, не думаючи про те, як саме це зберігається в RocksDB.
Це знімає одразу кілька класів проблем.
По-перше, зникає потреба дублювати структуру повідомлення у власних типах. Метадані, які логічно належать до заголовків, залишаються заголовками і в state store. Це спрощує моделі даних, зменшує обсяг коду й робить топології більш прозорими.
По-друге, зберігається безперервність інформації вздовж усього шляху події. Те, що потрапило в заголовки на вході в Kafka, може пройти через кілька топологій, осісти в state store, бути модифікованим і знову вийти в топік — без втрати структури. Для складних систем із кількома сервісами та довгими ланцюжками обробки це критично для спостережуваності, трасування та аудиту.
По-третє, це зменшує бар’єр входу для тих, хто раніше змушений був переходити на Processor API лише заради більш гнучкої роботи зі станом і метаданими. Частина сценаріїв, які вимагали ручного моделювання «значення плюс заголовки», тепер може бути реалізована на вищому рівні абстракції, із меншими витратами на інфраструктурний код.
Важливий нюанс: підтримка заголовків у state stores у 4.3 — це великий крок, але ще не фінальна точка. Функціональність не вважається повністю завершеною: попереду кілька наступних KIP’ів (Kafka Improvement Proposals), які мають «довести до ладу» API й можливості, зробити підтримку заголовків справді всеохопною в різних типах сховищ і сценаріях.
Втім, уже зараз зрозуміло, що напрямок руху однозначний: Kafka Streams прагне до того, щоб state stores поводилися як природне продовження Kafka-топіків, а не як окремий, спрощений світ.
Від винятків до dead letter queue: як спільнота змінює обробку помилок
Еволюція state stores — не єдина сфера, де Kafka Streams стає «дорослішим». Останні роки принесли суттєві зміни в тому, як фреймворк дозволяє працювати з помилками під час обробки подій. І тут ключову роль відіграла спільнота користувачів.
Один із яскравих прикладів — компанія Michelin. Вона є великим користувачем Kafka Streams і побудувала навколо нього власне «скелетування» — внутрішню обв’язку, яка спрощує використання Streams у масштабі організації. Цей фреймворк Michelin відкрила на GitHub, і саме звідти кілька ідей почали свій шлях у ядро Kafka Streams.
Серед них — покращена обробка винятків. У потокових системах помилки на окремих записах — неминучі: невалідні дані, проблеми з десеріалізацією, неочікувані стани. Раніше розробникам доводилося самостійно будувати складні механізми навколо Streams, щоб не «валити» увесь застосунок через один проблемний запис.
Тепер у Kafka Streams з’явилися розширені можливості для обробки винятків, які дають розробникам більше контролю над тим, що робити з помилковими подіями. Це результат спільної роботи команди Confluent і зовнішніх контриб’юторів, зокрема інженерів Michelin, які перенесли свої напрацювання з внутрішнього фреймворку в KIP’и.
Ще один важливий крок — поява dead letter queue (DLQ) у Kafka Streams. Це окремий топік або набір топіків, куди можуть спрямовуватися записи, обробка яких завершилася помилкою. Замість того щоб зупиняти весь потік або втрачати дані, система може «відкласти» проблемні події для подальшого аналізу чи повторної обробки.
Dead letter queue давно є стандартним патерном у світі черг повідомлень і інтеграційних платформ. Для Kafka Streams поява вбудованої підтримки DLQ означає, що розробникам більше не потрібно винаходити власні велосипеди для маршрутизації помилкових записів. Це знижує ризики, спрощує експлуатацію й робить поведінку системи більш передбачуваною.
Важливо, що і покращена обробка винятків, і DLQ — це не «спущені зверху» фічі, а результат реального бойового досвіду великих користувачів. Michelin не лише відкрила свій фреймворк, а й активно працює над KIP’ами, щоб інтегрувати ці можливості безпосередньо в Kafka Streams. Це показовий приклад того, як великі організації можуть не просто використовувати open source, а й формувати його розвиток.
Спільнота, KIP’и й майбутнє state stores
Розвиток підтримки заголовків у state stores і нових механізмів обробки помилок відбувається на тлі помітного зростання активності спільноти Kafka Streams. За останні дванадцять місяців кількість контриб’юцій суттєво зросла. Це створює додаткове навантаження на мейнтейнерів, які мають переглядати KIP’и й pull request’и, але загальна оцінка якості залишається позитивною.
Так, трапляються поодинокі «шумові» PR’и — великі, погано описані, іноді з тисячами змінених файлів без зрозумілої мети. Але це радше неминучий побічний ефект високої популярності проєкту. У більшості випадків код, який надходить, виглядає якісним, а іноді навіть важко сказати, чи писала його людина, чи з допомогою AI-інструментів. Ключовим фільтром залишається ретельний код-рев’ю.
Показово, що робота над підтримкою заголовків у state stores для релізу 4.3 стала великим спільним проєктом. Ініціатива й основні ресурси прийшли від Confluent, але до неї приєдналися чотири-п’ять інженерів із ширшої спільноти, які взяли на себе частину завдань. Такий формат співпраці дозволяє реалізовувати масштабні зміни швидше й водночас зберігати відкритість процесу.
Попереду — наступні KIP’и, які мають зробити підтримку заголовків у state stores по-справжньому всеохопною. Потрібно врахувати різні типи сховищ, сценарії використання, інтеграцію з існуючими API. Але загальний вектор уже не зміниться: Kafka Streams рухається до того, щоб state stores були не просто локальними key–value таблицями, а повноцінним відображенням подій Kafka з усіма їхніми атрибутами.
Це важливо не лише з точки зору зручності розробки. Чим ближче модель state stores до моделі Kafka-повідомлень, тим легше мислити про систему цілісно. Подія, яка народжується в одному сервісі, проходить через топіки, обробляється кількома потоковими застосунками, зберігається в state stores і знову виходить у Kafka, залишається тією самою подією з точки зору структури. Це спрощує проєктування, дебагінг і еволюцію системи.
Висновок: Kafka Streams дорослішає разом із вимогами до потокових систем
Десять років тому Kafka Streams стартував як відносно легка бібліотека для побудови потокових застосунків поверх Kafka. Сьогодні це зрілий інструмент, який працює у місіон-критичних сценаріях у великих компаніях. Еволюція state stores — від простого key–value до записів із timestamp і заголовками — добре ілюструє, як змінюються вимоги до потокових систем.
Підтримка заголовків у state stores у релізі 4.3 робить модель даних у Kafka Streams більш повною й узгодженою з Kafka. Покращена обробка винятків і dead letter queue, значною мірою народжені у спільноті, зокрема в Michelin, піднімають на новий рівень надійність і керованість потокових застосунків.
Разом із активним зростанням команди Kafka Streams у Confluent і хвилею зовнішніх контриб’юцій це свідчить про одне: Kafka Streams не просто зберігає актуальність у світі, де з’являються нові стрімінгові платформи, а й продовжує активно розвиватися. І наступне десятиліття, схоже, пройде під знаком ще глибшої інтеграції зі світом подій, де кожен байт метаданих — від timestamp до headers — має значення.
Джерело
Повний епізод подкасту:
https://www.youtube.com/watch?v=wuWJ99wp9hQ


