ADR-0002: Kafka I/O on Source/Sink V2¶
| Status | Accepted |
| Date | 2026-04-23 |
| References | KZM-2.0 |
Context¶
Flink 2.x removed the legacy FlinkKafkaConsumer/FlinkKafkaProducer classes (Source/Sink V1) that Apache StateFun's Kafka I/O was built on. Running on Flink 2.2.x meant the Kafka ingress and egress layer had to be rebuilt on the new connector APIs, without breaking the KafkaIngressSpec/KafkaEgressSpec surface that users and module.yaml depend on.
Decision¶
Migrate Kafka ingress to KafkaSource with a KafkaRecordDeserializationSchema delegate, and Kafka egress to KafkaSink (Sink V2). Keep KafkaIngressSpec, KafkaEgressSpec, and the module.yaml schema unchanged so this is purely a connector-layer swap, invisible to function code.
Consequences¶
- Savepoints taken on upstream Apache StateFun are not restorable on the fork; the new source/sink operators use a different internal state layout than the removed V1 connectors.
withKafkaProducerPoolSizeis a silent no-op underKafkaSink, which manages its own producer pool internally. Callers relying on this setting see no effect.- Delivery semantics now map onto Flink's
DeliveryGuaranteeenum;EXACTLY_ONCErequires a transactional ID prefix to be configured, unlike the old producer default. - The StateFun state path itself is byte-identical to upstream: only the connector layer changed. In practice a cross-fork restore still requires dropping the connector operators' state (
allowNonRestoredState) and re-reading offsets from Kafka, so treat upstream savepoints as non-restorable and plan a reprocessing cutover instead. - Follow-up: the missing
transactionalIdPrefixdefault forEXACTLY_ONCEwas flagged as a production gap during coverage analysis and should be addressed as a documented requirement or a safer default.