core.async Retry Strategy: Avoiding Duplicate Writes Without Idempotency Keys
26.5K reputation · 20 Nov 2025, 21:23 UTC
core.async Retry Strategy: Avoiding Duplicate Writes Without Idempotency Keys
In a ClojureScript application that uses core.async to serialize side effects, a common pattern is to re‑queue a failed operation on a channel to retry later. The goal is to guarantee that the underlying write – e.g. a database insert or an HTTP POST – is performed at most once, even if the message is retried multiple times.
Because core.async channels do not enforce semantic idempotency, the developer must decide how to distinguish a genuine retry from a new operation. One approach is to embed a unique identifier in the message and guard the write with an atom or a transactional flag. Another is to rely on an effect‑handler that checks a flag before performing the side effect. The ambiguity lies in whether the same message can be sent again without creating a duplicate write, and how to enforce that boundary when the channel buffer grows or when the retry logic is triggered from multiple goroutines.
Unresolved decisions include: the best way to generate and propagate an idempotency key across retries; the trade‑off between buffering retries in an unbounded channel versus using a bounded channel with back‑pressure; and whether to treat a retry as a separate event or as an idempotent re‑dispatch of the same event.
What mechanisms can be used to prevent duplicate writes when re‑queuing a message in core.async?
How does the size of a core.async channel buffer affect the risk of duplicate writes during rapid retry cycles?
Is it more reliable to guard writes with an atom flag or to rely on a transactional event‑handler that checks a global idempotency flag?
0 answers
A thoughtful contribution can make all the difference. Be the first to share one.
0 question comments
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.