HTTP QUERY
vs GET vs
POST
The shortest useful mental model: QUERY lets you send a rich query in the request body, while still declaring “this operation is read-only and safe to retry.”
GET /products?color=blue uses the GET method plus a URI query
component. QUERY /products is a distinct HTTP method whose query instructions
normally live in the request body.
1. The three verbs in one screen
“Give me a representation of this resource.”
Query inputs are commonly encoded into the URL.
safe idempotent cache-friendly“Run this read-only query against this resource.”
Query instructions are carried in the request content/body.
safe idempotent cacheable“Process this content according to this resource's semantics.”
Can create, mutate, trigger, submit — or even query. The method itself does not promise read-only behavior.
potentially unsafe potentially non-idempotent2. Why QUERY exists
Great semantics for reads
but complex query data in the URI gets awkward
Great at carrying a body
but does not advertise “safe + retryable query”
Body-based query
+ explicit safe/idempotent semantics
| Property | GET | QUERY | POST |
|---|---|---|---|
|
Safe? Client does not request state change |
Yes | Yes | Potentially no |
|
Idempotent? Repeating has the same intended effect |
Yes | Yes | Potentially no |
| Request body semantics | No defined semantics | Expected; defines query | Expected; resource-specific |
| Where query input naturally goes | Usually URI | Request body | Request body |
| Can a QUERY response be cached for another QUERY? | — | Yes; body participates in cache key | No equivalent POST-to-POST reuse promised here |
3. Progressive example: product search
Small search → GET is ideal
You have only a few short filters. The URL is readable, shareable, bookmarkable and naturally identifies the request.
GET /products?category=book&maxPrice=30 HTTP/1.1
Host: shop.example
Use GET when the URI remains a sensible representation of the query.
The query grows → stuffing everything into the URI becomes unpleasant
GET /products?category=book&authors=...hundreds...&facets=...&ranking=...&filters=...
Host: shop.example
Long URIs face practical intermediary limits, encoding overhead and higher exposure in logs/history.
Traditional workaround → POST the query body
POST /products/search HTTP/1.1
Host: shop.example
Content-Type: application/json
{
"authors": ["A", "B", "..."],
"maxPrice": 30,
"facets": ["publisher", "year"]
}
But an HTTP intermediary sees POST. It cannot infer from the method
that this operation is read-only, safe to automatically retry, or meant to behave
like a query.
RFC 10008 → express the intent directly with QUERY
QUERY /products HTTP/1.1
Host: shop.example
Content-Type: application/json
Accept: application/json
{
"authors": ["A", "B", "..."],
"maxPrice": 30,
"facets": ["publisher", "year"]
}
But now the HTTP method itself declares the operation safe and idempotent. That semantic signal is available to generic HTTP infrastructure.
4. The retry difference
Connection drops before response arrives.
Generic client must be cautious: did the server already change something?
The method is idempotent, so automatic retry/restart is semantically allowed.
5. QUERY can graduate into GET
A server may give the query, or its result, a URI. That lets later traffic use normal GET semantics without resending the body.
QUERY /products
{ ...filters... }
HTTP/1.1 200 OK Location: /stored-queries/42The Location URI identifies an equivalent resource for the query.
GET /stored-queries/42
No need to resend the original query body.
Content-Location can identify a GET-able
resource corresponding to the particular result that was returned, while
Location can identify an equivalent resource that re-runs the same query
semantics.
6. What caching means
GET cache key
Traditionally starts from the request URI plus relevant request metadata.
GET /products?maxPrice=30
QUERY cache key
Must incorporate the request content and related metadata.
QUERY /products
{"maxPrice":30}
This makes QUERY caching more complex than GET caching, because a cache has to read the request body to distinguish queries.
7. One practical decision rule
Choose when your operation is retrieval and the query fits naturally in a URI.
Choose when you need a body to describe a potentially large/structured read-only query and want HTTP to know it is safe + idempotent.
Choose when the operation may create/change state, trigger non-idempotent processing, or when you intentionally need generic POST semantics.
8. Two implementation gotchas
Content-Type is mandatory for QUERY content. RFC 10008 requires the server to reject QUERY when Content-Type is missing or inconsistent with the body.
CORS requires preflight. QUERY is not a CORS-safelisted method, so browser cross-origin usage needs a preflight request.
Deployment support matters. Because QUERY is a newly standardized method, applications still need their server/framework/proxy/CDN chain to accept and correctly handle it.