Start Building
Responsive|
Distributed
Systems
Evento is the Java framework
to build RECQ architectures —
where the architecture is enforced, not hoped for.
Develop RECQ
Components in Java
- Easy implementation of Invokers, Services, Aggregates, Projectors, Projections, Sagas and Observers in Java.
- Use annotations to define the component type and Command, Query or Event handlers.
- Implement interactions with the Message Gateway.
- Evento Framework works great even with other Java frameworks like Spring, Micronaut, Quarkus.
Hover the annotations to flip through real code from the live demo →
@Invoker
public class TodoListInvoker extends InvokerWrapper {
@InvocationHandler
public String createTodoList(String name, String user) throws Exception {
var identifier = "TDLS_" + UUID.randomUUID();
getCommandGateway()
.send(new TodoListCreateCommand(identifier, name),
toUserMetadata(user))
.get(30, TimeUnit.SECONDS);
return identifier;
}
@InvocationHandler
public CompletableFuture<TodoListView> findTodoListByIdentifier(String id) {
return getQueryGateway()
.query(new TodoListViewFindByIdentifierQuery(id))
.thenApply(Single::getData);
}
}
@Saga(version = 1)
public class ErpTodoListActivityRegistrationSaga {
@SagaEventHandler(init = true, associationProperty = "identifier")
public SagaState on(TodoListCreatedEvent event) { /* start tracking */ }
@SagaEventHandler(associationProperty = "identifier")
public void on(TodoListTodoCheckedEvent event, SagaState state,
CommandGateway commandGateway) throws Exception {
if (event.isAllChecked()) {
commandGateway.send(new ErpUserActivityRegisterCommand(
"TodoList", event.getIdentifier(), state.getUsages()
)).get();
}
}
}
@Projection
public class TodoListProjection {
@QueryHandler
public Single<TodoListView> handle(TodoListViewFindByIdentifierQuery q) {
return Single.of(repository.findById(q.getIdentifier())
.map(TodoList::toView).orElseThrow());
}
@QueryHandler
public Multiple<TodoListListItemView> handle(TodoListListItemViewSearchQuery q) {
return Multiple.of(repository.search("%" + q.getNameLike() + "%",
PageRequest.of(q.getPage(), q.getSize()))
.map(TodoList::toListItemView).toList());
}
}
@Projector(version = 2)
public class TodoListProjector {
@EventHandler
public void on(TodoListTodoCheckedEvent event, Metadata metadata,
Instant timestamp, ProjectorStatus status) {
var list = repository.findById(event.getIdentifier()).orElseThrow();
var todo = list.todo(event.getTodoIdentifier());
todo.setCompletedAt(timestamp.atZone(ZoneId.systemDefault()));
todo.setCompletedBy(metadata.get("user"));
repository.save(list);
if (status.isHeadReached()) sse.notifyListChanged(list.getId());
}
}
@Aggregate
public class TodoListAggregate {
@AggregateCommandHandler
public TodoListTodoAddedEvent handle(TodoListAddTodoCommand command,
TodoListAggregateState state) {
Assert.isTrue(state.getTodos().size() < 5,
"Error: Todo list is full");
return new TodoListTodoAddedEvent(command.getIdentifier(),
command.getTodoIdentifier(), command.getContent());
}
@EventSourcingHandler
public void on(TodoListTodoAddedEvent event,
TodoListAggregateState state) {
state.getTodos().put(event.getTodoIdentifier(), false);
}
}
Evento GUI · Catalog
Navigate the Catalog
The rigorous semantic of the RECQ Pattern lets Evento Server generate the System Catalog automatically from your code — explore and visualize the interactions of every Payload, Component and Bundle.
// Your javadoc, your annotations, your handlers…
/**
* Manager of the user's todo lists:
* validates commands, emits events.
*/
@Aggregate
public class TodoListAggregate { … }
scanned at startup — zero extra work
📖 TodoListAggregate Aggregate
Manager of the user's todo lists: validates commands, emits events.
↗ view source on GitHub
Evento GUI · Documentation
Documentation that can't lie
- Evento Server scans your bundles at startup — payloads, components and handlers become the catalog. No wiki, no stale diagrams.
- Rename a command, add a handler — the docs update themselves with the next deploy.
- Every handler deep-links to its source line on GitHub.
Evento GUI · Flows & Application Graph
Understand your RECQ Architecture
Flows render every interaction as a tree — how components cooperate, where to optimize. Explore your entire system or a subset, starting from a Payload, a Component or a Bundle, then switch to the Application-Graph to interact with the whole architecture at once.
Evento GUI · Performance
What-If Performance Analysis
Given a workload, estimate the concurrent requests handled by each handler, component and bundle — the algorithm detects the bottleneck of every interaction. Tune workload, service time and invocation frequency to find the best optimization or estimate computational resources before you buy them.
Available now
Evento 3
Everything you need to build a RECQ system in Java and run it from one site to three continents — every feature public, the client libraries under Apache-2.0.
Seven RECQ components
Aggregates, Services, Projectors, Projections, Sagas, Observers and Invokers — annotated Java classes that announce themselves to the server. No deployment descriptors.
Exactly-once commands
Idempotency keys make every retry safe on whichever server it lands; sagas, projectors and observers derive theirs automatically.
Aggregates that never fork
Every event carries its aggregate version under a unique index: two commands deciding from the same state can never both be stored.
Cluster from one site to three continents
Several servers on one PostgreSQL event store. Bundles fail over, fail back on their own, and are answered close to the caller.
Highly available consumers
Run every consumer, per context, in as many replicas as you like: one holds the lane, another takes over when it goes — no event lost or repeated.
Consumers that wait, not poll
The server tells each bundle when events it handles arrive. Updates flow at once, and an idle system costs the event store almost nothing.
Queries at any size
Streamed and paged answers with flow control, bundle-to-bundle streams, and read-your-writes when a query must see a command.
Payloads that evolve
Rename or reshape a command, event or query: upcasters read the history written with the old class, the event store is never rewritten.
Secure by default
Bus token, TLS, payload allowlist and real passwords required in production; single sign-on and audit trail for the console.
Privacy built in
Personal data encrypted per data subject: delete the subject's key and it is erased from the whole event history.
Observable
A console generated from your code, OpenTelemetry tracing and Prometheus metrics.
Any Java stack
Plain Java, Spring, Micronaut or Quarkus, a Spring Boot starter, test fixtures and an in-process broker, on Java 25.
Tested to break
Proven under failure, not only in the happy path
Exactly-once, failover and consumers that never skip an event are promises you should not take on trust. Evento 3 is checked against them on a three-continent lab, through rolling upgrades, and on the test suites of two production systems — a marketplace and a manufacturing-execution system — and benchmarked for what each command and query costs.
1,000+
automated tests on every change — PostgreSQL 16 and 17, MySQL 8.4, real TCP between bundles and servers
19
chaos scenarios on a three-continent lab: servers killed and frozen, a region cut off, database failovers, clock skew
0
acknowledged commands lost or executed twice, and no aggregate forked, in any scenario
3 × 3
contexts × replicas, the lane holder killed mid-stream: every event applied once and in order
3,900
commands a second stored by one server on a 4-core machine, p99 about 60 ms
7 ms
median round trip of a command on one machine, timed phase by phase from arrival to reply
Born from research, proven in production
7
component types — formally minimal, proven irredundant
235 kLOC
production manufacturing-execution system running on RECQ — 206 components, censused
2023
first peer-reviewed publication (QualITA’23) and founding master’s thesis
Do you find Evento Framework and RECQ Architectures interesting?
Evento Framework is FREE and Open Source. You can always support the project by giving a star on GitHub or contributing to the code base.
