Today I worked on the delete mutation for my Django inventory system.
The goal was to make the endpoint idempotent:
DELETE /items/<id>/
If the item exists → remove it
If it doesn’t exist → no change
Always safe to retry
The bug
The delete wasn’t actually changing state.
I was calling:
python
Item.objects.filter(item_id).delete()
instead of:
python
Item.objects.filter(id=item_id).delete()
Because the query wasn’t filtering on the correct field, the state transition wasn’t happening. The endpoint looked like it worked, but the underlying state wasn’t being modified correctly.
The fix
Using:
python
Item.objects.filter(id=item_id).delete()
inside a transaction made the delete naturally idempotent:
- existing item → removed
- missing item → no-op
- safe under retries
No extra conditional logic needed.
System takeaway
Idempotence often comes from how you shape the query and state transition, not from adding more control flow.
Designing the delete this way keeps the service:
- stateless
- retry-safe
- predictable
Next step
Next feature is atomic quantity updates:
- invariant enforcement
- transaction boundaries
- avoiding lost updates
Building one feature per day and focusing on correctness first.
Top comments (0)