DEV Community

Kirill Tolmachev
Kirill Tolmachev

Posted on

Every REST API I've Seen in Production Violates REST. Nobody Cares.

Roy Fielding must be spinning in his still-very-much-alive chair. The man who coined REST in his 2000 dissertation watches as an entire industry slaps "REST API" labels on endpoints that would make him weep into his coffee. And you know what? We're all better for it.

Every "RESTful" API I've audited in fifteen years of backend work commits the same sins. They return JSON instead of hypermedia. They stuff action verbs into URLs like /api/users/123/activate. They ignore HATEOAS completely. They treat HTTP status codes like suggestions rather than contracts.

But here's the uncomfortable truth: these "violations" make APIs faster to build, easier to consume, and simpler to maintain.

The Academic REST vs The Real World

True REST, as Fielding envisioned it, demands six constraints. Stateless communication, cacheable responses, uniform interface, layered system, code on demand, and the big one that trips everyone up: hypermedia as the engine of application state.

HATEOAS means your API responses should contain links telling clients what actions they can take next. Like a choose-your-own-adventure book for computers.

{
  "id": 123,
  "name": "John Doe",
  "status": "active",
  "_links": {
    "self": {"href": "/users/123"},
    "deactivate": {"href": "/users/123/deactivate", "method": "POST"},
    "edit": {"href": "/users/123", "method": "PUT"}
  }
}
Enter fullscreen mode Exit fullscreen mode

Beautiful in theory. Absolute hell in practice.

Why Everyone Ignores HATEOAS

I worked on a project where the backend team spent three months implementing proper HATEOAS. The frontend developers revolted. Mobile developers threatened to quit. The API became a maze of link-following that turned simple operations into multi-round-trip nightmares.

Frontend frameworks expect predictable endpoints. Mobile apps need offline capabilities that break when every action depends on server-provided links. GraphQL exists partly because REST's hypermedia constraints feel like handcuffs when you're trying to ship features.

The industry collectively decided that having /users/123/activate is more valuable than maintaining Roy Fielding's architectural purity. And we're right.

The Status Code Theater

HTTP status codes tell another story of pragmatic rebellion. Academic REST demands precise status codes for every scenario.

  • 201 for created resources
  • 202 for accepted but not processed
  • 204 for successful deletion
  • 422 for validation errors

Real APIs? Most return 200 for everything that doesn't explode, stuff error details in the response body, and call it a day.

{
  "success": false,
  "error": "User not found",
  "code": "USER_NOT_FOUND"
}
Enter fullscreen mode Exit fullscreen mode

This drives REST purists crazy. It also prevents client-side libraries from breaking when status codes change between API versions.

Resource URLs That Aren't Actually Resources

True REST treats everything as resources identified by URLs. Actions happen through HTTP verbs on those resources.

But what happens when you need to send a password reset email? Or trigger a complex workflow? Or batch process a thousand records?

You get endpoints like:

  • POST /send-password-reset
  • POST /workflows/inventory-sync/trigger
  • POST /batch/process-orders

These aren't resources. They're RPC calls wearing REST costumes. And that's perfectly fine because sometimes you need to tell a server to DO something, not just manipulate data.

JSON Killed the Hypermedia Star

The final nail in REST's coffin was JSON becoming the default response format. XML supported rich linking structures through standards like XLink. JSON turned APIs into simple data dumps.

Compare this XML response:

<user id="123" xmlns:xlink="http://www.w3.org/1999/xlink">
  <name>John Doe</name>
  <link rel="edit" xlink:href="/users/123" />
  <link rel="delete" xlink:href="/users/123" />
</user>
Enter fullscreen mode Exit fullscreen mode

With the JSON equivalent developers actually want:

{
  "id": 123,
  "name": "John Doe"
}
Enter fullscreen mode Exit fullscreen mode

The JSON version loses hypermedia capabilities but gains simplicity, performance, and developer happiness. We chose convenience over architectural correctness.

What We Actually Built Instead

Modern "REST" APIs are really just HTTP-based RPC with some conventions:

  • Use HTTP verbs when they make sense
  • Structure URLs in a hierarchy when possible
  • Return JSON because everyone expects it
  • Use status codes for major categories (success/client error/server error)
  • Ignore hypermedia unless you have infinite time and patience

This hybrid approach gives us 80% of REST's benefits with 20% of its complexity. That's an engineering win.

The Practical Takeaway

Stop feeling guilty about your "impure" REST APIs. Focus on what actually matters:

Consistency over compliance. Pick conventions and stick to them across your entire API surface.

Developer experience over dogma. Your API's job is to make other developers productive, not to satisfy academic requirements.

Pragmatic status codes. Use 200/400/401/403/404/500 for 95% of scenarios. Add others only when clients need to handle them differently.

Embrace RPC when needed. Some operations aren't resource manipulations. Don't force them into resource-based URLs just to satisfy REST purists.

The internet runs on APIs that violate REST principles. It works because we optimized for reality instead of theory. Roy Fielding gave us a foundation, but we built something more practical on top of it.

And that's exactly how software evolution should work.

Top comments (0)