Java 21+ Spring Boot 4.0+ Quarkus 3.12+ Dropwizard 4.0+ Jakarta EE 10 MIT License

Distributed Idempotency Engine for Modern Java

Guaranteed exactly-once execution across microservices. Prevent duplicate side-effects, acquire concurrent in-flight locks, detect payload tampering, and replay byte-perfect HTTP responses based on the IETF Idempotency-Key specification.

🚀 Get Started 📂 View GitHub Source
AvoOnce Architecture Diagram

The Gaps In Traditional Distributed Locks

Distributed locks alone (e.g. ShedLock or basic Redis locks) prevent concurrent execution, but fail to solve response replays or payload tampering.

Distributed Execution Challenge Distributed Locks Alone AvoOnce Idempotency Engine
Dropped Responses / Retries ❌ Lock releases after execution; client retries re-execute or fail ✅ Caches & replays exact HTTP status codes, headers, and raw body bytes
Concurrent Duplicate Requests ⚠️ Blocks or rejects; client retry does not receive cached result ✅ Returns immediate 409 Conflict during execution, cached result on retry
Payload Tampering Protection ❌ Same key with modified payload executes or corrupts database ✅ SHA-256 body hash validation rejects modified payloads with 422 Unprocessable Entity
Framework Overhead & Scope ⚠️ Requires complex custom aspects or manual lock boilerplate ✅ Clean, selective @Idempotent annotation with zero overhead for unannotated routes

Built for Production Microservices

Designed with pure Java SPI, high-throughput caching, and multi-framework support.

🎯

Selective Endpoint Protection

Explicit, annotation-driven protection using @Idempotent. Unannotated health checks, metrics, and read endpoints bypass filtering with zero performance cost.

Byte-Perfect HTTP Replay

Captures exact HTTP status code, response headers, and raw response body bytes. Replays cached responses without triggering controller logic or database queries.

🔒

In-Flight Concurrency Locks

Prevents race conditions when clients send parallel duplicate requests. In-flight requests holding the lock receive an instant 409 Conflict response.

🛡️

SHA-256 Payload Hash Validation

Computes cryptographic request hashes. Rejects requests trying to reuse an existing key with altered parameters with a 422 Unprocessable Entity.

🔄

Fault-Tolerant Retry Engine

Transient server errors (HTTP 5xx) automatically transition state to FAILED, releasing the key so clients can safely retry execution.

🔌

Pluggable Storage SPI

Switch seamlessly between single-node Caffeine in-memory, distributed JDBC (PostgreSQL, MySQL, H2, Oracle, MariaDB, SQL Server), and distributed Redis.

Integrate in Minutes

Choose your preferred framework baseline below.

1. Add Dependency (pom.xml)
<dependency>
    <groupId>io.github.ravocode.avoonce</groupId>
    <artifactId>idempotency-spring-boot-starter</artifactId>
    <version>1.0.0</version>
</dependency>
<dependency>
    <groupId>io.github.ravocode.avoonce</groupId>
    <artifactId>idempotency-caffeine</artifactId>
    <version>1.0.0</version>
</dependency>
2. Annotate Controller Endpoints
import io.github.ravocode.avoonce.spring.annotation.Idempotent;
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;

@RestController
@RequestMapping("/api/payments")
public class PaymentController {

    @PostMapping
    @Idempotent // Protected by AvoOnce
    public ResponseEntity<PaymentResponse> createPayment(@RequestBody PaymentRequest req) {
        return ResponseEntity.status(201).body(paymentService.process(req));
    }
}
1. Add Dependency (pom.xml)
<dependency>
    <groupId>io.github.ravocode.avoonce</groupId>
    <artifactId>idempotency-jaxrs</artifactId>
    <version>1.0.0</version>
</dependency>
<dependency>
    <groupId>io.github.ravocode.avoonce</groupId>
    <artifactId>idempotency-caffeine</artifactId>
    <version>1.0.0</version>
</dependency>
2. CDI Filter Producer & Endpoint Protection
@ApplicationScoped
public class IdempotencyProducer {
    @Produces @Singleton
    public IdempotencyContainerFilter filter() {
        return new IdempotencyContainerFilter(new CaffeineIdempotencyRepository(new IdempotencyConfig()));
    }
}

@Path("/api/payments")
public class PaymentResource {
    @POST
    @Idempotent // Name-bound JAX-RS protection
    public Response createPayment(PaymentRequest req) {
        return Response.status(201).entity(paymentService.process(req)).build();
    }
}
1. Register in Dropwizard Application.run
@Override
public void run(MyConfiguration config, Environment environment) {
    IdempotencyRepository repository = new CaffeineIdempotencyRepository(new IdempotencyConfig());
    
    // Register AvoOnce JAX-RS Name-Bound Filter
    environment.jersey().register(new IdempotencyContainerFilter(repository));
}
2. Annotate Resource Methods
import io.github.ravocode.avoonce.jaxrs.Idempotent;
import jakarta.ws.rs.*;

@Path("/api/orders")
public class OrderResource {

    @POST
    @Idempotent // Name-bound protection for Dropwizard
    public Response placeOrder(OrderRequest request) {
        return Response.ok(orderService.place(request)).build();
    }
}
Standard Jersey / RESTEasy Filter Registration
ResourceConfig resourceConfig = new ResourceConfig();

IdempotencyRepository repository = new CaffeineIdempotencyRepository(new IdempotencyConfig());
resourceConfig.register(new IdempotencyContainerFilter(repository));

resourceConfig.register(PaymentResource.class);

Strict State Machine & IETF Standard

Clean separation between framework adapters, state machine, and pluggable storage engines.

AvoOnce Architecture Diagram
1

Key Extraction & Inspection

The @Idempotent filter intercepts the request, extracts Idempotency-Key header, and computes a SHA-256 body hash.

2

Payload Hash & Lock Check

If cached payload hash mismatches → returns 422 Unprocessable Entity. If key is currently IN_PROGRESS → returns 409 Conflict.

3

Execution & Response Caching

If lock acquired, controller executes. Response status, headers, and body bytes are stored as COMPLETED for instant replay.

4

Fault-Tolerant Retry

Server 5xx errors transition record to FAILED, allowing the client to safely retry the request with the same key.

Production-Ready Storage Backends

Pick the storage engine that matches your infrastructure topology.

☕ Caffeine (In-Memory)

Ultra-fast, zero-dependency in-memory store. Ideal for single-node applications or local testing with automated sliding-window eviction.

🗄️ JDBC (Relational DB)

Multi-dialect support for PostgreSQL, MySQL, H2, Oracle, MariaDB, and SQL Server. Features automatic table initialization (auto-ddl) and scheduled background cleanup.

⚡ Redis (Distributed Cache)

High-throughput distributed store leveraging Redis native TTL expiration and zero-dependency binary record serialization for maximum performance.