Reference guide · http-status · Published 2026-08-16 · 3 min read
HTTP 409 conflict
HTTP 409 conflict meaning for concurrent writes and versioned APIs, with conditional request patterns and the right client response.
- ·What 409 means
- ·Common causes
- ·Resolving them
What 409 means
409 Conflict tells the client: I understood your request, but it cannot apply to the current state of the resource, because that state has changed underneath you, or your request changes it in a conflicting way. The clear case: your PUT /topics/123 references a version that someone else already modified. The server deliberately refuses on the spot rather than overwrite silently.
Distinguish: 400 is a malformed request; 404 is a missing resource; 412 is a preconditions failure of a conditional-request header. A 409 is the "your data and mine disagree about the current state" answer, and it is the standard signal from a concurrency guard.
Where it appears in practice
- Concurrent edits: two CMS-saving editors submit at once; the later one conflicts. The editor receives
409instead of silently clobbering the first save. - Versioned APIs:
PUTwith a staleIf-Matchor version id. The resource supports conditional updates; the client's copy is behind. - Unique-constraint collisions: creating an item whose slug or SKU already exists and the API resolves it as a conflict rather than a
400. - Document and wiki editors: same-document merge conflicts surface as 409.
- WordPress / plugin sync (occasionally): an API call conflicts with a newer revision.
The server side: what to return with it
If you control the API, return the conflict with:
ETagof the current server state, so the client canIf-Matchon the retry.- A
Locationor body that shows the current version (in a diff format the client can display). - A
Retry-Afterheader only when the conflict is expected to clear (e.g. a lock releasing). Do not send it for a data-level conflict that a wait does not fix; a user decision is required.
A helper pattern is to make the client send its version up front:
PUT /topics/42
If-Match: "v8"
The server compares the tag with its current v9, returns 409 Conflict when they differ, and the client knows it must re-fetch. This is the standard optimistic concurrency flow.
The client side: respond, do not retry-hammer
When you receive 409:
- Do not blindly retry the same request. The data is stale by definition; the same payload re-submits the same conflict.
- Re-fetch the current state (GET the resource), diff with what you meant to write, merge, and resubmit.
- Show the human a merge surface where two versions differ (which tabs, which fields) before overwriting. Autosave + 409 is the classic "someone else changed this, refresh to see it" path.
- Once the sync clears, resubmit with the fresh version and the conditional header.
Rules of thumb
- A 409 is a state signal, not a transport fault. Backoff/retry loops that blindly retry on 409 will pointlessly repeat the same conflict; the client must reconcile the state first.
- Where an API needs an explicit short-lived exclusive lock, a
423 Locked(WebDAV semantics) is a more honest answer than a global 409, but most web apps use optimistic concurrency with 409 instead. - On the CMS and hosting side,
409related to syncing plugin data is usually resolved by refreshing the source and re-running the operation after the plugin state re-synchronizes.
The status list puts 409 next to the other 4xx codes, and the retry-after article covers the header only where a timed retry truly applies.