Hi, I’ve created a JIRA issue to improve observability by logging when the Idempotency-Key header is missing:
FINERACT-2591 Happy to work on this if it aligns with the project direction. Thanks, Dishita On Thu, Apr 23, 2026 at 12:45 AM Dishita Suyal <[email protected]> wrote: > 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 >>> >>> >>>
