<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Karan</title>
    <description>The latest articles on DEV Community by Karan (@karan51ngh).</description>
    <link>https://dev.to/karan51ngh</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3096168%2Fcd53665e-801a-4b2c-ba12-c8a3df368dec.jpeg</url>
      <title>DEV Community: Karan</title>
      <link>https://dev.to/karan51ngh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/karan51ngh"/>
    <language>en</language>
    <item>
      <title>HTTP Just Got a New Method: Why QUERY Changes API Design</title>
      <dc:creator>Karan</dc:creator>
      <pubDate>Thu, 16 Jul 2026 10:50:13 +0000</pubDate>
      <link>https://dev.to/karan51ngh/http-just-got-a-new-method-why-query-changes-api-design-51ig</link>
      <guid>https://dev.to/karan51ngh/http-just-got-a-new-method-why-query-changes-api-design-51ig</guid>
      <description>&lt;p&gt;&lt;em&gt;One of API design's most familiar workarounds may finally have an expiration date.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For years, API designers have quietly made the &lt;strong&gt;same compromise&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;They start with a clean GET request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="nf"&gt;GET&lt;/span&gt; &lt;span class="nn"&gt;/products?category=laptop&amp;amp;brand=acme&lt;/span&gt; &lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api.example.com&lt;/span&gt;
&lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the product team asks for price ranges, multiple brands, availability rules, nested attributes, full-text search, sorting, pagination, and user-specific constraints.&lt;/p&gt;

&lt;p&gt;The URL begins to look less like an address and more like a programming language:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/products
└── filters
    ├── category = laptop
    ├── brands = [acme, contoso, globex]
    ├── price
    │   ├── minimum = 800
    │   └── maximum = 1800
    ├── specifications
    │   ├── memory &amp;gt;= 32 GB
    │   └── storage = SSD
    └── sort = rating desc, price asc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the team moves the filters into JSON and sends them with POST:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="nf"&gt;POST&lt;/span&gt; &lt;span class="nn"&gt;/products/search&lt;/span&gt; &lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api.example.com&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
&lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"brands"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"acme"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"contoso"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"globex"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"min"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"max"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1800&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"specifications"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"memoryGb"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"gte"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"storageType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ssd"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-rating"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The endpoint works. The JSON is readable. The server returns products. &lt;strong&gt;But the method is now vague:&lt;/strong&gt; without endpoint-specific knowledge, POST could mean a safe search, a payment, a message submission, or some other state-changing command.&lt;/p&gt;

&lt;p&gt;In June 2026, &lt;a href="https://www.rfc-editor.org/rfc/rfc10008.html" rel="noopener noreferrer"&gt;RFC 10008&lt;/a&gt; &lt;strong&gt;gave that operation its own method:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="nf"&gt;QUERY&lt;/span&gt; &lt;span class="nn"&gt;/products&lt;/span&gt; &lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api.example.com&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
&lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"brands"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"acme"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"contoso"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"globex"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"min"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"max"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1800&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-rating"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;QUERY gives complex reads request content without giving up explicit read-only, retry, and caching semantics.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  HTTP Methods Are Tiny Words With Large Contracts
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;POST&lt;/code&gt;, &lt;code&gt;PUT&lt;/code&gt;, and &lt;code&gt;DELETE&lt;/code&gt; are method tokens with standardized meanings. Those meanings let clients, servers, caches, proxies, gateways, and monitoring systems reason about a request before they understand the application behind it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The method is the first line of the contract:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP request
├── method: What kind of operation is this?
├── target: Which resource is in scope?
├── fields: What metadata applies?
└── content: What representation accompanies the request?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three properties matter to the &lt;strong&gt;QUERY&lt;/strong&gt; story:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;What it actually means&lt;/th&gt;
&lt;th&gt;What it does not mean&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Safe&lt;/td&gt;
&lt;td&gt;The client does not request a change to the target resource's state&lt;/td&gt;
&lt;td&gt;The server performs no work, writes no logs, or creates no auxiliary resources&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Idempotent&lt;/td&gt;
&lt;td&gt;Repeating the same request has the same intended effect as sending it once&lt;/td&gt;
&lt;td&gt;Every response must contain identical data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cacheable&lt;/td&gt;
&lt;td&gt;A response may be stored and reused under HTTP caching rules&lt;/td&gt;
&lt;td&gt;Every CDN will cache it automatically&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Idempotent does not mean identical responses.&lt;/em&gt; &lt;code&gt;GET /products/42&lt;/code&gt; can return \$900 today and \$850 tomorrow; &lt;strong&gt;GET&lt;/strong&gt; remains idempotent because repeated reads request no additional state change. &lt;strong&gt;PUT&lt;/strong&gt; and &lt;strong&gt;DELETE&lt;/strong&gt; are also idempotent despite changing state. &lt;strong&gt;POST&lt;/strong&gt; is not idempotent by definition because replaying it may repeat an action. &lt;strong&gt;PATCH&lt;/strong&gt; may be idempotent in a specific use, but HTTP does not guarantee it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Gap Between GET and POST
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;GET&lt;/strong&gt; is an excellent fit when query input fits naturally in the target URI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="nf"&gt;GET&lt;/span&gt; &lt;span class="nn"&gt;/feed?q=http&amp;amp;limit=10&amp;amp;sort=-published&lt;/span&gt; &lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;example.org&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It clearly communicates a safe, idempotent retrieval. Its responses work naturally with browsers, shared caches, CDNs, bookmarks, links, and observability tools.&lt;/p&gt;

&lt;p&gt;Complex queries expose four practical limits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clients, proxies, gateways, and servers impose different limits on request targets. &lt;em&gt;**RFC 9110&lt;/em&gt;* recommends support for at least 8,000 octets, but your path is only as tolerant as its most restrictive hop.*&lt;/li&gt;
&lt;li&gt;Nested filters, arrays, ranges, and query languages become awkward once they are flattened via encoding into a query string.&lt;/li&gt;
&lt;li&gt;Request URIs often appear in logs, browser history, bookmarks, referrers, and monitoring tools. Request content can also be logged, but it is less widely exposed by default.&lt;/li&gt;
&lt;li&gt;With &lt;strong&gt;GET&lt;/strong&gt;, every input combination becomes a distinct URI. That is useful for small filters and clumsy for large query documents.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;POST&lt;/strong&gt; avoids those limits because it expects request content. &lt;em&gt;It also loses the generic signal that the operation is a safe, idempotent query.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;That is the gap QUERY fills.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcl9wusun50ao7jqsfrqb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcl9wusun50ao7jqsfrqb.png" alt=" " width="800" height="1170"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What QUERY Actually Means
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc10008.html#section-2" rel="noopener noreferrer"&gt;RFC 10008&lt;/a&gt; defines &lt;strong&gt;QUERY&lt;/strong&gt; as a method that asks the target resource to perform a server-side query within that resource's scope. The request's content and &lt;code&gt;Content-Type&lt;/code&gt; define the query. The target URI defines the resource being queried.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="nf"&gt;QUERY&lt;/span&gt; &lt;span class="nn"&gt;/contacts&lt;/span&gt; &lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;example.org&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/jsonpath&lt;/span&gt;
&lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;

$[?(@.country == "India" &amp;amp;&amp;amp; @.status == "active")]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;/contacts&lt;/code&gt; establishes the scope. &lt;code&gt;application/jsonpath&lt;/code&gt; tells the server how to interpret the content. The JSONPath expression describes the query.&lt;/p&gt;

&lt;p&gt;A server &lt;strong&gt;must reject&lt;/strong&gt; a &lt;strong&gt;QUERY&lt;/strong&gt; request when &lt;code&gt;Content-Type&lt;/code&gt; is missing or inconsistent with the content. &lt;em&gt;That requirement is not decorative.&lt;/em&gt; The same bytes could have completely different meanings under &lt;code&gt;application/json&lt;/code&gt;, &lt;code&gt;application/sql&lt;/code&gt;, or &lt;code&gt;application/jsonpath&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  QUERY is not simply “GET with a body”
&lt;/h3&gt;

&lt;p&gt;That phrase is a useful first approximation, but it &lt;strong&gt;hides the semantic difference&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GET&lt;/strong&gt; asks for a current representation of the resource identified by the target URI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;QUERY&lt;/strong&gt; asks the target resource to perform the operation described by the request content.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;HTTP assigns &lt;em&gt;no generally defined semantics&lt;/em&gt; to content in a GET request. Some implementations reject it, some ignore it, and intermediaries cannot safely assume what it means.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Capability&lt;/th&gt;
&lt;th&gt;GET&lt;/th&gt;
&lt;th&gt;QUERY&lt;/th&gt;
&lt;th&gt;POST&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Safe by definition&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Idempotent by definition&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Request content&lt;/td&gt;
&lt;td&gt;No generally defined semantics&lt;/td&gt;
&lt;td&gt;Expected&lt;/td&gt;
&lt;td&gt;Expected&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Query identified entirely by URI&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Response can satisfy the same method later&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best fit&lt;/td&gt;
&lt;td&gt;Ordinary retrieval and compact filters&lt;/td&gt;
&lt;td&gt;Complex, read-only queries&lt;/td&gt;
&lt;td&gt;Submissions and application-defined processing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;POST&lt;/strong&gt; responses can be cached under specific conditions, but a stored response generally cannot satisfy a later &lt;strong&gt;POST&lt;/strong&gt;. By design, a cached &lt;strong&gt;QUERY&lt;/strong&gt; response can satisfy an equivalent later &lt;strong&gt;QUERY&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Most Important Part: Caching the Content
&lt;/h2&gt;

&lt;p&gt;A cache normally starts with the method and target URI when matching requests. &lt;strong&gt;That is insufficient for QUERY.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These two requests target the same URI but ask different questions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="nf"&gt;QUERY&lt;/span&gt; &lt;span class="nn"&gt;/products&lt;/span&gt; &lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"brand"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"acme"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="nf"&gt;QUERY&lt;/span&gt; &lt;span class="nn"&gt;/products&lt;/span&gt; &lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"brand"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"globex"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a cache considered only &lt;code&gt;/products&lt;/code&gt;, it could return Acme results to a client asking for Globex. RFC 10008 therefore requires a QUERY cache key to incorporate the request content and related metadata.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsvt68hnueq4opsa4of67.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsvt68hnueq4opsa4of67.png" alt=" " width="800" height="874"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A cache may normalize semantically insignificant differences before generating the key. For example, these JSON documents might mean the same thing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"brand"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"acme"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"inStock"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"inStock"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"brand"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"acme"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But normalization is dangerous when the cache and application disagree about meaning. &lt;strong&gt;A false match can return the wrong data.&lt;/strong&gt; The safest initial implementation is often &lt;em&gt;a deterministic query format plus a hash of the exact content and relevant metadata&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This is why “&lt;strong&gt;QUERY&lt;/strong&gt; is cacheable” does not mean “every CDN supports it today.” A compliant QUERY cache must read the full request content and include it in matching.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Query Can Become a GET-able Resource
&lt;/h2&gt;

&lt;p&gt;RFC 10008 offers another useful pattern. A server can assign a URI to the query itself, to the result that was just produced, or to both.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt; &lt;span class="ne"&gt;OK&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
&lt;span class="na"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/products/stored-queries/42&lt;/span&gt;
&lt;span class="na"&gt;Content-Location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/products/stored-results/17&lt;/span&gt;
&lt;span class="na"&gt;ETag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"result-17"&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"brand"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"acme"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1299&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"brand"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"contoso"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1499&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The two response fields serve different purposes:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Identifies&lt;/th&gt;
&lt;th&gt;A later GET means&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Location&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;An equivalent resource representing the query and its target&lt;/td&gt;
&lt;td&gt;Retrieve the current result equivalent to executing that query&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Content-Location&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A resource corresponding to the result just returned&lt;/td&gt;
&lt;td&gt;Retrieve that result representation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpth6wcch4739mkenu1zt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpth6wcch4739mkenu1zt.png" alt=" " width="800" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The distinction matters when the underlying data changes.&lt;/strong&gt; A stored query can produce a newer answer. A stored result can represent the answer from a particular execution.&lt;/p&gt;

&lt;p&gt;QUERY also supports conditional requests. Once a client has an &lt;code&gt;ETag&lt;/code&gt; or &lt;code&gt;Last-Modified&lt;/code&gt; validator, it can ask for results only if they changed. If the server supplies a &lt;code&gt;Location&lt;/code&gt; for an equivalent resource, subsequent GET requests can make that flow simpler and more widely compatible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Safe Retries Are a System Design Feature
&lt;/h2&gt;

&lt;p&gt;Imagine a client sends a complex search and the connection drops before the response arrives.&lt;/p&gt;

&lt;p&gt;With an application-specific &lt;strong&gt;POST&lt;/strong&gt; endpoint, the client cannot infer from the method alone whether retrying might repeat a state change. It needs out-of-band knowledge of that endpoint's behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;QUERY carries the answer in the protocol.&lt;/strong&gt; It is idempotent, so clients and intermediaries can repeat it after a connection failure without introducing a second requested state change.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Connection fails
├── POST
│   └── Retry only with endpoint-specific knowledge or safeguards
└── QUERY
    └── Retry is allowed by the method's idempotent semantics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Servers Can Advertise QUERY Support
&lt;/h2&gt;

&lt;p&gt;The RFC also defines the &lt;code&gt;Accept-Query&lt;/code&gt; response field. A resource can use it to advertise the media types it accepts as query content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="nf"&gt;HEAD&lt;/span&gt; &lt;span class="nn"&gt;/products&lt;/span&gt; &lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api.example.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt; &lt;span class="ne"&gt;OK&lt;/span&gt;
&lt;span class="na"&gt;Accept-Query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json, application/jsonpath&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells the client that the resource supports QUERY with JSON or JSONPath content. &lt;code&gt;Content-Type&lt;/code&gt; identifies the query format, while &lt;code&gt;Accept&lt;/code&gt; lists the desired response formats.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request format                         Response format
Content-Type: application/json         Accept: application/json
             │                                  │
             └── how to read the query          └── how to return the result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why You Should Not Replace Every GET Tomorrow
&lt;/h2&gt;

&lt;p&gt;QUERY is now standardized. &lt;strong&gt;Standardization and universal deployment are not the same event.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An HTTP request usually crosses a chain of components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client
  └── SDK or browser
      └── corporate proxy
          └── CDN or edge cache
              └── WAF
                  └── API gateway
                      └── application server
                          └── route handler
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Every component must either understand QUERY or pass it through correctly.&lt;/strong&gt; Before adopting it, verify the boring path:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The client can send an extension method with content.&lt;/li&gt;
&lt;li&gt;Proxies, firewalls, and gateways do not reject or rewrite it.&lt;/li&gt;
&lt;li&gt;The application server can route it.&lt;/li&gt;
&lt;li&gt;Cache behavior includes content and relevant metadata in the key.&lt;/li&gt;
&lt;li&gt;Authentication and authorization are evaluated before query execution.&lt;/li&gt;
&lt;li&gt;Logs and tracing systems label it correctly without exposing sensitive content.&lt;/li&gt;
&lt;li&gt;Rate limits account for query cost, not merely request count.&lt;/li&gt;
&lt;li&gt;Cross-origin browser calls complete the required CORS preflight.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is also a security misconception worth removing:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Request content is less likely than a URI to appear in routine logs. It is not automatically private.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Use HTTPS. Redact sensitive fields. Validate the query language. Apply authorization at the data level. Limit depth, joins, result size, and execution time. A beautifully semantic method can still carry an expensive or malicious query.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bigger Lesson Is Not About One New Word
&lt;/h2&gt;

&lt;p&gt;HTTP methods help distributed systems &lt;strong&gt;communicate intent&lt;/strong&gt;. &lt;strong&gt;GET&lt;/strong&gt; says, “Give me a representation of this resource.” &lt;strong&gt;POST&lt;/strong&gt; says, “Process this content according to this resource's rules.” &lt;strong&gt;QUERY&lt;/strong&gt; now says, “Safely process this query and give me the result.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Simple filters should remain GET requests.&lt;/strong&gt; Existing &lt;strong&gt;POST&lt;/strong&gt; search endpoints will not suddenly stop working. But when a read operation becomes too expressive for a URI and your request path supports it, developers no longer have to choose between &lt;em&gt;readable content&lt;/em&gt; and &lt;em&gt;honest HTTP semantics&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The gap finally has a method.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The one sentence to remember:&lt;/strong&gt; QUERY is a safe, idempotent, content-bearing HTTP method for complex server-side queries.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc10008.html" rel="noopener noreferrer"&gt;RFC 10008: The HTTP QUERY Method&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc9110.html" rel="noopener noreferrer"&gt;RFC 9110: HTTP Semantics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc9111.html" rel="noopener noreferrer"&gt;RFC 9111: HTTP Caching&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>softwareengineering</category>
      <category>softwaredevelopment</category>
      <category>systemdesign</category>
      <category>http</category>
    </item>
  </channel>
</rss>
