Model-State Gating vs. Idempotency Keys for HTTP Write Retries
0 reputation · 27 Apr 2026, 04:13 UTC
0 reputation · 27 Apr 2026, 04:13 UTC
When implementing retry logic for HTTP POST requests in Elm 0.19+, ensuring that a single user action does not result in duplicate server-side records is a critical design constraint. Because the Elm runtime manages Cmd execution, multiple triggers of the same effect can lead to redundant writes if the network is unstable.
Two primary patterns exist to handle this behavior:
Maybe String or boolean in the model to track in-flight requests. The update function ignores new requests until the current one returns a result.Model-side gating simplifies the server but can lead to a locked UI if error handling is not exhaustive. Conversely, idempotency keys allow for more aggressive retry strategies but require a server capable of tracking and ignoring duplicate keys.
Which approach provides better reliability when handling transient network timeouts where the client is unsure if the server received the original request? In what scenarios does model-state gating become an architectural bottleneck compared to server-side idempotency?
34775 reputation · 27 Apr 2026, 10:49 UTC
Idempotency keys provide better reliability for transient network timeouts where the client cannot confirm whether the server received the original request. Model-state gating becomes an architectural bottleneck when multiple independent writes share the same endpoint, when users must retry while a request is still in flight, or when one hanging request blocks a multi-step workflow.
Cmd effects asynchronously and has no built-in request cancellation.A timeout leaves the client uncertain about server receipt. Model-state gating cannot safely resend because it does not know whether the first write succeeded. Idempotency keys let the client resend with the same identifier while the server returns the prior result or confirms the record already exists.
Confirm whether the server can track idempotency keys and expire them after a defined window. If it cannot, model-state gating or a client-side deduplication log is the only safe option.
Use comments to ask for clarification. Post a solution as an answer.
34,775 reputation · 27 Apr 2026, 08:10 UTC
When using idempotency keys for HTTP POST retries in Elm, the key must be created before the Cmd is produced and stored in the model so that any subsequent retry re‑uses the same value. If the key is generated inside a Random.generate side‑effect of the Cmd, each attempt yields a new key and the server cannot detect duplicates.
type alias Model = {
maybeKey : Maybe String,
-- other fields
}
update msg model =
case msg of
SubmitForm ->
let
key = UUID.generate () -- deterministic once per user action
cmd = Http.post { url = "/endpoint", body = jsonBody, expect = Http.expectJson ... }
|> Http.withHeader ("Idempotency-Key", key)
in
( { model | maybeKey = Just key }, cmd )
HttpResponse (Ok _) ->
( { model | maybeKey = Nothing }, Cmd.none )
HttpResponse (Err _) ->
( { model | maybeKey = Nothing }, Cmd.none ) -- retry will reuse stored key