Hi Lukman, Adam, I completely agree with Adam's assessment. Enforcing server-side deterministic key generation based solely on payload introduces severe risks to core banking operations.
In microfinance, it is entirely valid for a client to submit two identical business intents in a short window (e.g., making two separate $50 loan repayments on the same day). If the server automatically generates a fallback key based on that payload, the Idempotency Filter will falsely flag the second legitimate payment as a duplicate and block it with a 409 Conflict. This corrupts the ledger. Idempotency must remain a strict client-server contract. The client owns the intent; the server enforces the lock. In the system-wide idempotency architecture mapped out for FINERACT-2169 / FINERACT-2485, this is handled explicitly to ensure zero regression: 1. The OncePerRequestFilter strictly targets the Idempotency-Key HTTP header. 2. If the header is missing, the filter bypasses the PostgreSQL lookup entirely ($O(1)$ exit) and allows the request to pass to the legacy command processing pipeline. 3. Payload canonicalization and hashing are used strictly for integrity verification (ensuring a client doesn't maliciously reuse the same key for a different payload), never for fallback key generation. The global configuration flag allows legacy clients to continue operating without keys, while modern clients can opt-in to the safe execution path. Regards, Mohammed Saifulhuq On Fri, Apr 17, 2026 at 3:53 PM Ádám Sághy <[email protected]> wrote: > Hi > > Thank you for raising this topic! > > In my understanding, if no idempotency key is provided, we should not > enforce idempotent behavior. > > While I understand where the fallback logic is coming from, I am hesitant > to go on that path: > > > - “Same payload” is not always the same business intent. > - shifts idempotency responsibility from the client contract to server > inference > - it can mean blocking a valid transaction > > > For these reasons, I am not sure we should enforce this as default > fallback. Maybe it is as an optional thing would be better? > > Regards, > Adam > > > On Apr 9, 2026, at 2:07 PM, elnafateh <[email protected]> wrote: > > Hi everyone, > > I would like to raise a discussion regarding idempotency handling in > Fineract, specifically when a client does not provide an idempotency key. > Problem > > Currently, if a client omits the idempotency key, the system may generate > a random UUID per request. In retry scenarios, this can lead to duplicate > processing of the same logical operation. > > A typical scenario: > > 1. > > Client sends a request (e.g., funds transfer) > 2. > > Server processes and commits successfully > 3. > > Client does not receive the response (e.g., network timeout) > 4. > > Client retries the same request without an idempotency key > 5. > > A new UUID is generated → request is treated as a new operation > > This can result in unintended duplicate transactions (e.g., double > spending). > Proposal > > Instead of generating a random UUID, generate a deterministic idempotency > key based on: > > - > > Request payload > - > > Relevant context (e.g., clientId, entityName,ActionName etc) > - > > Optional bounded time window > > This ensures that repeated identical requests map to the same idempotency > key, even when the client does not explicitly provide one. > Open Questions > > - > > Should the system enforce idempotency even when the client does not > provide a key? > - > > Is deterministic key generation an acceptable fallback strategy? > - > > Are there concerns around edge cases (e.g., payload variations, time > window constraints)? > > I would really appreciate feedback on whether this problem is valid in the > context of Fineract and if this approach aligns with the project’s design > principles. > > Thanks, > Lukman Fateh > > >
