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

Published August 9, 2026

Published on August 9, 2026 • Updated on August 27, 2026

By Denny Eka Saputro (16 years in IT)

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 because it changes nothing, it is idempotent because 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

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. The blog list is literally the GET /api/blog?type=blog&page=2 above, and I am not going to rewrite it. QUERY earns its place the moment a search grows a real filter object. For me that moment is coming, not gone. As the blog grows and I add proper search, tag filters, and date ranges, that query string is exactly the thing that will outgrow itself, and that is when a JSON body starts to look like the honest answer instead of the awkward one.

The honest catch

Here is where I want to be straight, because a new HTTP method is not something you just start using. It has to survive the entire path a request takes, and mine is not short. A call to my API goes through Cloudflare, then CloudFront, then API Gateway, and only then reaches my Gin backend running on Lambda. Every one of those hops has to recognize QUERY and pass it through instead of rejecting an unknown method, and my frontend's HTTP client has to be willing to send it in the first place. Until that whole chain is ready, a QUERY request risks getting bounced somewhere in the middle with an error that has nothing to do with my code.

So the POST hack is still the pragmatic call today, and I am not switching anything yet. 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, and I had stopped noticing it was a workaround at all.

That gap is closing. The next time I design a search endpoint that outgrows a query string, I will finally have an answer that does not require lying about what the request does. It is a small change. But the boring plumbing of the web getting a little more honest is exactly the kind of thing I like to see, and it is worth understanding before the day you actually get to use it.