How to prevent duplicate submissions for write interfaces, where should the idempotence key be placed in the request header or in the business field

How to prevent duplicate submissions for the writing interface depends on which layer you want to prevent. The idempotence description of the protocol layer is that 'one request and multiple identical requests have the same expected effect on the server', the official terminology page describes it as consistency of 'intended effect on the server'; the duplicate submission at the business layer also includes specific scenarios such as user double-clicking, task retry, and batch replay. Where to place the idempotence key in the request header or in the business field, the answer also follows the layering.

The protocol layer has classified the methods.

Method Does the protocol recognize idempotence? The meaning of falling on the content interface.
GET, HEAD, OPTIONS, TRACE Idempotent (a secure method) Repeated query of the same resource does not change the state
PUT Idempotent Use the same data to overwrite, and the repeated execution results are consistent
DELETE Idempotent May return 200 first, then return 404, and the effect will no longer stack
POST Does not guarantee idempotence Repeating execution of a new class operation will produce multiple records
PATCH Does not guarantee idempotence Incremental modifications repeated execution will accumulate

Two details are often misread. The first is that idempotence does not equal no side effects, the terminology page clearly states that the server may still record the arrival time of each request; the second is that the response can be different each time, the change in the return code of the delete operation is a typical example. Therefore, 'designing for idempotence' manages the final state, not the complete consistency of the response bytes.

Why do append-like operations need to be supplemented by yourself

Create articles, import archives, and such interfaces often use commit semantics, falling under the category of 'not guaranteed idempotent.' Client timeouts, queue replays, and manual duplicate clicks will turn the same intent into multiple records. There are two ways to compensate, with different scopes.

The first is a duplicate key. AnQiCMS provides a document content import interface /api/import/archive, which also supports querying whether it already exists by title, for batch import scenarios: the caller performs a query first before writing, skipping or updating if a match is found. This approach solves the problem of 'not repeating the same content twice', which depends on the identifiable fields of the content.

The second is an idempotent key. Generate a unique number for each business intent, and the server records the processing result according to this number. If a request with the same number is repeated, it directly returns the previous result. It solves the problem of 'do not execute the same action twice', even if there are slight differences in the data carried by the two requests, as long as the number is the same, it is processed once.

Where should the idempotent key be placed, in the request header or in the business field?

The benefit of placing the request header is that it is decoupled from business data: the field structure does not change, it can be carried as is during retries, and the server can block duplicate requests at the intermediate layer. It is also convenient to count by this key in the gateway and log. Common practice is to use a custom header and write the required conditions clearly in the interface document.

Place business fields suitable for another scenario: the caller is a client that cannot customize the request header, or the key itself belongs to part of the business record and needs to be stored and exported with the data. ZIP compressed packages and batch import of Excel tables are of this kind: batch numbers are written in the data, and when the import task is replayed, the results are recovered according to the batch number.

The decision can be made by three questions: can the caller consistently generate and carry this key; should the key be kept with the business data for a long time; can the server read it before writing to the database. When all three questions are met, it is cleaner to place it in the request header, and if any of the questions are not met, it falls into the field.

The interface documentation must clarify the boundaries

The public interface documentation must at least make clear four things: whether the interface accepts idempotent keys, the consequences of repeated calls by default, the priority relationship between title duplication checking and idempotent keys, and how the response body distinguishes between 'newly created', 'already existing and skipped', and 'replay returning the old result'.

The state flow also needs to be written clearly. AnQiCMS document status is divided into formal documents, drafts, pending release, and recycling bin. When the import interface is marked with a draft, the extra records caused by repeated calls will continue to affect the subsequent release queue. This kind of rework is harder to find than direct repeated entry. It is more effective to annotate the parameter meaning in the API call example than to add a sentence like 'Do not repeat submission' in the text.

Common questions

Is it enough to check for duplicates only by title?It is not enough when the title changes. Duplicate checking depends on the content field, and idempotent key depends on the intention; only by working together can both prevent repeated entry and repeated execution.

How long should the idempotent key be saved?Cover the retry window, usually taking the larger value between the longest execution time of the task and the queue backlog time, and providing the semantics after expiration.

How does the server store this key?Press the key to record the processing result and set an expiration, pay attention to the explicit handling of concurrent conflicts for the same key, and return identifiable duplicate prompts instead of a general failure report.