Stop Forcing REST onto Domain-Driven Architectures
Many teams struggle applying REST in domain-driven systems, often leading to complexity. Discover why RPC-style APIs are a better fit for these architectures.
Understanding REST vs. Domain-Driven Design Conflicts
For years, I've seen teams struggle to mesh REST principles with domain-driven architectures. Initially, they establish clean REST endpoints. However, as business requirements evolve, these designs get compromised. Eventually, most REST principles are dropped as complexity soars. This pattern isn't accidental; it's due to a fundamental clash between REST's assumptions and domain-driven design's realities.
Why Doesn't REST Mesh Well with Domain-Driven Design?
REST focuses on resource-centric views, assuming globally consistent entities. In contrast, domain-driven design (DDD) centers on bounded contexts and business capabilities, challenging REST's global resource navigation.
For instance, in DDD:
- A
Userin the Orders context might have{id, shippingAddress}. - The same user in the Identity context could be
{id, email, preferences}.
This variance complicates RESTful API implementation. If the Orders service needs customer info, who owns the user representation? It can't be the Orders service, as user data falls under the Identity service.
How Do Teams End Up Compromising REST Principles?
Faced with these challenges, teams often dilute REST principles to keep REST-like endpoints, leading to complex solutions like:
- Adding context prefixes:
/orders/api/users/{userId}/orders - Using domain-specific naming:
/orders/customers/{customerId}/orders - Treating cross-context queries as searches:
/orders/search?customerId={id}
Some opt for gateway routing, which maps clean URLs to internal paths, e.g., /users/{id}/orders to /orders-service/customers/{id}/orders. This, however, can introduce fragile configurations and expose incorrect user models to clients.
Why Does REST Struggle with Complex Business Operations?
REST shines with operations that neatly fit CRUD actions. But complex business tasks, like "partially canceling an order for specific items," don't align well. Teams try to fit these into REST by:
- Misusing
PATCH /orders/{id}/line-itemswith unclear request bodies. - Employing
POST /orders/{id}/partial-cancel, which veers off REST norms. - Creating artificial resources that reflect workflows, not real entities.
These approaches deviate from REST's core principles, obscuring operations or pretending they're resource-based.
When Is REST Most Effective?
Despite its limitations, REST has benefits in certain scenarios:
- Caching: Reduces server load through HTTP caching.
- Hypermedia: Allows clients to dynamically discover capabilities.
- Uniform interface: Facilitates the use of generic tools across APIs.
Yet, domain-driven systems seldom gain from these advantages. For example, caching /orders/12345 doesn't account for business events like cancellations or shipments, making cached data quickly obsolete.
Many REST implementations stem from tutorials focused on HTTP, JSON, and resource URLs, missing the architectural depth that gives REST its strength. This often leads to HTTP-based RPC that mimics REST without harnessing its full potential.
Why Are RPC-Style APIs More Suited to Domain-Driven Design?
RPC-style APIs align API design with business operations through explicit, verb-based endpoints like /orders/cancel, /orders/refund, and /orders/split-shipment. This removes the need to translate domain operations into API structures.
RPC endpoints also simplify documentation. Compare POST /orders/cancel with PUT /orders/{id}, where the latter could mean updating status, adding items, or changing shipping details based on the request body. The generic update endpoint complicates client interactions with a uniform interface.
Conclusion: Choosing the Right Architecture
REST suits entity-driven systems with consistent global resources, perfect for CRUD operations like media libraries or inventory systems. However, for domain-driven systems with bounded contexts and complex operations, RPC-style APIs are a better fit.
To improve your system design:
- Adopt explicit, verb-based endpoints mirroring business capabilities.
- Avoid cramming operations into resource updates.
- Recognize that different bounded contexts need unique resource definitions.
Understanding REST's limitations in domain-driven designs enables developers to craft clearer, more effective, and purpose-aligned APIs.
Related Articles
Top Highlights from Git 2.52: New Features for Developers
Explore the key features and enhancements in Git 2.52, including improved performance, new functionalities, and user experience upgrades for developers.
Nov 22, 2025
Should We Even Have :closed? Exploring CSS State Management
Explore the debate around the CSS pseudo-class :closed. Is it necessary or does :not(:open) suffice? Dive into coding insights and best practices.
Nov 21, 2025
Build a Multi-Tenant RAG with Fine-Grain Authorization
Discover how to build a multi-tenant RAG system with fine-grained authorization, inspired by Stardew Valley. Perfect for developers looking to enhance their applications!
Nov 21, 2025
