Telamin treats an event-processing graph the way the JVM treats bytecode: as something to be compiled ahead of time, inspected, and executed deterministically. The result is a stack where audit, replay, debugging, and LLM-authoring fall out of one design decision — compile the processor.
This page walks the six layers of that stack — authoring, compilation, artifact, server, plugins, workflow — and states, at each layer, what you get and what a traditional stream framework, ESB, or actor system does instead.
Speed, safety, and flexibility. Pick a stream framework and you give up audit. Pick a cluster framework and you give up developer ergonomics. Pick an ESB and you give up determinism and latency. The triangle is forced by interpreting the topology at runtime.
Raw threads, lock-free queues, microsecond latency. But no audit trail. You can't reproduce a production bug, and you can't show a regulator what happened.
Heavyweight cluster framework. Snapshots, exactly-once, replay. But the code path is opaque, the dependencies are vast, and "step through" doesn't apply.
Orchestrator-of-orchestrators (Camel, Spring Integration, NiFi). Composable, but you give up deterministic ordering and performance.
Compile the processor and the triangle collapses. The artifact is fast (no reflection, no virtual dispatch through framework interfaces). It is safe (deterministic dispatch, byte-exact replay, audit-by-construction). And it is flexible (authored as plain Java, DSL, Spring XML, YAML, or LLM-emitted bean defs — same compiler, same artifact).
Authoring flows down into the compiler. The compiler emits an artifact that runs unchanged in every environment from unit test to production. The server and plugins are deployment-shape concerns layered around that artifact, not coupled to it.
Authoring is decoupled from runtime. The Fluxtion compiler accepts a logical model of the graph in five shapes: plain Java POJOs (the common case), a fluent DSL builder, Spring XML bean definitions, YAML config, or anything else that emits compatible bean definitions — including from an LLM. The same compiler accepts all five and produces the same artifact.
// plain Java — most common authoring shape
public class FilterAndForward {
private final PriceSink sink;
public FilterAndForward(PriceSink sink) {
this.sink = sink;
}
@OnEventHandler
public boolean onPrice(MarketTick tick) {
if (tick.isStale()) return false; // no propagation
sink.publish(tick);
return true; // notify downstream
}
}| Telamin | Stream framework / ESB |
|---|---|
| Same processor, five authoring shapes | One framework, one DSL |
| Plain POJOs, no framework inheritance | Topology DSL coupled to runtime |
| LLM, GUI, XML, YAML all hit the same compiler | Authoring tool change = topology rewrite |
Fluxtion analyses the bean graph at build time. It walks the trigger annotations, resolves the dependency edges, detects cycles, and emits a fixed-shape Java source file. The dispatch order is a property of the compiled artifact — not a runtime decision recomputed per event.
| Telamin | Stream framework / cluster |
|---|---|
| Dispatch order computed at compile time | Reflective dispatch every event |
| Diagram generated from same analysis | Architecture diagrams rot in Confluence |
| Topology errors caught by the compiler | Topology errors surface in production |
One compile pass produces three outputs: a generated Java source file (open it in your IDE; it is plain code), a GraphML diagram (the structure auditors and architects look at), and a compiled class (what the JVM actually runs). They cannot drift: they are derived from the same analysis.
A single readable file. Set a breakpoint on the dispatch line, step through, watch the events flow. The framework is not in the way; there is no framework.
Open in yEd or Cytoscape. The picture is the picture of the code — generated from the same graph analysis. Auditors get a diagram that cannot lie about what runs.
Drop into any JVM. Lambda, embedded app, regulated host, container — same artifact. No framework runtime required. Mongoose is one host; not the only one.
Because dispatch order is a fixed property of the artifact, every event has a single deterministic causal chain through the graph. You don't have to instrument log lines to know what happened — the dispatch order is the trace. Capture the input event log and re-feed it; processor state is bit-identical to the production run. That is what makes Telamin viable in regulated work where reproducibility is mandatory, not a perk.
| Telamin | Stream framework / cluster |
|---|---|
| Single deterministic causal chain per event | Correlate across distributed logs |
| Bit-exact replay from input event log | Savepoints + prayer |
| Step debugger lands in your code | Ten frames of framework first |
Mongoose hosts the compiled processor on an Agrona AgentRunner,
serialises sink writes (single-writer by contract), and exposes a @ServiceRegistered injection point for cross-cutting services. Same processor in unit
test, integration test, simulation, and production — the only thing
that changes is which plugins are wired up.
One agent per source / sink / service. The dispatcher itself is one agent. Reasoning about concurrency is local — everything an agent sees, it sees on its own thread.
Four hooks: init, start, doWork, tearDown. Clear ordering, idempotent
teardown. Not Spring's seven overlapping stages.
Annotate a setter with @ServiceRegistered.
Type-matched against the service registry at boot. Swap
implementations by YAML config; the processor is unchanged.
| Telamin | Spring Boot / Akka / cluster framework |
|---|---|
| Compiled artifact runs in any JVM | Topology owned by the cluster |
| Four lifecycle hooks, clear semantics | Seven overlapping Spring stages |
| Single-writer sinks by dispatcher contract | Concurrent modifications, opaque threading |
A plugin is a POJO that extends one of three abstract base classes, overrides two or three methods, and ships in its own Maven module. Drop the jar on the classpath, reference the class in YAML or Java config, and it boots. No annotation processor, no buildtime compiler plugin, no framework SPI to register against.
public class MyEventSource
extends AbstractAgentHostedEventSourceService<MyEvent> {
public MyEventSource() { super("my-source"); }
@Override public void onStart() { /* open */ }
@Override public int doWork() {
int published = 0;
while (hasNext()) {
output.publish(nextEvent());
published++;
}
return published;
}
@Override public void tearDown() { /* close */ }
}public class MySink
extends AbstractMessageSink<MyEvent>
implements Lifecycle {
@Override public void init() { /* open */ }
@Override
protected void sendToSink(MyEvent value) {
// dispatcher guarantees single-writer here
write(value);
}
@Override public void tearDown() { /* close */ }
}aeron · chronicle · file · kafka · multicast. Each is its own module with only
its own deps. Pick what you need.
cache · jdbc · admin-rest · admin-telnet · loader-yaml · loader-spring.
Injected by type, swapped by config.
json-serialiser · test-support.
Test support gives you a five-line integration test that
boots a real server. No TestContainers, no Docker.
| Telamin | Spring Boot starters / Quarkus extensions |
|---|---|
| One Maven module per plugin, deps you choose | Starter pulls 50 transitive deps |
| Extend abstract class, override two methods | Buildtime compiler-plugin authoring |
| Drop jar on classpath, reference in YAML | SPI registration + framework boilerplate |
No new IDE, no new build system, no new test runner. Write a processor
as a Java POJO. Maven compiles it (the Fluxtion compiler emits the
dispatcher as a side-effect of normal mvn package). Test it with the
harness. Debug it with the IDE. Replay a captured event log to
reproduce a production bug locally.
| Telamin | Stream framework / cluster framework |
|---|---|
| Five-line integration tests, real server | @SpringBootTest 30s container boot |
| Reproduce prod bug from captured event log | Restore cluster snapshot, diverge anyway |
| Plain JUnit, plain Maven | @SpringBootTest / @QuarkusTest / dev-mode |
Spring XML and YAML are not just human authoring shapes — they are the carrier for LLM-emitted logic. The LLM does what LLMs do (synthesise from intent). The compiler does what compilers do (enforce invariants). The result is an event processor that is auditable and replayable even though it was authored by a non-deterministic model. This pattern is the subject of a provisional patent.
The non-determinism stays at build time, when a human reviews and approves the emitted bean definitions.
The compiled artifact has no model call on the dispatch path. The auditor reads code, not vendor terms-of-service.
Prompt → emitted bean defs → compiled artifact → event log. Every step is recorded and reproducible.
@OnTrigger.The compile-time design removes the usual sources of dispatch overhead. No reflection, no virtual dispatch through framework interfaces, no per-event lambda allocation, no JSON parsing on the dispatch path. What's left is direct method calls the JIT can inline.
AgentRunner (LMAX heritage)@OnTriggerconnector-aeron IPCA published benchmark suite is on the roadmap. What we can say today are the timings the integration tests land on:
These are not benchmarks. They are what the test suite happens to measure. Real numbers will land with the next release.
The same compiled .class runs in your unit test, your
integration test, your simulation, and your production. The
processor doesn't know which environment it's in. The plugin
set — which connectors are wired to which feeds — decides.
This is the property that makes Telamin defensible in regulated work. The thing under audit is the same code that ran in test, simulation, and production. There is no migration step where determinism could be lost.
What an architect will want to know before bringing this in:
Shipped. mongoose-test-support cuts integration-test boot to five lines. Brand new — feedback welcome.
Roadmap. Each plugin exposes counters ad-hoc today. Micrometer / OpenTelemetry wiring is next.
Roadmap. Typos in property names silently no-op. Schema generation is plumbing-grade work that hasn't happened yet.
Builds and cold-starts; benchmark suite pending. The Maven plugin emits GraalVM reachability metadata (tested), reflect-config ships so @ServiceRegistered resolves natively, and the AOT example compiles to a native binary that launches and processes events in ~16 ms — a native executable's cold-start profile. A full native benchmark suite is still to come.
Mostly consolidated. Fluxtion runtime/builder and Mongoose runtime are already under com.telamin.*; Mongoose plugins joined them in 0.2.12 as com.telamin.mongoose.plugin.*. The Maven plugin still carries a legacy root; canonical com.telamin.* by 2.0.
Pending. Architecture removes the usual overhead sources; numbers will land with the next release.
These are catchable in weeks. The dispatcher core — the part that's hard to get right — has been shipping in production at this design point for years.
Run a compiled Fluxtion processor in the browser. See the
generated .java and the dispatcher trace.
Annotation reference, DSL guide, compiler internals. The authoring-level documentation.
Mongoose plugin catalogue — connectors, services, libraries. Per-plugin config tables and runnable examples.
From playground to production. Same artifact, different runtime container.
The business case for compile-time determinism. For compliance, audit, and regulator-facing work.
Cost shape, latency budget, throughput. Why a compiled processor is cheaper to run than an interpreted topology.
The dispatcher is the moat. The rest is good engineering.