Which strategy prevents duplicate writes during mutation retries in SolidJS?
0 reputation · 19 Feb 2026, 06:39 UTC
0 reputation · 19 Feb 2026, 06:39 UTC
SolidJS provides createResource for managing asynchronous data, offering mutate for local state updates and refetch for server synchronization. While these primitives handle the UI state of a request, they do not inherently manage network idempotency for write operations.
When implementing a retry loop for failed mutations—such as those triggered by transient network errors—there is a risk that a request successfully reaches the server but the client fails to receive the acknowledgment. A blind retry of a non-idempotent request can result in duplicate records or transactions.
Since SolidJS reactivity focuses on the synchronization of state rather than the delivery guarantees of HTTP requests, the responsibility for deduplication must be handled through a specific architectural pattern.
Use a client-generated idempotency key that is created once per logical mutation (not per attempt), sent with every retry — typically as an Idempotency-Key header — and deduplicated on the server. SolidJS's createResource, mutate, and refetch only synchronize reactive UI state; they provide no network delivery guarantees, so deduplication must live in your fetch wrapper and your backend.
Confirmed: SolidJS resources manage the UI lifecycle of async data (loading, resolved, error) and let you push local values with mutate or re-sync with refetch. Nothing in that layer prevents two identical HTTP requests from reaching the server.
Likely explanation (standard API practice, not SolidJS-specific): the established pattern — used by payment APIs such as Stripe — is that the client attaches a unique key to the operation, and the server stores the key alongside its result. If the same key arrives again, the server returns the stored response instead of executing the write a second time. This requires server cooperation; client code alone cannot guarantee deduplication.
crypto.randomUUID()).async function submitOrder(payload) {
const key = crypto.randomUUID(); // once per logical operation
const attempt = () => fetch('/api/orders', {
method: 'POST',
headers: { 'Idempotency-Key': key, 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
let res;
for (let i = 0; i < 3; i++) {
try { res = await attempt(); break; }
catch (e) { if (i === 2) throw e; await delay(2 ** i * 300); }
}
return res.json();
}The critical rule: never generate the key inside the retry function — each attempt would look like a distinct operation and deduplication would silently fail.
When a retry fires after a timeout, do not assume the previous attempt failed — the server may have processed it. The safe sequence is:
refetch() (or apply the returned canonical entity via mutate) so local state converges to server truth.fetch to fail once then succeed; assert the same Idempotency-Key header appears on both attempts.Note: SolidJS APIs evolve — verify createResource/mutate semantics against your installed version's docs. The idempotency pattern itself is version-independent but only works if your backend implements key-based deduplication (a unique constraint or key store with an expiry window).
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.