Protocol Deep Dives

RFC 7231/9110: HTTP Method Semantics — Safe, Idempotent, and Cacheable

Deep dive into HTTP method properties defined by the RFC — safety, idempotency, cacheability, and what they mean for API design and intermediaries.

Method Properties — The RFC Definitions

HTTP methods are not just arbitrary verbs. RFC 7231 (obsoleted by RFC 9110 in 2022) defines three formal properties that methods can have. These properties determine how browsers, caches, proxies, and load balancers may treat a request without needing to understand the application semantics.

Safe Methods

A method is safe if it is essentially read-only — the client does not request or expect any state change on the server. The server *may* have side effects (logging, analytics) but these are not the client's concern.

Safe methods: GET, HEAD, OPTIONS, TRACE

Safety matters because:

  • Browsers can prefetch safe requests without asking user permission
  • Web crawlers can follow safe links automatically
  • Users can bookmark and re-request safe URLs without concern
  • Caches can serve safe responses without forwarding to the origin

Idempotent Methods

A method is idempotent if making the same request N times has the same effect as making it once. The responses may differ (the server might return a different timestamp each time), but the *state change* is identical.

Idempotent methods: GET, HEAD, OPTIONS, TRACE, PUT, DELETE

Note: all safe methods are also idempotent, but not all idempotent methods are safe. PUT and DELETE change state — they are just *predictably repeatable*.

Idempotency matters because:

  • Load balancers can retry timed-out idempotent requests automatically
  • Clients can safely retry on network failure without risk of duplication
  • API clients can implement at-least-once delivery safely

Cacheable Methods

A method is cacheable if responses to it may be stored and reused for future equivalent requests, subject to cache-control directives.

Cacheable methods: GET, HEAD, POST (when explicitly marked cacheable)

The Properties Table

MethodSafeIdempotentCacheable
GETYesYesYes
HEADYesYesYes
POSTNo**No**Only if response includes explicit freshness
PUTNoYesNo
DELETENoYesNo
PATCHNoNoNo
OPTIONSYesYesNo
TRACEYesYesNo
CONNECTNoNoNo

GET and HEAD — Retrieval Semantics

GET — The Primary Retrieval Method

GET retrieves a representation of the target resource. The request must not include a message body (though RFC 9110 no longer prohibits it, all mainstream frameworks ignore GET bodies). All query parameters travel in the URL:

GET /api/users?page=2&limit=50&sort=created_at HTTP/1.1
Host: api.example.com
Accept: application/json
If-None-Match: "etag-abc123"
If-Modified-Since: Mon, 01 Jan 2024 00:00:00 GMT

Conditional GET: The If-None-Match and If-Modified-Since headers make a GET conditional. If the resource has not changed, the server returns 304 Not Modified with no body — saving bandwidth while validating freshness.

Partial GET: The Range header requests a byte range for resumable downloads and video streaming:

GET /video/large-file.mp4 HTTP/1.1
Range: bytes=1048576-2097151   ← request bytes 1MB–2MB

HTTP/1.1 206 Partial Content
Content-Range: bytes 1048576-2097151/15728640
Content-Length: 1048576

HEAD — Metadata Without Body

HEAD is identical to GET but the server must not send a response body. It is used to:

  • Check if a resource exists without downloading it
  • Get Content-Length to pre-allocate a download buffer
  • Validate a cached response by checking ETag or Last-Modified
# Check if a large file exists and get its size:
curl -I https://example.com/large-dataset.csv
# HTTP/1.1 200 OK
# Content-Length: 524288000
# Last-Modified: Fri, 10 Jan 2025 12:00:00 GMT

POST vs PUT vs PATCH

POST — Non-Idempotent Creation and Actions

POST submits data to the server. The server determines what to do with it — create a resource, process a command, or append to a collection:

POST /api/orders HTTP/1.1
Content-Type: application/json

{"product_id": 42, "quantity": 3}

HTTP/1.1 201 Created
Location: /api/orders/7891

POST is not idempotent. Sending the same POST twice creates two orders. This is correct behavior — a double-click should not double-charge a customer. Clients must implement idempotency keys if they need safe retry:

POST /api/orders HTTP/1.1
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000

The server stores the key and returns the same response for duplicate requests with the same key — a pattern used by Stripe, PayPal, and most payment APIs.

PUT — Full Replacement

PUT replaces the target resource with the request body. The client supplies the complete new representation. If the resource does not exist, PUT creates it (returning 201); if it exists, PUT replaces it (returning 200 or 204):

PUT /api/users/42 HTTP/1.1
Content-Type: application/json

{"id": 42, "name": "Alice Smith", "email": "[email protected]", "role": "admin"}

HTTP/1.1 200 OK

PUT is idempotent — sending the same request twice leaves the resource in the same state. This makes PUT safe to retry on network timeout.

The PUT trap: PUT requires sending the *complete* resource representation. If you PUT only {"name": "Alice"} to a user resource, the server is supposed to replace the entire user with just a name — losing email, role, etc. Many APIs violate this and treat PUT as PATCH semantics. Use PATCH when you want partial updates.

PATCH — Partial Update

PATCH (RFC 5789, 2010) applies a partial modification to a resource. The request body is a patch document — a set of instructions describing the change:

PATCH /api/users/42 HTTP/1.1
Content-Type: application/merge-patch+json   ← RFC 7396

{"name": "Alice Smith"}   ← only update name, leave everything else

---

PATCH /api/documents/1 HTTP/1.1
Content-Type: application/json-patch+json   ← RFC 6902

[{"op": "replace", "path": "/title", "value": "New Title"},
 {"op": "add", "path": "/tags/-", "value": "python"}]

Two patch formats dominate:

  • JSON Merge Patch (RFC 7396): Simple — send only the fields to change. Null values delete fields. Cannot append to arrays.
  • JSON Patch (RFC 6902): Expressive — add, remove, replace, move, copy, test operations with JSON Pointer paths. Supports conditional patching.

PATCH is neither safe nor idempotent by the RFC definition (though idempotent PATCH implementations are possible and common). Clients should treat PATCH retries carefully.

DELETE and OPTIONS

DELETE — Resource Removal

DELETE requests removal of the target resource. A successful DELETE returns:

  • 200 OK with a body describing the deletion
  • 204 No Content with no body (most common)
  • 202 Accepted if deletion is asynchronous
DELETE /api/users/42 HTTP/1.1
Authorization: Bearer eyJ...

HTTP/1.1 204 No Content

DELETE is idempotent: deleting an already-deleted resource should return 404 Not Found (or 204 — opinions vary), not an error that breaks retry logic.

OPTIONS — Capability Discovery and CORS Preflight

OPTIONS describes the communication options for the target resource. It is used in two contexts:

1. CORS Preflight — Before a cross-origin request with custom headers, the browser sends an OPTIONS preflight to check permissions:

OPTIONS /api/users HTTP/1.1
Origin: https://app.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type, Authorization

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400

2. API Discovery — Servers may return an Allow header listing methods:

OPTIONS /api/users/42 HTTP/1.1

HTTP/1.1 200 OK
Allow: GET, PUT, PATCH, DELETE

Method Registration — IANA and WebDAV

The IANA Method Registry

HTTP methods are registered with IANA at https://www.iana.org/assignments/http-methods/. Anyone can register a new method by submitting an RFC or a specification. The registry prevents conflicts between separately developed protocol extensions.

WebDAV Methods

Web Distributed Authoring and Versioning (RFC 4918) added methods for filesystem-like operations over HTTP:

PROPFIND   Retrieve properties of a resource (XML response)
PROPPATCH  Change properties of a resource
MKCOL      Create a collection (directory)
COPY       Copy a resource to a new URL
MOVE       Move a resource to a new URL
LOCK       Lock a resource against concurrent modification
UNLOCK     Release a lock

WebDAV powers macOS's Finder network folders and many CMS backends. It extends HTTP into a full filesystem protocol without changing the transport.

Custom Methods — Discouraged

RFC 9110 explicitly discourages defining custom HTTP methods. Instead:

  • Use a standard method + differentiate by URL (POST /actions/approve)
  • Use a request body field to specify the operation
  • Use a custom header if semantics are truly unique

Custom methods break caches, proxies, and security tools that only understand the standard method vocabulary. The few legitimate custom methods (PATCH, SEARCH, REPORT from WebDAV) required years of standardization to gain broad support — that is the correct bar for a new method.

Related Protocols

Related Glossary Terms

More in Protocol Deep Dives