Introduction to Idempotent IDs
Idempotent IDs allow for a safe way to retry failed API requests without risk of causing duplication issues or other problems. Instead of processing the same request again, Idempotency IDs allow the server to simply cache the response of original request using the Idempotent ID as a key. If the original response fails to reach its destination due to a disruption occurring, the request can be sent again. Then, the server can use the ID to retrieve the cached response and send it back.
For example, say you were putting through a sale in Shopfront and after finalising it, you lose your connection to the internet. You now don't know whether the sale went through, or whether it was rejected. Therefore, once your connectivity is restored, you may put the exact same sale request through again. This time you receive a positive response back from Shopfront indicating that the order went through.
Because Shopfront makes use of Idempotency, the response that you receive back from the server will be the one that was originally lost. The server saw that the second request was identical to the first and instead of processing it again, sent back the first response. Although you technically made two sale requests, Shopfront was able to deduce that you only wanted to make one.
Shopfront supports the use of Idempotent IDs when querying with
GraphQL to ensure
that, if desired, duplicate requests are not actioned. This is more useful when working with Mutations,
as accidentally duplicating Queries carries little risk of causing issues due to a lack of actual
server-side data manipulation.
Some rules regarding our implementation:
- Shopfront requires each Idempotency ID to be unique within the vendor and application
- Shopfront will store the Idempotency ID in cache for up to 8 hours before it is discarded
- If another request with the same ID is made while the original is still being processed, Shopfront will wait for the original request to finish before sending responses back to both requests with identical data (processed from the original request)
To make use of this, an X-Idempotent-Id header needs to be added to the initial HTTP request, then if something
were to go wrong while receiving the response, the request can be made again with the same X-Idempotent-Id header
to receive the original response.
Each follow-up request made must be treated as if the original never reached the server. Therefore, the content of the request needs to be the exact same each time.
See an example of a simple GraphQL request made using the X-Idempotent-Id header:
POST /api/v2/graphql HTTP/1.1
Host: example.onshopfront.com
Authorization: Bearer 123abc
X-Idempotent-Id: [uniqueClientSideId]
Content-Type: application/json
Accept: application/json
{
"query": "{
categories {
id,
name
}
}"
}