Hi Mohammed, James, Thank you for the detailed feedback — this was very helpful.
I understand that the check should be placed at the OncePerRequestFilter boundary to keep it lightweight and avoid impacting deeper layers. I’ll explore implementing the missing-key logging at the HTTP filter level, and ensure it is tied to the global idempotency configuration and uses an appropriate log level. I’d be happy to coordinate further to align with the existing architecture before opening the PR. Thanks again for the guidance. Regards, Dishita On Thu, Apr 23, 2026 at 11:54 AM Mohammed Saifulhuq < [email protected]> wrote: > Hi Dishita, James, > > Great initiative on FINERACT-2591. > > To address James’s concern regarding performance overhead: standard I/O > logging operations on the critical path can easily become bottlenecks under > high concurrency. To keep this strictly $O(1)$ and lightweight, we should > execute this missing-key check at the absolute edge of the HTTP stack. > > By placing this logging logic inside the OncePerRequestFilter boundary > (mapped out in FINERACT-2485 > <https://issues.apache.org/jira/browse/FINERACT-2485>) rather than deeper > in the Spring routing layer, we avoid consuming heavy Tomcat threads for > malformed requests. Wrapping it in a conditional log.debug tied to the > global idempotency toggle will guarantee zero performance penalty when > disabled. > > Dishita, I am happy to coordinate with you on the filter boundary once the > GSoC coding period opens so your PR drops in seamlessly. > > Regards, > > Mohammed Saifulhuq > > On Thu, Apr 23, 2026 at 8:40 AM James Dailey <[email protected]> wrote: > >> 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 >>>>>> >>>>>> >>>>>>
