Thinking in Terms of Resources Instead of Tables

Thinking in Terms of Resources Instead of Tables
Image generated with ChatGPT

One of the most significant mental shifts in API design is moving away from database-driven thinking. We often start by designing APIs around tables, schemas, or ORM models. While this approach may feel natural, it leads to brittle APIs that expose internal structure and limit evolution in the future.

In REST, resources are the primary abstraction, not database tables or domain models.

What is a resource

A resource is anything that can be named and addressed. It represents a concept that is meaningful to the API consumer, not necessarily something that maps directly to a single table or object.

A resource can be:

  • A concrete entity such as a book or an author
  • A collection of entities
  • A computed or derived concept
  • A business process or workflow

For example, a library system may store authors across multiple tables and join them with books, publishers, and metadata. Exposing a single /authors resource allows clients to interact with the concept of an author without knowing how that information is stored internally.

Why tables make poor API contracts

When APIs are built directly on top of database schemas, internal decisions become external commitments. Renaming a column, splitting a table, or changing relationships suddenly becomes a breaking change for clients.

This creates a dangerous form of coupling. Clients are forced to understand implementation details they should never care about, and backend teams lose the freedom to refactor or optimize.

A resource, by contrast, is an abstraction layer. It allows the backend to change while preserving a stable contract for consumers.

Resources reflect business language

Good resource design starts with business language, not technical vocabulary. If users talk about books, loans, and waitlists, those concepts should appear in the API. Internal constructs like join tables, foreign keys, or cache layers should not.

Consider a waitlist for a book. Internally, it might be implemented using multiple tables or queues. From an API perspective, it is simply a resource associated with a book:

GET /books/{id}/waiting-list

The client doesn't need to know how the waitlist is stored or processed. It only needs to understand how to interact with it.

Resources are shared contracts

Resources are not private implementation details. They are shared contracts between the API provider and its consumers. Once published, they are difficult to change without breaking clients.

This makes resource design one of the most important steps in API architecture. Time spent modeling resources correctly pays dividends later in reduced friction, clearer documentation, and more resilient systems.

Designing resources is not about perfection. It is about choosing abstractions that make sense today while leaving room for change tomorrow.

This is part of a series about REST and APIs I've been working on for a while, if you like what you read or resonate with my opinions please subscribe, it's free!