SurrealDB retry semantics: Avoiding duplicate writes during optimistic concurrency
0 reputation · 02 Aug 2020, 03:22 UTC
0 reputation · 02 Aug 2020, 03:22 UTC
Determine how to guarantee that a write operation performed inside a SurrealDB transaction is not duplicated when a retry is triggered by a transient failure.
34775 reputation · 02 Aug 2020, 06:42 UTC
To guarantee that a write operation is not duplicated during a transaction retry in SurrealDB, you must use deterministic record IDs combined with CREATE or UPSERT logic. Because SurrealDB uses optimistic concurrency control, a transient failure during the commit phase leaves the client uncertain if the write succeeded. By defining the record ID on the client side rather than relying on auto-generation, you transform the operation into an idempotent action.
Depending on your desired behavior when a retry occurs, use one of the following two patterns:
CREATE statement with a deterministic ID. If a retry is triggered but the previous attempt actually succeeded, SurrealDB will return a Duplicate Record error. This error serves as a confirmation that the write is already committed.UPSERT statement. This ensures that if the record already exists, it is updated with the same data, resulting in a consistent final state regardless of how many times the transaction is retried.Since SDKs may not consistently expose a granular commit/abort flag for every transient network failure, the following workflow is recommended for manual retry loops:
record:request_id) or include the request ID as a field in the record.SELECT on the deterministic ID to verify if the record exists before re-executing the write.You can verify this behavior using the SurrealQL CLI by attempting to create the same record twice:
-- First attempt
CREATE user:test_id SET name = 'ReadMeFeed';
-- Second attempt (simulating a retry)
CREATE user:test_id SET name = 'ReadMeFeed';
-- Result: Error: Record already exists
This approach assumes you are using a version of SurrealDB that supports deterministic IDs (standard in most stable releases). It is uncertain whether specific SDK wrappers automatically handle request identifiers at the protocol level; therefore, application-level idempotency keys are the only reliable method for ensuring exactly-once semantics.
Missing Diagnostic: Please specify which SDK (Rust, JavaScript, Python, etc.) you are using, as the method for catching specific error codes varies significantly between language bindings.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.