How I built a lightweight idempotency engine in vanilla Java to prevent duplicate requests, race conditions, and replay attacks in financial systems.
When building financial systems, one of the most critical challenges is preventing duplicate transactions. A user clicking a button twice, a network timeout followed by a retry, or a client-side bug can all trigger multiple identical requests. Without proper safeguards, this leads to double charges, duplicate orders, or other costly errors.
I faced this exact problem and decided to build a lightweight idempotency engine in Java, focusing on a "Vanilla-First" approach to maintain complete control over memory usage and performance.
The Architecture
The engine acts as a State Interceptor, sitting between incoming requests and business logic. When a request arrives with a unique key, the engine checks its state:
- If it's a new request, it proceeds normally
- If it's a duplicate, it handles it based on the previous state
- If it's within a protected window, it blocks the request
This simple pattern provides powerful protection against the most common failure modes.
Key Features
LRU Cache for Memory Management
I implemented a synchronized LRU (Least Recently Used) cache to store transaction records in memory. This is crucial for preventing memory overflow under heavy load - when the cache reaches capacity, the oldest entries are automatically evicted. This keeps memory usage predictable and bounded, even during traffic spikes.
Thread-Safety with Synchronized Collections
Using Collections.synchronizedMap, the engine protects against race conditions in multi-threaded environments. This is essential because multiple requests for the same transaction might arrive simultaneously from different threads or processes.
Anti-Fraud Window
The engine includes a 30-second preventive block for identical attempts. This mitigates replay attacks where malicious actors capture and resend packets. Any request with the same key within this window is automatically rejected.
Failure Resilience
The engine distinguishes between successful and failed transactions. If an operation fails, it allows an immediate retry by clearing the error state. This ensures that temporary failures don't permanently block legitimate operations.
Defense Layers
Here's how the engine protects against different attack vectors:
| Challenge | Defense Mechanism | Goal |
|---|---|---|
| Double Spending | Unique Idempotency Key | Prevent duplicate charges in real-time |
| Replay Attack | Timestamp Validation | Block captured packets from third parties |
| Race Condition | Memory Synchronization | Prevent parallel requests from bypassing validations |
| Memory Overflow | LRU Eviction Policy | Maintain server stability under heavy load |
Why Vanilla Java?
Building this from scratch using vanilla Java allowed me to implement a custom Registration object to encapsulate transaction metadata (values, status, and timing) without the overhead of heavy frameworks. This approach provides:
- Complete control over memory management and performance characteristics
- Deep understanding of system behavior and failure modes
- No hidden dependencies or framework-specific quirks
- Easier debugging and troubleshooting
The Implementation
The core of the engine is a synchronized map that stores transaction states keyed by a unique identifier. Each entry contains:
- Transaction metadata (amount, user ID, etc.)
- Current status (pending, success, failed)
- Timestamp of last operation
- Retry count
When a request arrives, the engine:
- Generates or extracts a unique key
- Checks the cache for existing state
- Applies the appropriate logic based on current state
- Updates the state if the operation proceeds
- Returns the cached result for duplicates
Real-World Impact
This approach has proven effective in production environments where:
- Network reliability is variable
- Client applications might retry automatically
- Multiple services might process the same request
- Memory usage must be predictable
By implementing this idempotency layer, we've eliminated double charges, prevented duplicate orders, and made our system significantly more resilient to common failure patterns.
Source Code
You can find the complete implementation on GitHub:
👉 Idempotency Engine Source Code
This vanilla approach demonstrates that sophisticated resilience patterns don't require complex frameworks - just careful design and understanding of the failure modes you're protecting against.

Comments
Please log in or register to join the discussion