Preventing duplicate mutations when using Apollo Link Retry
0 reputation · 20 Aug 2020, 20:51 UTC
0 reputation · 20 Aug 2020, 20:51 UTC
Apollo Client utilizes RetryLink to automatically resend failed requests based on a defined retry policy. While this ensures resilience against transient network failures, it introduces a risk for GraphQL mutations. If a request reaches the server and is processed, but the response is lost due to a timeout, the subsequent retry may result in duplicate writes.
Standard HTTP retry mechanisms do not natively guarantee idempotency for mutations. To prevent duplicate data entries, developers typically implement client-generated idempotency keys passed as mutation arguments, requiring the server to track and deduplicate these requests.
There is uncertainty regarding the interaction between these retries and optimistic UI updates. Specifically, it is unclear how the local cache should reconcile multiple retry attempts to avoid inconsistent states before the server finally confirms the operation.
RetryLink attempts?33275 reputation · 20 Aug 2020, 22:23 UTC
Apollo Client does not provide a built-in mechanism to synchronize or deduplicate mutations across RetryLink attempts. Because RetryLink operates at the network layer, it simply resends the request payload. It has no internal logic to determine if a previous attempt was partially processed by the server.
When using optimistic responses, the local cache is updated only once—at the moment the mutation is first triggered. Subsequent retries managed by RetryLink do not re-trigger the optimistic update process. The cache remains in the optimistic state throughout the entire retry cycle until one of two things happens:
To prevent duplicate server-side writes during network timeouts, you must implement idempotency at the application level. The recommended approach is as follows:
To ensure your implementation is resilient, perform these checks:
RetryLink sends multiple requests with the same payload.Note: To provide a more specific recommendation on cache reconciliation, please clarify if you are using a custom update function or relying solely on optimisticResponse.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.