For nearly thirty years, the Web has lived with a semantic paradox that anyone developing for the backend knows well: how do you execute a complex, voluminous query, or one containing sensitive data, if the only “safe” method available does not allow a request body?
Think about when we need to send a structured search query with nested filters, sorting, and multidimensional pagination. Or maybe a SQL query, a JSONPath expression, or a GraphQL document.
The naive developer’s first thought is: I will just add a “q” parameter to the URI and send it with GET, what could go wrong.
Then, over time, the parameters grow to 10, 100, 1000, and the application implodes. This happens because the proxy crossing the firewall, caching data in Redis, and load balancing has a 2048-character limit for the URI. Or it happens because the firewall logs the URI in plaintext and sends it to a SIEM, exposing sensitive data such as search filters or credentials.
Stuffing all of this into a URI using the classic GET method exposes us to physical transport limits and serious security risks.
What do those who want a minimum of security do instead? They only use POST requests: everything remains hidden in the request body, and it doesn’t matter if we destroy semantics, prevent caching, or drive our systems professor to despair—the important thing is that security is safe.
I worked on a project based on this exact logic: crude, but effective.
RFC 10008, published by the IETF in June 2026 and classified as a Proposed Standard, finally resolves this dilemma by introducing the QUERY method. Let’s try to understand if it is worth it or if it has arrived too late on our desks. One thing is the standard, another is its adoption, which will take years. It involves updating languages, frameworks, libraries, proxies, load balancers, CDNs, WAFs, and browsers.
This new verb combines the semantic guarantee of safety and idempotency (typical of GET) with the structural capability to carry an extended payload in the request body (typical of POST).
In this article, we will explore the genesis of the QUERY method, how it works under the hood, its implications for caching and security, and how we can implement it today in our backends (or at least in the future, when the ecosystem stops rejecting the request with a depressing HTTP/1.0 405 Method Not Allowed).
QUERY carries the query in the request body, overcoming the limitations of GET, but with a safety semantic that POST cannot guarantee.Code language: JavaScript (javascript)
The genesis of a standard: AUTH48 and the role of the IETF
The QUERY method was not born overnight. It is the result of the work of the IETF’s HTTPbis working group, authored by well-known protocol engineering names like Julian Reschke (greenbytes), James M. Snell (Cloudflare), and Mike Bishop (Akamai).
An interesting detail concerns the final review stage of the standard, known as “AUTH48”. For the first time, the RFC Production Center (RPC) used a pilot project based on GitHub repositories instead of the traditional and slow email flows (https://github.com/rfc-editor-drafts/FinalReview-rfc10008).

This allowed for granular traceability of editorial changes, accelerating the release of a standard that promises to change the rules of the game.
The problem: physical and semantic limits of GET and POST
To appreciate the value of QUERY, we must look closely at the limitations that have plagued us for decades.
GET limits: between too long URIs and logs in plaintext
With GET, the query lives entirely in the URI. Even though RFC 9110 recommends that infrastructure support URIs of at least 8000 octets, in reality, we clash with uncoordinated firewalls, load balancers, and CDNs that apply lower and variable limits. Anyone working in the enterprise space knows well that 2048 characters is a common limit, while some older proxies stop at 1024.
Exceeding these limits generates errors like “414 URI Too Long”, which are always hard to diagnose, especially when the issue only manifests in production environments under real traffic.
Then there is a critical privacy issue: URIs are logged in plaintext in server logs. A simple search using grep can extract a vast amount of sensitive data with minimal effort.
I still remember when, during one of my first log security audits for a major national telecommunications operator, I literally jumped in my chair: looking at them, I realized that all logins for a certain application were happening in GET instead of POST. The passwords of thousands of users were right there, written in plaintext in the web server’s text files.
Besides, even though the phenomenon is much more mitigated than in the past, “Referer” headers to third-party sites can carry data that should have remained segregated in the origin server.
For these reasons, GET has an original sin: it is not suitable for carrying sensitive data, yet it is the only safe and idempotent method available.
Finally, caching these requests is inefficient. Any syntactic variation in parameter order or character encoding invalidates the cache, turning semantically identical queries into distinct resources.
The fallback to POST: the loss of the semantic contract
To bypass the limits of GET, the common practice has been to abuse POST, moving the query to the body: a simple approach, but with significant semantic consequences.
This way, we no longer have space issues in the URI and logs remain clean (it is true that body logging can be enabled, but it is not active by default), but the mechanism breaks the protocol’s guarantees. The POST method is neither safe nor idempotent by definition.

Consequently, intermediaries involved in transporting a POST request, not knowing whether it is reading data or modifying a database, avoid resending the data (as browsers do) or caching it (as CDNs do).
WebDAV precursors and why to avoid SEARCH or REPORT
Those with more experience or a few gray hairs will surely remember the attempts made with WebDAV and methods like “SEARCH” or “PROPFIND”. Some still think WebDAV is a perfect solution, but perhaps they should reconsider after this specification and how it deliberately ignored WebDAV methods to create a completely new one.
However, it was decided not to recycle those methods, which were closely tied to the “application/xml” Content-Type, but to start from scratch.
QUERY was born agnostic, not tied to a specific format, so that those who use it can independently manage their “Content-Type”.
We are therefore taking the positive aspects of GET: safety, idempotency, and caching, and adding the POST request body.
Content negotiation and error codes
Reasoning with the “Content-Type”, the first constraints begin to appear: if a client requests an “application/xml” format and the server has a different content, the request is rejected. The same happens if the client does not explicitly indicate this data.
The standard rigorously defines this step within section “2.1 Media Types and Content Negotiation”:
- 400 Bad Request: if the media type is absent or malformed.
- 415 Unsupported Media Type: if the query format is not supported by the endpoint.
- 406 Not Acceptable: if the format requested in “Accept” is not available.
- 422 Unprocessable Content: if the query is syntactically valid but logically unprocessable (e.g., refers to a non-existent table or field).
Discovery and the Accept-Query header
How does a client know which query formats are accepted by an endpoint? RFC 10008 introduces the “Accept-Query” response header.
This header adopts the “Structured Fields” specifications (RFC 9651). Being a formatted list of tokens, it allows client parsing in a standard way, without complex regexes:
Accept-Query: "application/jsonpath", "application/sql"Code language: JavaScript (javascript)
A client can discover the server’s capabilities in two ways:
- Preventive: sends an “OPTIONS” or “HEAD” request and reads the “Allow” (which includes QUERY) and “Accept-Query” headers.
- Aggressive: sends a “QUERY” request directly. If the server does not support that format, it responds with “415 Unsupported Media Type” and includes “Accept-Query” to indicate the allowed formats.
Clearly, if there is a possibility to negotiate the format, this approach is better because it avoids additional round-trips, but it is not always possible.
The concept of “equivalent resource”
To respect the Web principle that every resource must have a URI, the RFC introduces the “equivalent resource”: a conceptual resource (accessible via GET) representing the result of a specific QUERY request plus its metadata.
The server can materialize this resource by providing two distinct headers in the response:
- Location: points to the live and repeatable query. The client can perform a “GET” to this URI to repeat the query and obtain updated data. This URI can be temporary: if it expires, the client simply goes back to sending the complete “QUERY” request.
- Content-Location: identifies a static and historical snapshot of the results at that precise moment.
Redirect management and conditional requests
Unlike POST, where “301” or “302” redirects often led browsers to transform the request into a “GET” (losing the body), with QUERY, the client must maintain the same method and body towards the new URI for codes “301”, “302”, “307”, and “308”.
Only the “303 See Other” code forces a transition to GET. This is useful for highly resource-intensive asynchronous queries: the server responds immediately with “303” and a “Location” header, telling the client to retrieve the ready result via a subsequent “GET”.

For conditional requests, the client can send headers like “If-Modified-Since” based on previously received timestamps. If the underlying data has not changed, the server responds with a lightweight “304 Not Modified”, saving precious bandwidth.
Edge network engineering: body-based caching
The most challenging part of QUERY is definitely cache management. For current reverse proxies or CDNs, which are used to caching based only on the header, it means introducing mechanisms capable of also taking the request body into account.
This means the cache system must calculate a hash of the request body to identify repeated calls. Depending on the size of the payload, this operation can introduce a latency proportional to the sent data.
Normalization
Given the problems related to parameter order and cache inefficiency, the RFC specifies:
To improve cache efficiency, caches MAY first remove semantically insignificant differences from the request content and related metadataCode language: JavaScript (javascript)
This is an important aspect to improve cache efficiency, but it introduces a risk: if the proxy parser and the origin server parser normalize data differently, there is a risk of “Parser Differentials”—the cache might serve a false positive (data from one query for another).
If there is a chain of intermediate processes that risks leading to this drift, the expected header is:
Cache-Control: no-transformCode language: HTTP (http)
To be honest, the no-transform header represents the visceral fear of whoever designed this specification. They probably spent sleepless nights debugging cache mismatches in the most subtle ways possible and finally gave up, introducing a non-alterability parameter right inside a specification that theoretically declared its feasibility.
This header will end up being adopted in many real-world scenarios precisely to avoid any unpredictable misalignment between different parsers.

Security, privacy, and CORS preflight
Up to this point, it all seems great, but introducing a new HTTP method has important implications for security and privacy.
- WAF Blind Spots: many traditional Web Application Firewalls analyze the request body only for unsafe methods (POST, PUT, PATCH). Seeing a “safe” method like QUERY, they might skip deep inspection, allowing harmful payloads (SQL Injection, XSS) to reach the backend. Security teams must update WAFs and configure rules to closely monitor QUERY traffic.
- Anti-CSRF controls: if QUERY endpoints are poorly implemented and cause side effects on the database (for example, used as if they were POSTs), anti-CSRF middlewares might ignore them, assuming they are safe, exposing the application to vulnerabilities.
- CORS Preflight: QUERY is not a “safelisted” method in WHATWG’s Fetch specifications. Cross-origin requests will always require an “OPTIONS” preflight request, doubling the network round-trip. It is crucial to properly configure the “Access-Control-Max-Age” header to cache the preflight and avoid performance bottlenecks.
- Privacy advantages: by moving sensitive parameters from the URI to the opaque request body, QUERY prevents data leaks in server logs and browser histories, aligning perfectly with the GDPR data minimization principle.
The turning point for GraphQL and headless commerce
GraphQL has lived with a caching dilemma for years. Because its queries are too long for GET, they have historically been sent via POST, disabling edge caches. Engineers had to invent complex solutions like persisted queries to restore caching with GET.
With QUERY, GraphQL clients can send full queries by specifying “application/graphql”, increasing performance and reducing application complexity.
Backend support
- Node.js: the built-in C++ parser in recent Node branches (21.x and 22+) natively supports QUERY. Frameworks like Fastify allow explicit routing with the
{ hasBody: true }flag. - Go: the “net/http” package handles methods as strings, and the router introduced in Go 1.22 already supports QUERY routing out-of-the-box.
- OpenAPI 3.2+: officially supports the definition and documentation of the QUERY method.
And browsers?
Discussions at WHATWG (issue #12594) are defining support for <form method="query">. When this is implemented, we can finally update web search forms, saying goodbye to the annoying “confirm form resubmission” warning on page refresh.
A finally mature protocol?
The QUERY method is not a simple syntactic addition. It resolves a structural inconsistency we have carried since the dawn of the Web.
By restoring semantic dignity to complex reads, it allows us to build cleaner, safer, and more efficient APIs, freeing us from the obligation to trade cache scalability for privacy and transport space.
The transition will take time, especially for the adaptation of web clients and network security systems. But the path is clear: querying is not modifying, and as of today, the HTTP protocol knows it.




