The slippery slope

Published: (February 16, 2026 at 04:00 PM EST)
3 min read
Source: Dev.to

Source: Dev.to

Introduction

A recent LinkedIn post discussed using query parameters to request alternate representations of a resource. The idea is to project only the needed fields, e.g.:

GET /users/1

Response

HTTP/1.1 200 OK
Content-Type: application/json

{"username": "Name", "displayName": "Display Name"}

If the client only needs displayName, the request can be written as:

GET /users/1?fields=displayName

Response

HTTP/1.1 200 OK
Content-Type: application/json

{"displayName": "Display Name"}

At first glance this looks reasonable, but it raises questions about the proper use of the query component.

RFC 3986 Overview

RFC 3986 defines the generic syntax of a URI:

scheme ":" hier-part [ "?" query ] [ "#" fragment ]
  • Scheme – protocol identifier (e.g., http, ftp). Case‑insensitive.
  • Authority – host, optional port, and optional userinfo (e.g., //www.example.com:80).
  • Path – hierarchical sequence of segments identifying a resource.
  • Query – non‑hierarchical data, typically key=value pairs, introduced by ?.
  • Fragment – secondary resource identifier (e.g., a page anchor), introduced by #; processed by the user agent, not the server.

The specification treats the query string as an opaque set of key‑value pairs. It does not prescribe any semantics for parameters such as fields, sort, or filter.

Query Parameters as a Mini‑DSL

Using query parameters as instructions (e.g., fields, sort, filter) effectively creates a domain‑specific language (DSL) on top of a limited set of HTTP verbs. Examples:

GET /users/1?fields=displayName
GET /users/?sort=
GET /users/?filter=
GET /users?id=1&fields=displayName

Here id is a search parameter, while fields is a projection instruction. Over time, such conventions can become de‑facto standards, forcing API designers to maintain additional documentation and treat these keywords as reserved words.

Why This Is Problematic

  • Opacity of the URI – RFC 3986 treats everything after ? as opaque; interpreting it as a DSL adds hidden contracts.
  • Coupling of verbs and instructions – The limited set of HTTP methods becomes overloaded with extra semantics.
  • Maintenance burden – Every new instruction (e.g., fields, sort) requires documentation and client awareness.

Content Negotiation as an Alternative

Projection is fundamentally a representation concern. HTTP already provides a mechanism for clients to request specific representations: content negotiation.

GET /users/1
Accept: application/json; fields=displayName

The Accept header can carry media‑type parameters, similar to:

GET /users/1
Accept: application/json; q=0.9; charset=UTF-8

These parameters are open‑ended, allowing servers to interpret them as needed.

RFC 6906 – Profile Parameter

RFC 6906 introduces a more structured way to request representation variations:

GET /users/1
Accept: application/json; profile="http://www.example.com/profiles/user-summary"

Alternatively, a custom media type can be defined:

GET /users/1
Accept: application/vnd.user.displayname+json

Practical Considerations

  • Links – When creating resources, it is simpler to convey a URL that already includes the desired projection:

    Location: /users/1?fields=displayName

    Using additional headers to convey projection instructions would complicate the response.

  • Caching – Caches are not inherently aware of custom query‑parameter semantics. Proper caching requires explicit Vary: headers, and behavior can differ across implementations, leading to cache misses or stale data.

Conclusion

The prevalence of query‑parameter shortcuts does not automatically make them an architectural best practice. While they are pragmatic, they introduce hidden contracts and can erode the clarity and interoperability that REST aims to provide. Remember:

“Architecture erodes not through wrong decisions, but through forgotten reasons.”

Explicitly documenting such shortcuts as conventions, not standards, helps preserve the intent and prevents a slippery slope away from established HTTP semantics.

0 views
Back to Blog

Related posts

Read more »