New HTTP QUERY Method RFC 10008 explained - Safe and Idempotent alternative to POST for search
Introduction
In June 2026, the IETF published RFC 10008 - the first new general-purpose HTTP method since PATCH was introduced in 2010.
The method is called QUERY.
In simple terms:
QUERY = Safety of GET + Body of POST
You can now send complex search/filter queries in the request body, while the server knows the operation is safe and idempotent. This means caching, automatic retries, and CDNs can all work properly.
This single change can finally end the long-standing practice of using POST for search.
The Problem We Had
1. Limitations of GET
With GET, query parameters go in the URL:
httpGET /products?category=electronics&price_min=1000&price_max=50000&brand=samsung,apple&sort=-rating&page=1&limit=20
When filters become complex (JSON filters, nested conditions, many tags), the URL easily exceeds 8,000 characters. Many servers, proxies, and browsers struggle with this. URLs also get logged, bookmarked, and shared - which is often undesirable.
2. Problems with POST
So many developers started using POST for search:
httpPOST /products/search Content-Type: application/json { "filters": { "category": "electronics", "price": { "min": 1000, "max": 50000 }, "brands": ["samsung", "apple"] }, "sort": "-rating", "page": 1, "limit": 20 }
But POST is not safe and not idempotent. That means:
- Caches and CDNs cannot safely cache the response
- Automatic retries after network failures are risky
- The server may treat it as a state-changing operation
We have been pretending that a read operation is a write operation for years.
What is the QUERY Method?
According to RFC 10008:
A QUERY requests that the request target process the enclosed content in a safe and idempotent manner and then respond with the result of that processing.
In plain English:
- You send the query in the request body (like POST)
- The server processes it and returns the result
- It does not change any server state (like GET)
- Sending the same request multiple times produces the same result (idempotent)
Comparison Table
| Property | GET | QUERY | POST |
|---|---|---|---|
| Safe | Yes | Yes | No (potentially) |
| Idempotent | Yes | Yes | No |
| Request Body | None | Expected | Expected |
| Cacheable | Yes | Yes | Limited |
| URL Length Problem | Yes | No | No |
| Safe to Auto-Retry | Yes | Yes | No |
Examples
Old Way (POST)
httpPOST /feed Host: example.org Content-Type: application/x-www-form-urlencoded q=foo&limit=10&sort=-published
New Way (QUERY)
httpQUERY /feed Host: example.org Content-Type: application/x-www-form-urlencoded q=foo&limit=10&sort=-published
Or with a JSON body:
httpQUERY /products/search Host: api.example.com Content-Type: application/json Accept: application/json { "filters": { "status": "active", "created_after": "2026-01-01", "tags": ["security", "web"] }, "sort": ["-created_at"], "limit": 50 }
A successful response returns 200 OK with the results.
Important Header: Accept-Query
Servers can now advertise which formats they accept for QUERY:
http200 OK Accept-Query: application/json, application/sql, application/jsonpath Content-Type: application/json
Examples mentioned in the RFC:
application/jsonapplication/x-www-form-urlencodedapplication/sqlapplication/jsonpathapplication/xslt+xml
Why This Matters
-
Correct Semantics
Read-only operations like search, filtering, and report generation can finally be expressed properly. -
Caching & Performance
CDNs, proxies, and browsers can now cache requests that have a body (the body becomes part of the cache key). -
Safe Retries
Clients can safely retry after network failures. -
Better Privacy & Logging
Complex queries no longer appear in URLs, so they are less likely to be logged. -
Better API Design
GraphQL-style queries, JSON filters, SQL-like queries — all can now use a standard HTTP method.
Node.js / Express Example
Most frameworks do not yet support QUERY natively, but it is easy to add:
jsconst express = require('express'); const app = express(); app.use(express.json()); // Custom method support for Express app.query = function (path, ...handlers) { return this.all(path, (req, res, next) => { if (req.method === 'QUERY') { return handlers[0](req, res, next); } next(); }); }; app.query('/search', (req, res) => { const filters = req.body; // Your search logic here const results = searchDatabase(filters); res.set('Accept-Query', 'application/json'); res.json({ count: results.length, data: results }); }); app.listen(3000);
Test with curl:
bashcurl -X QUERY http://localhost:3000/search \ -H "Content-Type: application/json" \ -d '{"status":"active","limit":10}'
When Should You Use QUERY?
| Situation | Recommendation |
|---|---|
| Simple list + a few filters | GET |
| Complex filters / nested JSON | QUERY |
| Search + pagination + sorting | QUERY |
| Create / Update / Delete data | POST / PUT / PATCH / DELETE |
| Report generation (read-only) | QUERY |
Caveats
- Not all browsers, CDNs, WAFs, and load balancers support QUERY yet. Test thoroughly before production use.
- QUERY is not currently safelisted for CORS, so a preflight request may be required.
- Servers must check the
Content-Type. Missing or mismatched Content-Type should return400or415.
Final Thoughts
One of the biggest gaps in HTTP has finally been filled.
The habit of “using POST for search” will slowly fade away.
If you are designing APIs, start considering QUERY for new endpoints. And plan to migrate existing POST-based search endpoints over time.
Tags: #HTTP #RFC10008 #WebDevelopment #API #Backend