Why GET and DELETE are idempotent?
The GET method does not modify data on the server. No matter how many times you request the same resource — the result will be the same.
Junior Level
GET — idempotent because it only reads
The GET method does not modify data on the server. No matter how many times you request the same resource — the result will be the same.
GET /users/1 → Returns user data
GET /users/1 → Returns the same data again
GET /users/1 → Returns the same data again
GET is called “safe” — it doesn’t modify the resource the client is accessing. GET may write to logs or update a view counter in Redis. This is acceptable! “Safe” in HTTP means “doesn’t affect the response the client receives”.
DELETE — idempotent because the result is the same
The first DELETE removes the resource. All subsequent DELETEs confirm that the resource is already gone. The final server state (“resource doesn’t exist”) doesn’t change.
DELETE /users/1 → 200 OK (resource deleted)
DELETE /users/1 → 404 Not Found (resource is already gone)
DELETE /users/1 → 404 Not Found (resource is still gone)
// Different response codes (200 vs 404) don't violate idempotency, because
// idempotency is about the resource state on the server, not what the client sees.
// The resource was deleted after the first call — subsequent calls change nothing.
After all calls, the server state is the same — the user is gone.
Middle Level
GET: Idempotency through Safety
According to RFC 9110, safe methods have no side effects that the client would expect.
Hidden changes: GET may write to logs or update a view counter in Redis. This is acceptable! Idempotency and safety concern resource responsibility. Technical side effects (logs, analytics, cache warming) don’t break the GET contract.
Risk: If you implement GET /user/1/delete, a browser may “pre-load” the link and accidentally delete the user. This is exactly why GET must be safe.
DELETE: Idempotency through Invariance
DELETE changes state, so it is not safe, but it is idempotent.
Mechanics:
- Request 1: Resource exists. Delete it. Code
200or204. - Request 2: Resource is gone. Try to delete. Code
404.
Key point: The final server state (“Resource is gone”) hasn’t changed after the second call.
Soft Delete
If DELETE sets a flag is_deleted = true and updates deleted_at — it remains idempotent. A repeat call just sets true again.
Performance
- DELETE results are not cached, but DELETE invalidates the cache for that URI
- For batch deletion, use
DELETE /resources?ids=1,2,3instead ofPOST /delete-multiple(the latter is not idempotent)
Diagnostics
- A large number of 404s on DELETE requests indicates aggressive client Retry policies
- When testing, always make two identical DELETE calls in a row
Senior Level
Deletion in Distributed Systems
In microservices, DELETE may trigger a chain of events (e.g., via Kafka).
Edge Case: The first DELETE removed the record and sent a UserDeleted event. A second DELETE (retry due to network lag) arrived later — the server must not send the UserDeleted event a second time, otherwise downstream services may fail.
Solution: Check resource existence before deletion and sending the event.
Caching DELETE
DELETE invalidates (purges) the cache for that URI on all intermediate nodes. This ensures the next GET doesn’t return stale data from the cache.
Batch Delete: POST /delete-multiple — not idempotent. For idempotency, use DELETE /resources?ids=1,2,3.
Idempotency and Distributed Events
When using queues (Kafka, RabbitMQ), DELETE must guarantee that the deletion event is sent only once, even on repeated calls.
GET: result is the same because nothing changes.
DELETE: result is the same because after the first call, there's nothing left to change.
Monitoring
- Track the number of 404 responses on DELETE requests
- High percentage of 404 on DELETE = aggressive client Retry policies
- When integrating with event-driven architecture, verify that repeated DELETE doesn’t generate duplicate events
Interview Cheat Sheet
Must know:
- GET is idempotent because it only reads — Safe method per RFC 9110
- GET may write to logs and cache — this is acceptable, “safety” concerns the response to the client
- DELETE is idempotent: after the first call the resource is gone, subsequent calls change nothing
- Different response codes (200 -> 404) don’t violate idempotency — server state matters
- DELETE invalidates the cache for that URI, so the next GET doesn’t return stale data
- Soft Delete (is_deleted = true) remains idempotent — repeat call just sets true again
- DELETE in distributed systems must not send a deletion event twice
Frequent follow-up questions:
- Why is GET /user/1/delete bad? — Browsers may pre-load GET links, which would accidentally delete the user
- How to ensure idempotent batch deletion? — DELETE /resources?ids=1,2,3, not POST /delete-multiple
- What if DELETE is called twice in an event-driven system? — The second call must not generate a duplicate event
- GET updates a view counter — does this violate idempotency? — No, technical side effects are acceptable
Red flags (DO NOT say):
- “DELETE is not idempotent because the second time it returns 404” — server state is the same
- “GET must be absolutely side-effect-free” — logs, analytics, cache warming are acceptable
- “POST is better for batch deletion” — DELETE with query parameters is idempotent, POST is not
- “Different response codes = different idempotency” — idempotency is about state, not response codes
Related topics:
- [[What is idempotency]]
- [[Which HTTP methods are idempotent]]
- [[Is POST idempotent]]
- [[What are the main HTTP methods used in REST]]
- [[What is RESTful API design]]