For decades, web developers have been lying to their servers.
We all do it. We use GET for fetching data until our search filters get too long or complex, and then we panic-switch to POST. We end up hitting endpoints like POST /api/products/search — using a method that does not clearly say "this is read-only," even though we are not creating, updating, or triggering anything. We are simply asking a question.
It is one of the web's favorite architectural workarounds, born out of necessity. But now the web finally has a cleaner alternative. Meet QUERY, a new HTTP method designed for complex read-only requests with a body.
1. The Problem Starts With a Search Filter
Imagine you are shopping online.
You open a shoe store app and apply filters:
- Brand: Nike
- Color: red
- Size: 10
- Price: under $50
- Shipping: free
- Delivery: tomorrow
To you, this is just a normal product search.
But behind the scenes, the frontend has to send all those filters to the backend. The backend then checks the database and returns matching products.
For a simple search, GET works fine:
GET /api/products?brand=nike&color=red&size=10This is clean, readable, and cache-friendly.
But modern apps do not always send simple filters. Sometimes they need to send hundreds of IDs, nested filters, date ranges, permission scopes, sorting rules, and advanced search conditions.
Soon the URL becomes too long, messy, and difficult to manage.
That is where GET starts to break down.
2. Why Not Use a Body With GET?
A developer might reasonably think: why not keep the URL clean and put the filters inside the GET body?
Like this:
GET /api/products
Content-Type: application/json
{
"brand": "nike",
"color": "red",
"size": 10,
"priceMax": 50
}It looks reasonable. It is not a reliable design.
A body on a GET request does not have a clear, standard meaning across the web. Some tools may ignore it. Some proxies may mishandle it. Some caches will not consider it when storing responses.
So even if it works in your local setup, it may behave differently once the request passes through browsers, CDNs, gateways, servers, and production infrastructure.
3. The Common Workaround: Use POST for Search
To avoid long URLs, developers started using POST for searches:
POST /api/products/search
Content-Type: application/json
{
"brand": "nike",
"color": "red",
"size": 10,
"priceMax": 50,
"delivery": "tomorrow"
}This works technically. The request body can be large. The JSON is clean. The backend gets all the filters properly.
That is why so many APIs expose endpoints like:
POST /search
POST /query
POST /graphqlEven when they are only fetching data.
But there is a hidden problem: POST does not clearly mean "read-only."
A POST request might create an order, submit a form, charge a card, upload a file, or trigger a workflow.
Because of that, browsers, CDNs, and other systems treat it carefully. They cannot always assume it is safe to retry. They do not naturally cache it like a normal read. They do not know that your POST /search endpoint is only asking a question.
So the API works, but the meaning is not clean. You are using a method designed for "sending something that may change state" to perform a search that only reads data.
That is the architectural mismatch.
4. Why This Matters for Performance
Caching is one of the biggest reasons the web is fast.
When a request is cacheable, a CDN can store the response and serve it again without hitting the main backend every time.
With GET, caching is straightforward because the URL identifies the request:
GET /api/products?color=redThe cache can store the response for that exact URL.
But with POST, the important search details live inside the body. Many systems do not treat POST search requests as simple cacheable reads by default.
So if 10,000 users run the same heavy search, your backend may have to calculate the same result 10,000 times. That means more server load, slower responses, and higher infrastructure cost.
Developers were stuck with a trade-off:
| Method | Benefit | Problem |
|---|---|---|
GET | Correct meaning and cache-friendly | Bad for large complex queries |
POST | Supports large request bodies | Hides that the request is read-only |
The web needed a better middle ground.
5. Enter QUERY
The new QUERY method gives HTTP a proper way to say:
I am sending a request body, but I am only asking for data.
A QUERY request looks like this:
QUERY /api/products
Content-Type: application/json
Accept: application/json
{
"brand": "nike",
"color": "red",
"size": 10,
"priceMax": 50,
"delivery": "tomorrow"
}This is the missing piece.
Like POST, QUERY can carry a structured body. Like GET, QUERY is meant for safe, read-only operations. The request is not supposed to create, update, or delete anything. It simply asks the server to process the query and return a result.
That makes the intent much clearer. You are no longer pretending that a search is a POST. You are using a method that actually describes what the request is doing.
6. QUERY vs GET vs POST
Here is the simple way to think about it:
| Use case | Best method |
|---|---|
| Simple request that fits in the URL | GET |
| Creating, submitting, or triggering something | POST |
| Complex read-only request with a body | QUERY |
For a simple product page:
GET /api/products/123For creating an order:
POST /api/ordersFor a complex product search:
QUERY /api/productsThat is the clean separation.
7. Should You Use QUERY Today?
Not everywhere, and not immediately.
QUERY is new, so frameworks, browsers, CDNs, gateways, and security tools need time to support it properly. In many production systems, POST /search will continue to exist for a while because the existing infrastructure already understands it.
But the idea behind QUERY matters. It gives API designers a better vocabulary.
For years, developers had to choose between long GET URLs and misleading POST searches. QUERY finally gives complex read operations their own proper method.
Final Takeaway
The web has always been built on simple methods:
GETto fetchPOSTto submitPUTandPATCHto updateDELETEto remove
But modern applications ask more complex questions than that old model handled cleanly.
That is why QUERY matters. It does not replace GET. It does not replace POST. It fills the awkward gap between them — letting you send large, structured search requests while clearly saying:
This is only a query. Nothing is being changed.