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 >>>>> >>>>> >>>>>
