nerv-event is a Spring Boot event-delivery library for applications that need durable, broker-neutral publication and consumption. It persists delivery intent before contacting Kafka or SQS, then uses a durable Inbox to make consumer processing recoverable and idempotency-aware.
Publishing directly to a broker from a business transaction creates a failure window: the database can commit while the broker send fails, or the broker can receive an event while the database rolls back. nerv-event writes an Outbox record in the same transaction as the business update and sends it later. On the consumer side it persists an Inbox record before acknowledging the broker message.
Key capabilities include transactional Outbox publication, atomic database-local Inbox handling, optional aggregate ordering keys, Kafka and SQS adapters, database-backed retry, PostgreSQL migrations, observability, operations/manual recovery, retention, and multi-pod-safe claims with Outbox fencing tokens.
This source tree targets 2.1.0. Applications upgrading from 1.x must apply the new Outbox fencing
migration and update any direct OutboxService integrations; see Upgrading to 2.0.
For normal Spring Boot applications, add the public starter:
<dependency>
<groupId>com.czetsuyatech.nerv</groupId>
<artifactId>nerv-event-spring-boot-starter</artifactId>
<version>${nerv-event.version}</version>
</dependency>The starter brings Spring integration, JPA persistence, and the Kafka and SQS adapters. Kafka and SQS are inactive until nerv.event.kafka.enabled=true and/or nerv.event.sqs.enabled=true. Outbox publication is auto-detected from an application RetryPolicy, custom OutboxDispatcher, configured destination, or nerv.event.outbox.enabled=true. Inbox-only applications need no Outbox setting. Once publication is active, startup fails if an OutboxService can accept publications but no functional dispatcher is available. nerv.event.outbox.enabled=false remains available as an explicit opt-out.
Configure PostgreSQL, apply the packaged migrations, select a broker, and map a logical destination:
spring:
datasource:
url: jdbc:postgresql://localhost:5432/orders
username: orders
password: ${ORDERS_DB_PASSWORD}
jpa.hibernate.ddl-auto: validate
nerv:
event:
destinations:
orders:
broker: kafka
target: order-events
kafka:
enabled: trueInside a business transaction, build an EventMessage and publish an EventPublication to the logical destination. Implement EventHandler<T> for inbound event types. You do not need NERV component scanning, @EnableJpaRepositories, @EntityScan, @KafkaListener, or @SqsListener.
@Transactional
void createOrder(Order order) {
orders.save(order);
eventPublisher.publish(EventPublication.<OrderCreated>builder()
.event(EventMessage.<OrderCreated>builder()
.id(new EventId(UUID.randomUUID().toString()))
.type("order.created")
.timestamp(clock.instant())
.source("orders")
.payload(new OrderCreated(order.id()))
.build())
.destination(new Destination("orders"))
.orderingKey(order.id().toString())
.build());
}The ordering key is optional. Same-key Outbox rows are dispatched in persisted sequence; Kafka uses it as the record key and SQS FIFO producers use it as the message group ID. Standard SQS queues provide no ordering guarantee. Polling jitter uses Java's standard java.base runtime and requires no optional random-provider module.
See Getting Started, Publishing, and Consuming for the complete path.
Application -> EventPublisher -> Outbox -> OutboxDispatcher -> Kafka / SQS
Kafka / SQS -> consumer adapter -> Inbox -> ConsumerDispatcher -> EventHandlerInterceptor chain -> EventHandler<T>
The detailed module and lifecycle view is in Architecture.
- Getting Started
- Configuration reference
- Inbox and Outbox
- Kafka and SQS
- Database, Operations, and Observability
- Production guide and limitations
- Upgrading from 1.x to 2.0
The runnable adoption reference is nerv-examples/nerv-event-spring-boot-demo.
- Java 21 or newer
- Spring Boot 4.1.0 dependency management (the current build baseline)
- PostgreSQL is the tested production database; H2 is only a test/development convenience
- Kafka and standard SQS queues are supported adapters
nerv-event provides at-least-once delivery, not distributed exactly-once processing. See Production guide before production adoption.
Use the project license and repository conventions in this repository. Maven coordinates use com.czetsuyatech.nerv; Java packages remain com.czetsuyatech.nerv.event.