AlgoMaster Logo

HTTP Methods and Idempotency

High Priority43 min readUpdated August 14, 2026
Listen to this chapter
Unlock Audio

The method at the beginning of an HTTP request is more than a verb-shaped label. It is a protocol contract that tells servers, clients, proxies, caches, crawlers, and retry systems what the request is intended to do.

For example, these two endpoints might invoke identical application code:

They are not equivalent HTTP designs. GET promises that the client is only asking to retrieve information. A crawler, browser prefetcher, or monitoring system can issue it without expecting a state change. POST makes no such promise.

Method semantics matter most when a request fails in an ambiguous way. If the server completed an operation but its response was lost, can the client send the request again? The answer depends on idempotency and on any application mechanism used to prevent duplicate effects.

This chapter explains the standard methods, the difference between safety and idempotency, and how backend systems use those properties to make retries reliable.

The Method Defines the Request's Intent

An HTTP method is a case-sensitive token at the start of the request:

Here, PUT tells the recipient how to interpret the target and content. Changing only the method can change the meaning of the entire request:

The URI identifies the resource. The method states what the client wants to do with that resource.

HTTP methods are extensible. A server can receive a syntactically valid method that it does not recognize, and a resource can reject a known method that it does not support. Intermediaries should not silently rewrite an unfamiliar method into a familiar one because doing so changes the request's semantics.

The method also communicates properties that infrastructure can use:

An endpoint should honor the semantics of its chosen method. A route name or documentation cannot repair a method whose protocol meaning contradicts its behavior.

Safety, Idempotency, and Cacheability Are Different

Three method properties are often confused.

Safety

A method is safe when its defined semantics are essentially read-only. The client does not request or expect a state change at the origin server.

Safe does not mean that the server performs no writes at all. A server can still:

  • Append to an access log
  • Update request metrics
  • Refresh an internal cache
  • Record an advertising impression

Those are incidental side effects, not the operation requested by the client. A GET /products/42 request remains safe even if the server records that the product was viewed.

The distinction matters because automated systems commonly issue safe requests. Crawlers follow links, browsers prefetch resources, health monitors poll endpoints, and caches revalidate stored responses.

This design is unsafe:

The query parameter does not override the method. To HTTP infrastructure, this is still a safe retrieval request. If following the URI deletes a user, an automated link checker could trigger the deletion.

Among the widely used standard methods, GET, HEAD, OPTIONS, and TRACE are safe. The standardized QUERY extension is also safe.

Idempotency

A method is idempotent when the intended effect of sending the same request multiple times is the same as sending it once.

The idea resembles this operation:

Applying the same assignment once or five times leaves the requested state identical:

Contrast it with:

Repeating that operation changes the result each time:

Idempotency concerns the intended effect, not whether the server executes code more than once. The server can log every request, record multiple audit entries, or return a different response on a repeat. Those incidental differences do not necessarily change the method's idempotent semantics.

Safe methods are idempotent because repeating a read-only request does not request an additional state change. PUT and DELETE are also idempotent even though they are unsafe.

POST, PATCH, and CONNECT are not defined as idempotent; their method semantics provide no repeat-safety guarantee. A particular endpoint can implement repeat-safe behavior for one of these methods, but a generic client cannot assume that it does.

Cacheability

Cacheability asks whether a response may be stored and later reused for another request. It is not the same as safety or idempotency.

An idempotent request can still need to reach the origin every time. Repeating DELETE is idempotent, but a cache cannot satisfy it using an earlier deletion response. Conversely, HTTP defines limited caching semantics for some POST responses even though POST is not generally idempotent.

The practical rule is:

Do not infer one property solely from another.

Standard Method Properties

The following table gives the protocol-level defaults. “No” under idempotent means not guaranteed by the method, not that an application is forbidden from making a particular operation repeat-safe.

MethodPrimary intentSafeIdempotentRequest content
GETRetrieve a current representationYesYesNo generally defined semantics
HEADRetrieve response metadata without response contentYesYesNo generally defined semantics
POSTAsk the target to process supplied contentNoNoExpected when the operation needs input
PUTCreate or replace the target's stateNoYesDefines the desired resource state
DELETERemove the target resource's current associationNoYesNo generally defined semantics
PATCHApply a patch document to the targetNoNoContains modification instructions
OPTIONSDescribe communication optionsYesYesAllowed, but no general use is defined
TRACEPerform a request-message loopback testYesYesForbidden
CONNECTEstablish a tunnel through a proxyNoNoNo request content
QUERYPerform a safe, idempotent query using request contentYesYesDefines the query

These properties describe standardized semantics. They do not guarantee that every server implements the method correctly.

Loading simulation...

GET: Retrieve a Representation

GET asks for a current representation of the target resource:

The resource does not need to be a database row or file. It might represent:

The server decides how to produce a representation of that resource.

GET is safe and idempotent. Issuing the same request twice can produce different response data because the resource may change between requests:

That does not violate idempotency. The requests did not ask the server to perform two state changes; they observed the resource at different times.

Request content on GET has no generally defined semantics. Although HTTP message framing can technically carry such content, some servers and intermediaries reject it, ignore it, or handle it inconsistently. Put ordinary retrieval parameters in the target URI, or use a method whose content has defined meaning for the resource.

Sensitive values deserve special care in a URI because URLs commonly appear in browser history, access logs, monitoring systems, and analytics. HTTPS encrypts a URL while it crosses the network, but it does not remove those endpoint-visible copies.

Most importantly, never use GET for an action the client intends to perform:

The issue is not naming style. It is the promise that automated retrieval is harmless.

HEAD: Retrieve Metadata Without Response Content

HEAD has the same semantics as GET, except that the server does not send response content:

The response fields should generally match those that a corresponding GET would produce. This lets a client inspect metadata such as content type, size, or modification information without transferring the representation itself.

HEAD is safe and idempotent.

It is useful for checking whether a resource is reachable or whether metadata has changed, but it is not automatically a complete application health check. A server can generate headers successfully even if a downstream dependency needed to produce the full content would fail.

Like GET, request content on HEAD has no generally defined semantics and should normally be omitted.

POST: Ask a Resource to Process Content

POST asks the target resource to process the request content according to that resource's own semantics.

It is the most flexible standard method:

The target might:

  • Create a subordinate resource and choose its URI
  • Submit a form
  • Start a background job
  • Append an event
  • Execute a domain command
  • Process a payment

POST is unsafe and not idempotent by default. Sending the order request twice might create two orders. Sending a payment request twice might charge the customer twice.

This does not mean every POST operation must produce duplicate effects. A search endpoint implemented with POST, for example, might be logically read-only and repeat-safe. The method itself still does not advertise those guarantees to generic HTTP components.

Choose POST when the target decides how to process the content or when the server chooses the URI of a newly created resource:

If the client already knows the exact target URI and is supplying its complete desired state, PUT usually expresses the intent more precisely.

PUT: Create or Replace a Known Resource

PUT asks the server to create or replace the state of the target resource with the state represented by the request content:

The client knows the target URI:

and provides the desired resulting state:

Repeating the identical request still asks for that same state:

This is why PUT is idempotent. It is not safe because it requests a state change.

The standard meaning is replacement, not “update whichever fields happen to be present.” If omitting active means “leave the old value unchanged,” the operation behaves like a partial modification rather than a representation replacement:

Calling every update PUT hides that distinction and can make clients disagree about whether omitted fields should be preserved, cleared, or reset to defaults.

Idempotency does not require identical responses. The first request might create the resource while a repeat merely confirms or replaces it. Both requests still produce the same intended target state.

Server-generated logs, revision records, and timestamps also require judgment. Recording that two attempts occurred is compatible with protocol idempotency. Designing PUT to “increment the profile version and send another welcome email on every call” destroys practical retry safety even if the requested profile fields end in the same state.

DELETE: Remove the Target Association

DELETE asks the origin server to remove the association between the target URI and its current functionality:

HTTP does not require the server to erase every underlying byte permanently. The server might archive a record, mark it inactive, release a mapping, or schedule cleanup. The observable intent is that the target no longer provides its previous functionality.

DELETE is unsafe because it requests a state change, but it is idempotent:

The responses can differ. The first request can report that deletion occurred, while the second reports that the target is already absent. Idempotency is about the requested final effect, not identical status codes or response bodies.

Request content on DELETE has no generally defined semantics. Some private APIs assign a meaning to it, but clients and intermediaries cannot assume portable support. Prefer putting the resource identity in the target and other conditions in defined request fields.

PATCH: Apply Partial Modification Instructions

PATCH asks the server to apply a patch document to the target resource:

Unlike PUT, the content describes a change rather than a complete replacement representation.

The server must interpret the document according to its media type. JSON Merge Patch, JSON Patch, a text diff, and a domain-specific change format can have very different behavior.

The directly affected changes must be applied atomically: either the complete patch succeeds or none of it is applied. Other clients must not observe a partially applied patch document.

PATCH is unsafe and is not defined as idempotent. Whether a particular patch is repeat-safe depends on the patch operation.

This merge-style assignment is naturally idempotent:

Repeating it keeps setting the same value.

This JSON Patch operation is not idempotent if it appends a new array member on every application:

Applying it twice can append "priority" twice.

A client therefore cannot decide that every PATCH is retryable merely because one API's patch format happens to use assignment operations.

Patch documents that depend on a known base version should use a condition such as If-Match with a strong entity tag:

If another request changes the resource first, the old condition no longer matches and the server refuses to apply the patch to an unexpected base. This prevents lost updates and can also stop a retry from applying the same version-specific change twice.

The condition does not magically make every patch operation idempotent. It makes the requested change conditional on a particular resource version.

OPTIONS, TRACE, and CONNECT

These methods are less visible in ordinary application code but serve important protocol roles.

OPTIONS

OPTIONS asks about communication options for a resource:

The server can describe supported methods or other capabilities. An asterisk target asks about the server in general:

OPTIONS is safe and idempotent. Browsers also use it for some cross-origin preflight requests, but OPTIONS is a general HTTP method rather than a feature exclusive to browser security.

TRACE

TRACE asks the final recipient to reflect the received request for diagnostic purposes. It is safe and idempotent by its defined semantics, and a client must not attach request content.

Because reflection can expose credentials or cookies, many production servers disable TRACE. “Safe” describes the client's requested resource effect; it does not mean that enabling every safe method is free of security risk.

CONNECT

CONNECT asks a proxy to establish a tunnel to an authority:

After a successful transition, bytes flow through the tunnel according to the protocol being carried rather than as an ordinary HTTP request body. HTTPS through a forward proxy is a common use.

CONNECT is neither safe nor idempotent. Repeating it requests another tunnel with new connection state.

QUERY: Safe Queries with Request Content

QUERY is a standardized extension for performing a server-side query whose input is carried in the request content:

It fills a semantic gap between two common designs:

The request content and its media type define the query. This is useful when the query is too large or structured to fit comfortably in a URI.

QUERY is different from the query component of a URL. A request can use the QUERY method with or without ?parameters in its target, just as other methods can.

Because QUERY is newer than the core methods, client libraries, frameworks, gateways, and caches might not support it yet. An API must verify its entire request path before depending on it. Falling back to POST for a read-only query can work, but any retry or safety guarantee then belongs to the API contract rather than to the standard semantics of POST.

Choosing Between POST, PUT, and PATCH

These three methods all commonly carry content, but they express different intent.

Use POST when the target resource decides how to process the content:

Use PUT when the client knows the target URI and supplies its complete desired state:

Use PATCH when the client supplies instructions for partially changing an existing target:

A useful starting decision is:

This is not a substitute for resource design. The important point is to make the method's standardized intent match the operation the client is requesting.

Why Network Failures Make Idempotency Essential

Suppose a client sends:

The server charges the payment method and commits the result. Before the response reaches the client, the connection fails.

From the client's perspective, these outcomes are indistinguishable:

This is the ambiguous outcome problem. A timeout says that the client did not obtain an answer in time; it does not prove that the server did nothing.

For an idempotent request such as a complete PUT, repeating the same request preserves the same intended state even if the first attempt succeeded. HTTP clients can use that property when recovering from a connection failure.

A client should not automatically retry a non-idempotent request unless at least one of the following is true:

  • It knows the operation is repeat-safe for that resource.
  • It can prove that the original request was not applied.
  • The API provides a reliable deduplication mechanism.
  • It can query or reconcile the operation's outcome before deciding.

Seeing no response bytes is not proof that the operation was not applied.

Idempotency Keys for Non-Idempotent Operations

Many APIs support an idempotency key for operations such as payment creation, order submission, or job scheduling:

Idempotency-Key is a widely used API convention, but it is not a universal guarantee built into core HTTP. The client can depend on it only when the API explicitly documents and implements its behavior.

The key identifies one logical operation across multiple transport attempts:

The method remains POST, and POST remains non-idempotent at the protocol level. The API adds application-level duplicate suppression for a documented scope and retention window.

Server-Side Processing

A robust server follows a flow similar to this:

  1. Scope the key to the authenticated caller and operation.
  2. Atomically reserve the key before performing the side effect.
  3. Associate the key with a fingerprint of the method, target, and relevant content.
  4. Execute the operation once.
  5. Durably store the resulting resource identity and response outcome.
  6. Return the stored outcome when the same logical request is retried.

If the same key appears with different request content, the server must reject the reuse. Silently returning the old result or executing the new operation would make the key ambiguous.

The reservation must be atomic. This implementation is unsafe:

Two concurrent requests can both observe that the key is absent and both execute the payment. A unique database constraint, transactional insert, or equivalent coordination mechanism must allow only one attempt to claim the key.

The hardest failure occurs if the business side effect commits but the idempotency record does not:

Reliable designs place the effect and deduplication state in one transaction when possible. When they span systems, the service needs a durable workflow, operation record, or reconciliation process that can recover the incomplete state.

Key Scope and Lifetime

An API must define:

Keys should have high entropy so one caller cannot guess another caller's keys. Server lookups must include the authenticated ownership scope to prevent data leakage across tenants.

A key does not provide deduplication forever. If the server retains keys for 24 hours and a client repeats the request after 25 hours, the operation might be treated as new. Clients need to know the retention policy.

Designing Naturally Idempotent APIs

Idempotency keys are useful, but a resource model can often make repeat safety natural.

Set State Instead of Applying a Relative Change

Prefer:

over an operation whose meaning depends on the current state:

Repeating “set enabled to true” preserves the desired state. Repeating “toggle” reverses it.

Use a Client-Chosen Stable Identifier

If the client has a stable identifier, it can target the same resource on every attempt:

A repeated request addresses the same import instead of asking the server to create another unknown resource each time.

The identifier must be scoped and authorized correctly. Allowing clients to choose resource names does not mean they can overwrite another caller's resource.

Enforce Business Uniqueness

A database constraint can express a business invariant:

Concurrent submissions with the same external order ID cannot create two orders, even if they reach different server instances.

The service must translate the uniqueness conflict into the documented existing outcome. Simply allowing a database exception to escape does not give the client a useful retry contract.

Track Operations as Resources

Long-running work can have a stable operation resource:

The first request establishes the desired operation. Repeats refer to the same operation, and clients can inspect its state after an ambiguous timeout.

This turns “did my request run?” into a resource lookup instead of a guess.

Idempotency Does Not Solve Every Retry Problem

Idempotency makes duplicate attempts safer, but it does not mean “retry immediately and forever.”

The failure must be retryable. Repeating a request cannot fix invalid authentication, malformed content, a violated business rule, or a permanently missing dependency.

Retries consume capacity. When a service is overloaded, aggressive retries can amplify the outage. Clients need attempt limits, time budgets, delay, and jitter.

The request must remain identical in meaning. Reusing an idempotency key after changing the amount, target, or operation is not a retry; it is a different request.

Credentials and conditions can expire. An idempotent method can fail on a later attempt because its authorization token expired or its resource-version condition no longer matches.

Concurrent actors can change the resource. Repeating PUT asks for the same target state, but another client might update the resource between attempts. Idempotency does not provide isolation from concurrent writes.

A response can legitimately change. A repeated DELETE can produce a different response after the resource becomes absent, while the intended deletion effect remains the same.

Downstream calls also need protection. Deduplicating an incoming request after an email, payment, or queue publication has already been repeated is too late. The protection must cover the actual business side effect.

Idempotency is one component of a retry policy, not the complete policy.

Delivery Guarantees in Practice

HTTP alone does not provide an exactly-once business-operation guarantee.

A client that never retries approximates at-most-once attempts:

This avoids deliberate duplicates but can lose operations when the request never arrives.

A client that retries until it receives an answer approximates at-least-once attempts:

This improves delivery but can execute a non-idempotent operation multiple times.

An effectively-once business outcome requires more:

Even then, the guarantee has a scope. It might mean “one charge per merchant and idempotency key for 24 hours,” not “this byte sequence can never have an effect twice anywhere.”

Precise API documentation should state that scope rather than promising exactly-once behavior without qualification.

Common Misunderstandings

Safe does not mean side-effect-free implementation. Logging and metrics can change, as long as the client did not request a resource state change.

Idempotent does not mean read-only. PUT and DELETE are unsafe because they change state, but repeating them has the same intended effect.

Idempotent does not mean identical response. Resource state, response metadata, and status can differ between attempts.

A route name does not change method semantics. GET /account?delete=true is still a safe request from HTTP's perspective and must not perform the deletion.

PUT is not automatically a partial update. Its standard intent is to create or replace the target's state with the supplied representation.

PATCH is not automatically idempotent. Assignment-style patches may be repeat-safe, while append or increment operations are not.

DELETE can be idempotent even when the second response reports absence. The requested final effect remains that the target association is gone.

A timeout does not mean failure at the server. The server may have committed the operation before the response was lost.

A non-idempotent method can have an idempotent endpoint contract. That guarantee must come from application knowledge or a deduplication mechanism; generic clients cannot infer it from POST or PATCH.

An idempotency key is not a magic client-only header. The server must reserve, validate, persist, scope, and expire keys correctly.

Deduplication stored after the side effect has a race. Concurrent attempts can both execute before either records the key.

Idempotency does not justify unlimited retries. Retry policies still need failure classification, backoff, jitter, attempt limits, and an overall time budget.

HTTP does not guarantee exactly-once business execution. Durable coordination around the actual side effect is required.

Summary

An HTTP method communicates intent and the guarantees infrastructure may use. Safe methods do not request state changes; idempotent methods have the same intended effect when repeated. Safety, idempotency, and cacheability are separate. GET, HEAD, OPTIONS, TRACE, and QUERY are safe and idempotent; PUT and DELETE are idempotent but unsafe; POST, PATCH, and CONNECT are not idempotent by default.

GET retrieves a representation, HEAD retrieves its metadata, POST delegates processing, PUT creates or replaces known target state, and PATCH applies modifications. An idempotent retry may return a different response while preserving the same intended effect.

Timeouts are ambiguous because work may finish before the response is lost. Retrying non-idempotent work therefore needs application knowledge, reconciliation, or durable duplicate suppression. Idempotency keys identify one logical operation only within a documented scope and lifetime; correct handling atomically reserves the key with the business effect. They do not replace backoff, retry budgets, concurrency control, or failure classification.

Match the standardized method to the operation, and define identity plus duplicate handling before automatically retrying non-idempotent work.

Quiz

HTTP Methods and Idempotency Quiz

5 quizzes