
If you've built a backend of any real size, you've hit this wall. You're standing up a search endpoint, the filter payload is getting fat, and you're forced to answer a question that has quietly haunted HTTP for two decades:
Do I use GET or POST?
It sounds trivial. It isn't. Both answers are wrong in their own way, and every backend developer has silently made peace with picking the less-wrong one. As of mid-June 2026, we finally have a third option that isn't a compromise. It's called QUERY, and it's a real, standardized HTTP method — RFC 10008.
Let me walk through the problem the way I actually run into it in design reviews, and then why QUERY is the answer I've been waiting years for.
The 20-Year Problem: GET or POST for Search?
A search request is, semantically, a read. You're not creating anything. You're not mutating state. You send some filters, you get results back. Run it once or run it ten times — the server's state is untouched.
HTTP has a precise vocabulary for exactly this: a safe method (no side effects) that is also idempotent (repeating it changes nothing). That method is GET. Perfect match — until you look at where the data goes.
Why GET Falls Short
GET puts everything in the URL. That's fine for ?q=phones. It falls apart the moment your filters grow up:
GET /search?q=phones&filter=inStock&sort=price&page=3&brand=apple&brand=samsung&priceMin=200&priceMax=1200&color=black&rating=4 HTTP/1.1
Host: api.example.com
// safe + cacheable ✅
// but... 414 URI Too Long ❌The semantics are correct — GET is exactly the right meaning — but the transport betrays you. Real search UIs generate deeply nested filter trees, faceted selections, geo polygons, arrays of IDs. None of that fits comfortably in a query string, and servers, proxies, and CDNs all enforce URL length limits. Cross a threshold and you get a 414 URI Too Long. There's also the small matter of dumping sensitive filter criteria into access logs and browser history.
So you reach for the other tool.
Why POST Is a Compromise (a Small, Structural Lie)
POST has all the room in the world. The body is unbounded and structured:
POST /search HTTP/1.1
Host: api.example.com
Content-Type: application/json
{ "filter": "inStock", "sort": "price", "page": 3 }
// body fits ✅
// but POST means "I'm changing data" — a lie ❌This works. It's what most of us ship. But it's semantically dishonest. POST is neither safe nor idempotent — it announces a state change. That announcement ripples outward:
- Caches won't touch a
POST. Your read is uncacheable by default. - Clients and proxies won't auto-retry a
POST, because retrying might double-charge something. Your safe read loses free retriability. - Every developer reading the endpoint has to just know that this particular
POSTdoesn't actually write anything.
We've been shipping a read operation disguised as a write for twenty years. It works because we've all agreed to look past the lie.
QUERY: Safe + Idempotent, With a Body
QUERY is the method that stops the pretending. It carries a request body like POST, but it is defined as safe and idempotent like GET:
QUERY /search HTTP/1.1
Host: api.example.com
Content-Type: application/json
{ "filter": "inStock", "sort": "price", "page": 3 }
// safe + idempotent like GET ✅
// carries a body like POST ✅RFC 10008 says it plainly: a QUERY request asks the server to process the enclosed content in a safe and idempotent manner and return the result of that processing. It's the shape we always needed — the honesty of GET with the capacity of POST.
Because the semantics are declared at the protocol level, the whole stack can finally reason about the request correctly. And the RFC pairs it with a content-based caching model, so responses to identical query bodies can be cached — something POST could never offer.
Why It Matters
This is more than pedantry about verbs. The semantics are the feature:
- ✅ Safe & idempotent — auto-retryable. Intermediaries and clients can safely repeat a dropped
QUERYwithout fear of side effects. - ✅ Carries a full request body. Arbitrarily large, structured, nested filters — no
414, no cramming JSON into a query string. - ✅ Purpose-built for search and data APIs. The method finally matches the operation. Your code stops lying to your infrastructure.
Where Adoption Stands
Be clear-eyed about the timeline: QUERY is roughly eleven years in the making, tracing back to the early safe-method-with-body drafts before landing as a Proposed Standard in June 2026. The ecosystem is still catching up in layers:
- Runtimes: Node.js's HTTP parser has recognized the
QUERYmethod natively since early 2024, ahead of the final RFC. - Documentation: OpenAPI 3.2 (released September 2025) can formally describe
QUERYoperations, so your API specs and generated clients can represent it. - Frameworks: This is the lagging layer. Most web frameworks, routers, and HTTP clients don't expose
QUERYas a first-class verb yet. Expect a steady wave of support through 2026 and beyond.
Practically, that means you can start modeling endpoints around QUERY today, but you'll want graceful fallbacks — often a POST alias — until your framework and edge layer catch up.
Closing Thought
The best protocol changes aren't flashy; they just remove a compromise you'd stopped noticing. QUERY doesn't let you do anything you couldn't hack together before with a mislabeled POST. What it does is let the request mean what it does — safe, idempotent, and roomy — so that caches, proxies, clients, and the next engineer to read your code all understand it without a footnote.
After twenty years of choosing the less-wrong option, that's a genuinely satisfying upgrade. The next time someone asks "GET or POST for this search?", the honest answer is finally: neither.