Dishita - I think the documentation and client-side pieces are the way to go. In that case, the documentation at Fineract is only one side of the contract. That can be better documented and logged.
I think logging when a key is missing is a useful feature, provided it doesn't create additional overhead and can be "turned off" when other enforcement mechanisms are in place. On Wed, Apr 22, 2026 at 12:37 PM Dishita Suyal <[email protected]> wrote: > 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 >>>> >>>> >>>>
