AlgoMaster Logo

Safety, Idempotency, and Cacheability

High Priority12 min readUpdated September 13, 2026
Listen to this chapter
Unlock Audio

When a request fails or a client or cache could reuse a response, clients need to decide what they can safely do next. Suppose a bookstore client loses its connection after submitting a request. Should it try again? Could a browser preload a link without changing anything? Could a cache serve a previous response? Each decision depends on a different property of the interaction.

Safety, idempotency, and cacheability describe these separate concerns. Understanding them helps clients automate requests without inventing assumptions about the API's behavior.

1. Three Independent Questions

Safety concerns the requested effect: does the client ask the server to change state? Idempotency concerns repetition: does making the same request multiple times have the same intended server-side effect as making it once? Cacheability concerns response reuse: may a cache store a response and use it to satisfy a later request under HTTP caching rules?

These properties apply at different points in an interaction:

Do not infer all three from one observation. Deleting a reading list changes state, yet repeating the deletion need not add another effect. Reading a private list requests no change, yet the service may prohibit caching its response.

Method definitions establish expectations about safety and idempotency. The server must implement behavior consistent with them. Cacheability also depends on the response status, headers, and the rules the particular cache follows.

2. Safety and Requested Effects

A safe method has essentially read-only semantics. The client does not request a state change through the operation. HTTP defines GET, HEAD, OPTIONS, and TRACE as safe methods.

For the bookstore, retrieving a book's title is safe. Reserving a copy is not: the caller asks the service to change availability. An operation's cost does not determine safety. An expensive catalog search can still be safe, while a tiny request that deletes a saved list is not.

Safety permits incidental server activity. A book lookup can produce an access log, update a performance metric, or populate an internal cache. Those effects support handling the read; the caller did not ask to place an order or reserve stock.

The distinction matters because browsers, crawlers, and link-preview tools can retrieve URLs automatically. A flawed API that cancels an order through GET /orders/order_731?cancel=true makes an ordinary retrieval destructive. The query parameter cannot change GET's semantics. The service should reject that use and expose cancellation through a suitable state-changing operation.

Likewise, a “download link” that consumes a benefit the customer may use only once needs careful design. If consuming that benefit is part of the requested operation, the API should not hide it inside an otherwise ordinary GET. Treat the business action and retrieval as explicit behaviors.

Safe does not mean publicly accessible, confidential, or immune to abuse. A private reading-list GET still needs access checks. A valid customer identity without permission to read the list can receive 403 Forbidden in an API that permits disclosing the list's existence. That rejection does not alter GET's safety classification.

3. Idempotency and Repeated Effects

Repeating an identical request to an idempotent operation has the same intended effect on the server as making it once. All safe methods are idempotent. PUT and DELETE are also idempotent, even though they request state changes.

Consider replacing reading-list settings at https://api.bookstore.example/reading-lists/list_731. Assume the list exists, the caller owns it, and its complete editable settings are name, visibility, and description:

The service applies the replacement and responds:

EXAMPLE_TOKEN is a nonfunctional credential placeholder. The examples use HTTP/1.1 over HTTPS, and each JSON body occupies one line without a trailing newline.

If the client repeats that exact PUT without an intervening edit, the settings still have the requested values. The service might log both attempts, but it should not create a second reading list simply because the request arrived twice.

Idempotency does not require identical responses. Suppose an owner deletes a list:

The first request succeeds:

This bookstore reports an already absent list as not found. Repeating the same DELETE returns:

Both requests leave the list absent. The first removes it, and the second reports that there is nothing left to remove. Different status codes do not make the operation non-idempotent.

Repeated GET responses can also differ because another customer changes inventory between requests. Idempotency describes the effect this client requests, not a promise that the world stops changing or that response bytes remain identical.

4. Retry Boundaries

Idempotency is useful when a client cannot tell whether a request completed. Suppose the server deletes the list but the client never receives the response:

Outcome unknownNo additional removal effectDELETE list_731Remove the listClient never receives 204Repeat identical DELETE404, list absentBookstore appReading-list APIBookstore appReading-list API
7 / 7
algomaster.io

Assume the service does not reuse the identifier and the caller's permissions remain unchanged. In this API, the second response confirms that the list is absent. It does not tell you whether the first request removed it or it was already absent for another reason.

POST and PATCH are not idempotent by their generic method semantics. A POST that creates a server-identified order can create another order when the client repeats it. The client must not assume that matching request bodies identify the same purchase attempt.

A particular PATCH operation can nevertheless have an idempotent effect. The bookstore could support these different changes:

Scroll
Documented operationFirst applicationIdentical repeat
Set list visibility to publicVisibility becomes publicVisibility stays public
Increase a cart item's quantity by oneQuantity rises from 2 to 3Quantity rises from 3 to 4
Append another occurrence to an ordered listAdds one occurrenceAdds another occurrence

These are illustrative operation semantics, not interchangeable patch formats. A client needs the patch format and API contract to know which behavior applies. A generic HTTP client cannot assume every PATCH sets fields to fixed values.

An API can also let clients safely repeat a POST by defining how it handles duplicates—for example, by supporting an idempotency key that identifies one logical submission. That is an additional service guarantee. Inventing a header on the client does not make the server enforce it.

Even an idempotent request does not justify unlimited retries. A PUT with an invalid visibility value will remain invalid when the client resends it unchanged. A rejected credential needs correction rather than rapid repetition. A later retry of an old PUT can also overwrite another editor's intervening change unless the API provides concurrency protection.

Idempotency limits duplicate intended effects. It does not guarantee exactly-once execution, eventual success, preserved permissions, or protection against conflicting edits.

5. Cacheability and Response Reuse

A cache stores responses for potential reuse. A private cache serves one user, such as a browser cache. A shared cache serves multiple users, such as a reverse proxy or content delivery network.

Cacheability is permission, not a promise that a cache will store a response or serve it again. Reuse also requires a matching request and a response the cache can still use under the applicable rules. A fresh response is one whose age remains within its permitted freshness lifetime. A stale response normally needs validation with the server unless a rule permits stale reuse.

Consider a public catalog representation containing only bibliographic information. Assume it is identical for all callers, needs no credentials, and can tolerate a short delay in showing editorial changes:

The service returns:

For this response, public allows shared caching and max-age=60 supplies a 60-second freshness lifetime. The lifetime concerns the response's age, not a fresh 60 seconds on every cache hit. The bookstore chose this policy for title and author data; it does not imply that a checkout price or stock reservation should tolerate the same delay.

Assuming an eligible matching request and no other restriction, a shared cache can handle the two reads as follows:

GET public book detailsForward cache miss200 with public freshness policyStore responseReturn book detailsMatching GET while freshReturn stored responseReader AShared cacheCatalog APIReader BReader AShared cacheCatalog APIReader B
7 / 7
algomaster.io

The second retrieval does not have to reach the catalog handler. An API must not depend on every GET causing business work at the origin server.

Now consider a separate, existing private list at https://api.bookstore.example/reading-lists/list_842. The service can allow an authorized GET while returning Cache-Control: no-store. The operation is safe and idempotent, but caches must not store that response. Private lists, personalized prices, and account-specific results need policies appropriate to their actual contents.

Three directives are easy to confuse. no-store prohibits storage. private prohibits shared-cache storage but can allow storage in a private cache. no-cache can allow storage but requires successful validation before reuse. Neither private nor no-cache is a synonym for no-store, and none replaces authorization or transport security.

Cache decisions cannot rely on GET alone. The status code, request and response directives, credentials, and representation selection all matter. A shared cache cannot reuse a response to a request containing Authorization unless the response explicitly permits that reuse under HTTP's rules. Do not add public to personalized data simply to make a cache accept it.

6. Method Property Matrix

The following table describes generic method semantics. The cacheability column concerns HTTP response caching, not whether application code can store arbitrary data internally.

Scroll
MethodSafeIdempotentResponse cacheability
GETYesYesCaching rules determine whether caches may store the response
HEADYesYesCaching rules determine whether caches may store the response
POSTNoNo generic guaranteeCaches may store responses under specific explicit conditions
PUTNoYesNot cacheable
PATCHNoNo generic guaranteeCaches may store responses under specific explicit conditions
DELETENoYesNot cacheable
OPTIONSYesYesNot cacheable
TRACEYesYesNot cacheable
CONNECTNoNo generic guaranteeNot cacheable

Safe methods are idempotent, but idempotent methods need not be safe. OPTIONS is an example of a safe method whose responses are not cacheable. A GET response with no-store is another reminder that retrieval does not guarantee cache storage.

POST and PATCH response caching are narrow cases rather than the usual deployment behavior. Their specifications require explicit freshness information and a Content-Location matching the request target for this reuse. The stored representation can satisfy eligible later GET or HEAD requests; it cannot replace sending another POST or PATCH to the server. General caching restrictions still apply, and implementations might not support storing these responses.

Content-Location identifies the resource the response body represents. It is different from Location, which a creation response can use to identify a newly created resource. Merely adding a freshness directive to an order-creation response is not enough to establish these special caching conditions.

For everyday API work, start with GET and HEAD as the normal HTTP caching paths. Add specialized behavior only when the contract and deployed caches support it.

7. Contract and Implementation Alignment

These properties must hold in the running service. Calling an operation PUT does not make an implementation that appends another item on every request idempotent. Calling an operation GET does not make hidden order cancellation safe. Adding caching headers does not make a personalized response suitable for every caller.

For the bookstore, you can state the intended contracts concretely: reading book details does not reserve a copy, repeating a settings replacement establishes the same requested settings, and caches may reuse public bibliographic responses within a short freshness lifetime. Those promises are specific enough to check against the implementation.

Keep client behavior equally explicit. Before preloading a request, consider its requested effect. Before repeating an uncertain submission, establish whether duplicates add business effects. Before reusing a response, check whether the stored representation is eligible for that caller and request. Each decision uses a different property.

Summary

Safety means the client does not request a state change. Idempotency means identical repetitions have the same intended effect as one request, even when responses differ. Cacheability means a cache may store and reuse a response under the relevant rules.

These properties support automatic retrieval, recovery from uncertain outcomes, and reduced network work. They do not replace permissions, validation, concurrency controls, or explicit cache policies. Align the method, API contract, and implementation so clients can rely on the behavior each property promises.