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