HTTP Is Finally Getting a QUERY Method, and It Fixes a Hack I've Shipped a Dozen Times

Published 8/9/2026

Published on 8/9/2026 • Updated on 8/9/2026

HTTP Is Finally Getting a QUERY Method, and It Fixes a Hack I've Shipped a Dozen Times 1

ES2026 got approved this week, which is the headline everyone shared. The thing that actually made me sit up was smaller and further down the page: HTTP is getting a new method called QUERY.

If you have never had to build a search endpoint, this will sound boring. If you have, you already know the exact pain it fixes.

The problem I have hacked around forever

Here is the situation every backend developer runs into. You have a list endpoint. At first it is simple, so you write a clean GET:

GET /api/blog?type=blog&page=2

Query strings are perfect for this. The request is safe (it changes nothing), it is idempotent (calling it twice does the same thing), and it can be cached. That is exactly what GET is for.

Then the filtering grows. Now you need tags, a date range, a full text search, a sort order, maybe a few of each. And you hit the wall, because a GET cannot carry a request body, and a URL is a bad place to put a structured filter. You start encoding arrays and nested objects into the query string, the URL balloons past what some proxies and servers will accept, and every one of those parameters ends up sitting in plain text in your access logs. I have built this. It is never clean.

So most of us reach for the other hack:

POST /api/search
{ "type": "blog", "tags": ["go", "vite"], "from": "2026-01-01", "sort": "newest" }

Now the body is comfortable and structured. But you have just lied about what the request does. A POST tells every proxy, cache, and reader of your code that this call has side effects. It does not. It is a read. You lose caching, you muddy your own API's meaning, and you have trained your frontend to POST for something that only ever fetches. It works, and it always felt wrong, because it is wrong.

What QUERY actually is

QUERY is the missing option. It is a method that is safe and idempotent like GET, so caches and proxies can treat it correctly, but it is allowed to carry a request body like POST. That is the whole idea, and it is exactly the shape of the problem.

QUERY /api/blog
{ "type": "blog", "tags": ["go", "vite"], "from": "2026-01-01", "sort": "newest" }

That request says what it means. It reads, it does not change anything, it can be cached, and the complicated filter lives in a clean JSON body instead of a URL held together with encoding tape. No more choosing between an unreadable query string and a POST that pretends to be a mutation.

What this means in practice, and the honest catch

My own API is a Go and Gin backend, and most of its list endpoints are still simple enough that a plain GET is the right tool. I am not going to rewrite those. QUERY earns its place the moment a search grows a real filter object, and that moment always comes eventually.

Here is the catch, and I want to be straight about it. New HTTP methods take years to become safe to actually depend on. Your router has to support it, your CDN and proxies have to pass it through instead of rejecting an unknown method, and your client library has to send it. Until that whole chain is ready, the POST hack is still the pragmatic call. So I am not switching anything today.

What I am doing is naming the hack for what it is. For years I told myself "POST for search is just how it is done." It was not a rule, it was a workaround for a gap in the protocol. That gap is closing. The next time I design a search endpoint that outgrows a query string, I finally have an answer that does not require lying about what the request does.

Small change. But the boring plumbing of the web getting a little more honest is the kind of thing I like to see.

Until then, see you at the top!