The Detail You Probably Skipped: Idempotency
The hidden detail is called idempotency. In simple terms, an operation is idempotent if running it once has the same effect as running it ten times. Think of a light switch: flipping it on is not idempotent, because doing it again turns it off. But setting
a smart light to “blue” is idempotent; once it’s blue, telling it to be blue again changes nothing. In HTTP, some methods are designed to be idempotent, while others are not. The specification states that GET, PUT, and DELETE methods must be idempotent. Fetching data (GET), replacing a resource (PUT), or deleting a resource (DELETE) should have the same final result on the server, no matter how many times the exact same request is sent. The POST method, however, is explicitly not idempotent. This distinction is the crucial detail many engineers gloss over.
Why Is This So Often Overlooked?
This concept is often missed for a few key reasons. First, modern frameworks and libraries abstract away the raw HTTP requests, making it easy to just think in terms of "sending data" or "getting data." The underlying protocol rules feel academic. Second, in a perfect world where networks never fail and users never double-click, the difference is less apparent. A developer's local machine rarely simulates the chaos of real-world network conditions where requests can be lost or duplicated. Finally, the consequences aren't immediately obvious. An app can seem to work perfectly fine during development even if it uses HTTP methods incorrectly. The problem only reveals itself under stress, in production, when a customer gets charged twice for a single order.
Real-World Consequences of Getting It Wrong
Ignoring idempotency can lead to serious bugs. The classic example is the “double-click” problem on a payment form. If submitting a payment uses a non-idempotent POST request, a frantic double-click could send two separate requests, creating two separate charges. But the problem goes deeper. Distributed systems and unreliable mobile networks mean that clients, proxies, or load balancers might automatically retry a request if a response isn't received. If that retried request is a POST to create a new user account, you suddenly have duplicate accounts. If it's a POST that triggers a notification, the user gets spammed. An idempotent design prevents these issues. For example, using PUT to update a user's profile at a specific URL (`/users/123`) is safe to retry; the profile will just be updated with the same data again. Using DELETE on that same URL is also safe; after the first success, subsequent attempts will simply confirm the resource is gone.
How Understanding Idempotency Makes You a Better Engineer
Grasping idempotency moves you from simply using a tool to truly understanding it. It forces you to design more resilient and predictable APIs. When designing an API endpoint, you'll start asking the right questions: “Should this operation be repeatable? What happens if this request is sent twice?” This leads to better choices between PUT and POST. For actions that are inherently not idempotent, like creating a new resource with a server-generated ID, advanced engineers implement their own idempotency logic using unique request identifiers, often called an “idempotency key”. This is standard practice in high-stakes systems like payment gateways. By sending a unique key with each transaction, the server can recognize a retried request and safely send back the original response without processing the action a second time. This small detail is a hallmark of professional, robust system design.











