Skip to content

kzmlabs/flink-statefun

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1,316 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

StateFun Actors by Kzmlabs

Stateful actors on Apache Flink 2.x and Java 21 — durable per-key state, exactly-once messaging, Kafka and Kinesis I/O, Kubernetes-native deployment. Continues the Apache Stateful Functions programming model on the modern Flink line, with active releases on Maven Central and GHCR.

Maven Central GitHub Release License K8s E2E Coverage OpenSSF Scorecard Contributors Last commit

📖 Documentation  ·  ⚡ Quickstart  ·  📦 Maven Central  ·  🐳 GHCR  ·  🆚 vs Apache StateFun  ·  🌟 Awesome StateFun


What is this?

You write a function keyed by a logical ID. The runtime gives it per-key durable state, routes messages to it, replays on failure, and connects it to Kafka and Kinesis. Actor programming on top of Apache Flink — without writing a Flink job by hand.

flowchart LR
    KafkaIn["Kafka / Kinesis<br/>ingress"] --> Dispatch["StateFun<br/>dispatcher"]
    Dispatch -->|"state-keyed message"| Func["Function instance"]
    Func -->|"HTTP request-reply"| Remote["Remote endpoint"]
    Func -->|"emit"| Egress["Kafka / Kinesis<br/>egress"]
    Func <-->|"state I/O"| State[("RocksDB keyed state<br/>checkpointed to S3")]
Loading

Use cases: event-driven microservices, real-time fraud detection, IoT digital twins, payment orchestration, actor-style stateful compute, distributed sagas, serverless stream processing.

Why this exists

Apache Stateful Functions stopped releasing in October 2024 at 3.4.0, locked to Flink 1.16 and Java 11. Anyone wanting to run it against modern Flink either pinned old dependencies or vendored their own patches. StateFun Actors is the public, actively maintained branch — same code, modern stack, no vendor lock-in.

Update — May 2026: Apache has filed FLIP-569: Sunset the Stateful Functions sub-project, formalising the end of upstream maintenance and naming "fork the repository" as one of the migration paths. This fork was already active before the proposal landed; FLIP-569 confirms the read from October 2024 that picking the project up was worth doing.

Apache StateFun 3.4.0 StateFun Actors KZM-3.3
Flink runtime 1.16.2 2.2.0
Java baseline 11 21
Maven group org.apache.flink io.github.kzmlabs.flinkstatefun
Kinesis I/O Flink 1.x consumer Restored on Flink 2.x source/sink
K8s release gate None Mandatory kind + Flink Operator + LocalStack
Active CI Inactive after 3.4.0 Dependabot, CodeQL, Scorecard, Trivy
Release cadence Dormant Active (Maven Central + GHCR)

Full migration notes: Differences from Apache StateFun.

Quickstart

1. Add the dependency

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>io.github.kzmlabs.flinkstatefun</groupId>
      <artifactId>statefun-bom</artifactId>
      <version>3.4.0-KZM-3.3</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependency>
  <groupId>io.github.kzmlabs.flinkstatefun</groupId>
  <artifactId>statefun-sdk-java</artifactId>
</dependency>

2. Write a stateful function

import org.apache.flink.statefun.sdk.java.*;
import org.apache.flink.statefun.sdk.java.message.Message;

public class GreeterFn implements StatefulFunction {

  static final TypeName TYPE = TypeName.typeNameFromString("example/greeter");

  @Override
  public CompletableFuture<Void> apply(Context ctx, Message msg) {
    String name = msg.asUtf8String();
    System.out.println("Hello, " + name + "!");
    return ctx.done();
  }
}

3. Wire it in module.yaml

kind: io.statefun.endpoints.v2/http
spec:
  functions: example/*
  urlPathTemplate: http://my-fn-svc:8080/statefun

4. Run the runtime

docker run --rm -p 8081:8081 \
  -v $(pwd)/module.yaml:/opt/flink/conf/module.yaml \
  ghcr.io/kzmlabs/flink-statefun:3.4.0-KZM-3.3

Full walkthrough → Quickstart guide.

Module structure

Module Purpose
statefun-sdk-java Java SDK for remote functions
statefun-sdk-embedded Embedded SDK for co-located functions
statefun-flink-core Core Flink integration
statefun-flink-distribution Distribution JAR for deployment
statefun-flink-runner Uber JAR for K8s deployment via Flink Operator
statefun-kafka-io Kafka ingress/egress connectors
statefun-kinesis-io AWS Kinesis ingress/egress connectors
statefun-shaded Relocated Protobuf to avoid version conflicts
statefun-docker Distribution Docker image build
statefun-bom Bill of Materials for version alignment
statefun-e2e-tests/statefun-e2e-k8s-native Kubernetes-native end-to-end test gate

Building from source

git clone https://github.com/kzmlabs/flink-statefun.git
cd flink-statefun
./mvnw clean install                  # full build + K8s E2E gate (~25–30 min)
./mvnw clean install -Dskip.k8s.e2e   # skip the kind cluster (~5–7 min)
./mvnw clean install -DskipTests      # compile + package only (~3–5 min)

Prerequisites: Java 21, Maven 3.9+ (or ./mvnw), Docker (for the K8s E2E gate).

Restricted-network builds: set IMAGE_REGISTRY_PREFIX=harbor.example.com/dockerhub-proxy/ to pull all base images through your registry mirror — every Dockerfile and k8s manifest honours it. Full details in the build guide.

Logging

JobManager and TaskManager logging is configured via spec.logConfiguration.logback-console.xml on the FlinkDeployment — the Flink K8s Operator turns it into a ConfigMap mounted at /opt/flink/conf/. The recommended config uses Logback + LogstashEncoder to emit single-line JSON to stdout (Logstash-standard fields: @timestamp, logger_name, thread_name, level, message, stack_trace) with ShortenedThrowableConverter and rootCauseFirst=true so Flink's deeply wrapped exceptions surface the user-actionable frame on top. See the logging guide for the copy-paste block, in-incident DEBUG targets, and the Operator overlay quirk to be aware of.

Versioning and compatibility

Kzmlabs version Apache StateFun base Flink Java Status
3.4.0-KZM-3.3 3.4.0 2.2.0 21 Latest
3.4.0-KZM-3.1 3.4.0 2.2.0 21 Stable
3.4.0-KZM-3.0 3.4.0 2.2.0 21 Stable

Releases are signed via Sigstore keyless attestation. Verify with:

gh attestation verify oci://ghcr.io/kzmlabs/flink-statefun:3.4.0-KZM-3.3 --owner kzmlabs

Branch model

Branch Role
release Active development — all PRs target this branch.
master Vestigial Apache upstream pointer. Not used for development.

Contributing

Contributions are welcome. See CONTRIBUTING.md for the workflow, and the release process for how versions are cut.

In short:

  1. Branch from release.
  2. Run ./mvnw spotless:apply and ./mvnw -Dskip.k8s.e2e install locally.
  3. Open a PR against release. CI runs the full K8s E2E gate.

Security

Found a vulnerability? See SECURITY.md for the reporting process.

The repo runs CodeQL, OpenSSF Scorecard, Trivy CVE scans, and Dependabot on every push. Releases include SLSA build provenance and Sigstore attestations.

License

Licensed under the Apache License 2.0. Originally derived from Apache Flink Stateful Functions — see NOTICE for upstream attribution.

Citing

If you use StateFun Actors in research, please cite via the CITATION.cff file (GitHub's "Cite this repository" button).

Contributors

This fork continues the codebase originally developed by 41+ contributors to Apache Stateful Functions, including Tzu-Li (Gordon) Tai, Igal Shilman, Seth Wiesman, Stephan Ewen, Till Rohrmann, Martijn Visser, Marta Paes Moreira, and many others — see the full contributor graph for the complete list.

Active maintenance on Flink 2.x and Java 21 by @oleksandr-kazimirov. Pull requests welcome — see CONTRIBUTING.md.

See also

Links


Topics: apache-flink · stateful-functions · statefun · stream-processing · event-driven-architecture · event-driven-microservices · distributed-systems · actor-model · stateful-serverless · kubernetes · flink-kubernetes-operator · kafka · kinesis · rocksdb · exactly-once · java-21 · jvm · real-time-analytics