When Should You Use Fine‑Grained vs Coarse‑Grained Resources in REST APIs?

This article explains how to choose between fine‑grained and coarse‑grained resource designs in REST APIs, illustrating trade‑offs with blog‑post examples, showing how to model business processes as intent resources, and discussing the impact of avoiding PUT in favor of CQRS.

JavaEdge
JavaEdge
JavaEdge
When Should You Use Fine‑Grained vs Coarse‑Grained Resources in REST APIs?

Preface

“The core abstraction of information in REST is the resource. Anything that can be named can be a resource: documents, images, temporary services, collections, non‑virtual objects, etc.” – Roy Fielding.

Resources form the foundation of any REST API. Resource identifiers (URIs), representations, and HTTP methods are built around the resource concept. Properly modeling resources at the right granularity ensures that API consumers get the needed functionality while keeping the API maintainable.

1 Fine‑Grained vs Coarse‑Grained Resources

Designing APIs around very fine‑grained resources leads to many endpoints and frequent client‑server interactions, increasing load and complexity. Conversely, overly coarse‑grained resources that try to do everything can become hard to use and maintain. A blog‑post API illustrates the trade‑off:

Multiple fine‑grained endpoints for title, content, images, tags, etc., causing many HTTP requests.

A single coarse‑grained endpoint that creates a post with all fields in one request, reducing server load.

However, using a single coarse‑grained Post resource for actions like “like” or “comment” forces the provider to interpret intent from the payload, adding complexity on both sides.

1.1 Preventing Business Logic from Leaking to API Consumers

Fine‑grained APIs push business rules (e.g., a post must have tags, images must be present before tagging) onto the client. This creates consistency problems when requests succeed or fail out of order, and it ties client code to server‑side domain knowledge, making updates costly across many consumer types.

Coarse‑grained designs keep business logic on the server, shielding consumers from internal rules and reducing the need for client‑side changes when the domain evolves.

2 Business‑Process‑Oriented Coarse‑Grained Aggregate Resources

Complex workflows can be modeled as resources themselves. For example, a “CustomerEnrollment” resource represents the whole onboarding process, while a “ChangeOfAddress” resource captures an address‑change event with full audit data. Modeling such intent resources keeps the API expressive and decouples clients from low‑level domain details.

2.1 Moving Away from CRUD

Two approaches to updating a customer’s address:

Directly PUT to the Customer or Address resource, which discards valuable event data and couples the client to the domain model.

POST to a ChangeOfAddress intent resource, preserving who made the change, when, and what changed, while keeping the client agnostic to internal structures.

This shift ensures that only the service that owns the state can modify it, and optional event persistence can be decided based on business value.

2.2 Nouns vs Verbs

Choosing noun‑based resource names (e.g., CustomerEnrollment) aligns API design with business language, making it easier to query the current state of a long‑running process and to evolve the underlying implementation without breaking clients.

2.3 Concretizing Abstract Concepts

Examples:

Cash deposit in a bank modeled as a Transaction resource rather than directly updating an Account.

Money transfer between accounts modeled as a MoneyTransfer or Transaction resource, allowing the operation to be tracked as a distinct entity.

These concrete resources act as transaction boundaries and can be queried independently of the low‑level account resources.

3 “No‑PUT” REST and CQRS

Replacing PUT updates with POST to intent resources aligns with event sourcing and naturally separates command (C) and query (Q) sides. Clients POST a ChangeOfAddress resource, then later GET the updated Customer view, accepting eventual consistency while preserving rich event data.

4 Example from GitHub Public API

GitHub’s API demonstrates balanced granularity: a Forks sub‑collection lets you list or create forks (coarse‑grained), while low‑level resources like Tag remain available for detailed operations.

5 Conclusion

There is no one‑size‑fits‑all solution. Simple data retrieval (e.g., account balance) can use fine‑grained resources, whereas complex workflows (e.g., fund transfers, enrollment) benefit from coarse‑grained, intent‑oriented resources. Choose the granularity that matches business needs, technical constraints, and maintenance considerations to deliver the best consumer experience.

api-designCRUDrestCQRSresource modeling
JavaEdge
Written by

JavaEdge

First‑line development experience at multiple leading tech firms; now a software architect at a Shanghai state‑owned enterprise and founder of Programming Yanxuan. Nearly 300k followers online; expertise in distributed system design, AIGC application development, and quantitative finance investing.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.