Fluxtion is the compiler for event-driven logic. Annotate POJOs with @OnEventHandler; the compiler infers the event graph and emits a
deterministic dispatcher class — readable, audit-instrumented and replayable from the same input events. Execution inference like type inference, but for your event-handling dispatch.
// Counts trades.
public class TradeCounter {
private int count;
@OnEventHandler
public boolean onTrade(Trade t) {
count++;
return true;
}
public int count() { return count; }
}
// Reacts to the counter — the constructor ref is the wiring.
public class TradePublisher {
private final TradeCounter counter;
public TradePublisher(TradeCounter counter) {
this.counter = counter;
}
@OnTrigger
public boolean publishCount() {
System.out.println("trades: " + counter.count());
return true;
}
}
// Add only the child — Fluxtion discovers TradeCounter.
var flow = Fluxtion.compile(new TradePublisher(new TradeCounter()));
flow.onEvent(new Trade("AAPL", 100));// Generated by Fluxtion — plain Java, lives in your repo.
public final class TradeProcessor implements EventProcessor {
private final TradeCounter tradeCounter = new TradeCounter();
private final TradePublisher publisher =
new TradePublisher(tradeCounter);
@Override
public void onEvent(Object event) {
if (event instanceof Trade) {
handleEvent((Trade) event);
}
}
private void handleEvent(Trade typedEvent) {
boolean tradeCounter_updated =
tradeCounter.onTrade(typedEvent);
if (tradeCounter_updated) {
publisher.publishCount();
}
}
}Open source · Java 8+ · zero install · runtime is one jar
Fluxtion is an ahead-of-time compiler for event-driven Java. Source-gen, not reflection. The artifact is a plain Java class.
Annotate POJOs with @OnEventHandler / @OnTrigger. The
compiler walks the graph at build time and emits a deterministic dispatcher class.
The generated source is the audit. Replay reproduces the same decisions from the same input events. Your runtime
classpath is fluxtion-runtime + your code — no broker, no actor system,
no DAG to deploy.
The application logic is ordinary Java. The orchestration is not hand-written, configured in a workflow tool, or discovered by a runtime scheduler.
Fluxtion infers orchestration from explicit structure — annotated handlers, triggers, dependencies and the object graph — and generates a dispatcher as plain Java, so the runtime coordination is visible, testable and replayable.
What inferred orchestration programming is →| You provide | Fluxtion infers | Generated Java shows |
|---|---|---|
@OnEventHandler | event entry point | onEvent(...) |
| object-graph dependency | dispatch order | handleEvent(...) |
@OnTrigger | trigger propagation | node.onTrigger() |
| state dependency | change propagation | if (isDirty_...) |
| processor definition | executable orchestration | Processor.java |
Source generation, not runtime reflection. Generated Java, not a hidden runtime DAG. Ordinary POJOs, not a bespoke workflow language. The generated artefact is the product.
…but compile-time. Single dispatcher class instead of an actor system. No message-protocol design.
…but local and embeddable. No broker required. Your dispatcher is just a Java class, instantiate it where you like.
…but the topology is a .java file you read. No .uid() load-bearing for savepoint compatibility.
…but the generated code lives in your repo. The reactive graph compiles to ordinary methods you can step through in a debugger.
Where Fluxtion sits vs Kafka, Aeron, Chronicle, RxJava, Hazelcast and Spring Modulith: compare → · Longer story: alternative comparisons
Fluxtion walks your annotated POJOs at compile time and emits a flat Java class
containing dispatch order, trigger graph, and audit hook points. Your runtime
dependency is fluxtion-runtime + your code — no compiler at startup, no
reflection in the hot path, no DAG to deploy. The output is plain Java: your IDE
navigates it, your VCS diffs it, your auditor reads it.
//DEPS com.telamin.fluxtion:fluxtion-builder:1.0.8
//JAVA 21
package demo;
import com.telamin.fluxtion.Fluxtion;
import com.telamin.fluxtion.runtime.DataFlow;
import com.telamin.fluxtion.runtime.annotations.OnEventHandler;
import com.telamin.fluxtion.runtime.annotations.OnTrigger;
public class Trades {
public static void main(String[] a) {
// Add only the child — Fluxtion discovers TradeCounter and
// emits the dispatcher below.
DataFlow flow = (DataFlow) Fluxtion.compileAot(
"demo.generated", "TradeProcessor",
new TradePublisher(new TradeCounter()));
flow.init();
flow.onEvent(new Trade("AAPL", 100));
System.out.println("""
See generated Fluxtion dispatcher here:
less src/main/java/demo/generated/TradeProcessor.java""");
}
public record Trade(String symbol, int qty) {}
public static class TradeCounter {
private int count;
@OnEventHandler public boolean onTrade(Trade t) {
count++;
System.out.println("received -> " + t);
return true;
}
public int count() { return count; }
}
public static class TradePublisher {
private final TradeCounter counter;
public TradePublisher(TradeCounter counter) { this.counter = counter; }
@OnTrigger public boolean publishCount() {
System.out.println("trades: " + counter.count());
return true;
}
}
}// Generated by Fluxtion. This is the file you read,
// audit, diff in your VCS, and ship to production.
public final class TradeProcessor implements EventProcessor {
private final TradeCounter tradeCounter = new TradeCounter();
private final TradePublisher publisher =
new TradePublisher(tradeCounter);
@Override
public void onEvent(Object event) {
if (event instanceof Trade) {
handleEvent((Trade) event);
}
}
// Strongly-typed dispatch. One method per event type.
// The dispatcher's structure IS your event graph — every
// node call, every trigger edge, made explicit.
private void handleEvent(Trade typedEvent) {
boolean tradeCounter_updated =
tradeCounter.onTrade(typedEvent);
// @OnTrigger fan-out, in dependency order.
if (tradeCounter_updated) {
publisher.publishCount();
}
}
}jbang runs a single .java file directly — no Maven, no project. It
reads the //DEPS lines at the top, fetches those jars,
compiles the file, and runs main: jbang Trades.java.
That compile step runs on Fluxtion's cloud
generator — it turns your topology into the dispatcher and hands it back. It's a
service with a free tier for development:
drop a key in ~/.fluxtion and every jbang
run just works. (The playground is keyless because it bundles a local generator.) Get a free-tier key →
$ jbang Trades.java [jbang] Building jar for Trades.java... INFO: Using compiler strategy: javac received -> Trade[symbol=AAPL, qty=100] trades: 1 See generated Fluxtion dispatcher here: less src/main/java/demo/generated/TradeProcessor.java
$ jbang Trades.java
apiKey=MISSING_KEY
Register and create an API key here:
https://rapidapi.com/hub
Exception in thread "main" java.io.IOException: Remote source
generation failed with HTTP 401: {"message":"Invalid API key.
Go to https://docs.rapidapi.com/docs/keys for more info."}That 401 is expected, not a bug — no key, no compile. The generator is a
service, and its free tier covers local dev.
Want zero setup? The browser playground is keyless — the same example, generated in-page, nothing to install. Run it keyless in the playground →
The core graph-inference mechanism is patented (US filing 2026). The runtime is open source (AGPL today; Apache 2.0 under consideration) and carries a patent grant for its use.
Same nodes, same generated dispatcher — what you choose is when Fluxtion builds the graph. Bake it at build time for a fixed, audit-ready binary, or generate it in-process so the topology can evolve while the application runs.
Fluxtion emits the dispatcher as a plain .java file during mvn compile. The structure is fixed and committed to your repo; your
only runtime dependency is fluxtion-runtime. Auditable, native-image-ready,
zero startup cost — the right shape when the topology is known and stable.
Fluxtion builds the graph at startup, so the structure isn't
fixed: when your topology needs to change — add nodes, rewire branches, swap a
rule — regenerate it in-process and keep running. The trade: the generator has to be
reachable at runtime (a key in ~/.fluxtion, or the local generator on the
classpath).
Either way you get the same dispatcher and the same audit trail — only the timing differs. See every authoring channel × generation mode →
One mechanism — source-gen of a flat readable dispatcher — produces both. Read each
from the generated .java.
Dispatch order, trigger fan-out, lifecycle propagation, audit hook points — the compiler emits them. They're no longer code you maintain; they're code you read. Integration becomes a compile-time problem, solved once. The same property that makes vendor JARs free to consume applies to every component you write yourself.
The pattern, externalisedFlat structure is a branch-predictor's happy place. No reflection in the runtime path; the JIT inlines aggressively. Nodes allocate once at startup; the dispatcher stays hot in L1 icache. Zero per-event allocation from the substrate — your handlers choose the rest. The structure is the optimisation; you don't tune it, you just don't fight it.
Performance — server speed on a phoneThe compiler is the core; these are the tools around it — grouped by where you are in the lifecycle: build it, ship it, prove it.
Configure host, generation mode and starting topology — scaffold a production-ready Maven project in a few clicks.
Open starterRun, replay and inspect graphs instantly in your browser — GraphML view and audit-log step-through for time-travel debugging. Keyless.
Open playgroundLive graph preview as you wire nodes, real-time linting on illegal wiring, and jump from a graph node straight to its Java source.
Learn moreAOT generation as part of your build — graph validation, source-gen and GraalVM
reachability metadata, emitted during mvn compile.
The dispatcher is plain Java with no hot-path reflection, and the Maven plugin emits GraalVM reachability metadata — so your graph is ready to compile to a native binary. No JVM to warm up: fast cold starts, serverless-friendly.
Native via the Maven pluginSame compiled dispatcher, hosted in an industrial server — agent-threading, event sourcing, replay and an admin console around your processor.
Mongoose docsConnect your graph to the world — ready-made connectors for Kafka, Aeron, Chronicle Queue, JDBC and WebSocket, instead of writing them.
Plugin catalogueManage a running server in production — inspect node state, drive lifecycle and watch throughput from a browser console.
Admin-web docsReplay an auditable decision: scrub back through a payment authorization event-by-event and watch the accept / reject branch propagate — see exactly why each decision passed or failed, reproduced from the original events.
Open the demoA POJO, a Main, an event. Run it and read the dispatcher.
A 47-node generated dispatcher from a declarative builder. Six sinks, three trigger policies, replay-deterministic.
A neural network as a Fluxtion graph. Same compile mechanism; weights as Java arrays. Inference is dispatch.
The 2D matrix: four authoring channels × seven generation modes. Pick any cell; see the generated dispatcher.
Drop a JAR of pre-built Fluxtion nodes onto a consumer's classpath. Field references materialise the rest of the subgraph automatically.
Same compiled dispatcher, hosted in Mongoose for agent-threading, feeds, sinks. Deployment is plugin selection, not a code change.
JUnit 5 example: drive events through the compiled processor, assert state, verify byte-equal replay. Runs in the browser.
Fluxtion is unusually suited to AI authoring: you write intent (nodes + wiring), and the compiler guarantees determinism, audit and replay — a careless author can't introduce a race or a non-deterministic decision; the source-gen step enforces it.
You write nodes; the compiler wires them. Each node is ~30 lines, so a model reasons locally — one node at a
time — and the compiler does the topology. Its errors are directive (use @AssignToField), so a model with a run loop self-corrects instead of guessing.
There's no closed operator library to learn: any Java method is a candidate operator, so a model writes against the JDK and your domain code, not a framework API it has to memorise.
Point your assistant at the Fluxtion author guide and golden-path doc and it bootstraps itself — the conventions, the gotchas, the troubleshooting index, in one place. Then it iterates against real compiler feedback until the graph builds.
Bootstrap your LLM for FluxtionOpen source, one runtime jar, developed in the open since 2019. The badges devs scan for — stars, latest release, licence, good-first-issues — and a place to start.
Built by Greg Higgins. Fluxtion has been in development since 2019; 1.0 shipped in May 2026. The core graph-inference mechanism is patented — the open-source runtime carries a patent grant for its use.