Hi everyone, Thank you for raising and discussing this topic — it was very insightful.
>From my understanding, enforcing deterministic idempotency on the server side when the client does not provide a key could introduce risks, especially in financial workflows where identical payloads may still represent distinct business intents (e.g., multiple valid repayments within a short time window). It seems more aligned with the current architecture that idempotency remains a client-driven contract, with the server enforcing it only when an explicit key is provided. Would it make sense to instead focus on improving client-side guidance or safeguards (for example, better documentation or warnings when the key is missing), rather than introducing server-side fallback behavior? I’d appreciate your thoughts on this. Regards, Dishita On Fri, Apr 17, 2026 at 5:30 PM Mohammed Saifulhuq < [email protected]> wrote: > 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 >> >> >>
