Your API Doesn’t Always Need to Be a Product

1/13/2025 — 6 minutes read (1166 words)

HTTP/JSON APIs are ubiquitous in our web applications. Yes, the web involves having a user's browser communicate with the server managing the data, but that doesn't mean we need to treat every API as a standalone product. Sometimes, our APIs might deserve to be a little more discreet in a web application’s architecture.

Contents

A Brief History of the Web

In the Beginning, Documents

The first web pages looked nothing like what we know today. Take, for example, this webpage from the early 1990s: a few documents without images, without styles, connected by hyperlinks (I’ll let you judge how readable it is compared to modern websites). The web was primarily a network for accessing information in the form of documents organized into a network (web).

The HTTP protocol dates back to this era and is perfectly optimized for transporting hypermedia documents (hence the HT in HTTP), with a bit of interaction based on forms.

jQuery, XHR, and the Rejection of Page Navigation

The usage of the web exploded. Websites became more numerous, richer in content, and notably more interactive. Documents became less static to allow for an increasingly personalized user experience.

Consequently, the web slowed down (pages needed to be generated dynamically, and networks weren’t as fast yet in every household), and some websites began to look more like applications rather than interconnected documents.

This is why developers started to heavily use XHR requests to make websites more interactive1. Reloading an entire page just to change a small portion of it doesn’t make for a great user experience when loading times are significant.

The browser took a specific turn: rather than increasing the capabilities of the HTML language and the HTTP protocol, JavaScript allowed developers to code specific interactions for each website in the browser itself. Developers could modify parts of a page using HTTP requests directly in JavaScript rather than relying on HTML’s (limited) tools such as links and forms.

Single Page Applications: A Browser Within the Browser

The web development industry dove headlong into this path, resulting in what we know today. The contents of your browser’s viewport are entirely managed by JS code. HTTP requests are sent by JavaScript, and responses are processed by JavaScript. History, caching, routing, and scrolling management are all handled via JavaScript. Essentially, we’ve ended up with a browser within the browser.

To achieve this, JavaScript applications have turned into heavy clients, specific to each application. They retrieve data from APIs, which turned into the HTTP/JSON APIs we’re so familiar with today because they only have to manage data.

APIs: Their Strengths and Limitations

This architecture, with a dedicated frontend and an API solely managing data, has created several opportunities:

This is the main advantage of a data-oriented API. It enables various features for diverse users. However, you only benefit from these advantages by adhering to all best practices of product management, including:

You Don’t Always Need This

The problem with the web industry today is that we adopt this architecture far too readily without asking, “Do I need these benefits? Is the cost worth it?”

There are plenty of situations where we could simplify things. If your backend has only one consumer, and that consumer is under your control (such as when a team is building a full-stack product), you can skip backwards compatibility for changes. You can forego user documentation for your API in favor of global documentation for the application. You might even replace JSON with binary formats like Protobuf.

Go Back to Documents (Without Sacrificing Interactivity)

Modern frameworks are over-equipped to interact with JSON data APIs. However, it’s perfectly possible to build an application based on HTML document exchange. Many applications are still built with Ruby on Rails, for instance, leveraging HTML forms, links, and server-side rendering.

The Single-Page Application trend gained popularity partly because it allowed developers to avoid full page reloads during navigation or form submissions. HTMX has been generating buzz recently precisely because it enables bypassing full document reloads. At the same time, it sticks to a document-based approach for browser/server interactions. This eliminates the need to retrofit JSON API constraints. Additionally, it dramatically reduces the amount of JavaScript required on the frontend.

This approach is perfectly suitable for many modern applications where client-side logic is minimal (e.g., management apps with lots of forms, dashboards, etc.)2.

API as an Implementation Detail

Even within the JavaScript ecosystem, it’s possible to avoid an HTTP/JSON API (in the sense of a separate API with the constraints mentioned earlier). React Router/Remix loaders, the $server primitive in Qwik, and React Server Components all bring the client and server closer, making the JSON API between the two merely an implementation detail3.

For frameworks that don’t offer this, hiding the HTTP API often involves code generation. Server methods (Controllers) become JavaScript functions to use in your frontend app following an automated code generation process (e.g., based on OpenAPI or Protobuf). Changing a server-side method allows you to use the new version client-side without thinking about “HTTP requests.”

In all these cases, there’s still an HTTP API between the client’s browser and the server, but you’re not coding it or calling it explicitly. You lose some of the benefits mentioned earlier (like calling this API from another app easily), but you also avoid the constraints of treating an API as a “product.”

The Back for Front Pattern

Sometimes, your application’s backend isn’t under your control. Maybe it’s managed by another team, maybe it’s a third-party product, or maybe it’s exposed to other consumers as a product. In such cases, the constraints of backward compatibility, documentation, etc., exist de facto.

Here, introducing a server component between your frontend and this API can be useful. This component is dedicated to your application (so it can evolve without restrictions) and provides the benefits of a server like shared caching, server-side validation, authentication, algorithmic performance improvements, etc.

This pattern is known as Back for Front and is, in my opinion, still underutilized.

Conclusion

For your next web application, pause before reaching for the REST/JSON API weapon.

  1. Ask the right questions: Who depends on my backend? How many applications? Who controls them?
  2. Consider dropping the client/server architecture entirely in favor of documents, perhaps with HTMX2.
  3. Treat your API as an implementation detail, just a way to traverse the network (the approach React, Next.js, Remix, and Qwik take, but one you can adopt too).
  4. If your API is beyond your control or has multiple clients, introduce a Back for Front so your application can benefit from a server under your control.

This approach does, however, have one prerequisite: stop separating frontend and backend developers. If they’re building the same product, they need to work together.


  1. XHR started appearing in browsers as early as 1999.

  2. For further details, see my talk on this subject at BreizhCamp 2024 (in french). 2

  3. See more in Ryan Florence’s “Mind the Gap” talk.