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

Reply via email to