Overview

13 Designing an efficient API

Designing an efficient API is about helping consumers achieve their goals with the fewest calls and the least data, while keeping provider infrastructure lean and affordable. Inefficiency surfaces as long, sequential call chains, oversized payloads, battery and data-plan drain, and overloaded backends—issues that harm user satisfaction and business outcomes. Efficiency is a design concern (second only to security), but optimization should come after you’ve produced a clear, user-friendly, interoperable API and verified runtime basics: enable HTTP/2 (or compression and keep-alive with HTTP/1.1), set fair rate limits, expose informative rate-limit headers, and confirm the true root cause isn’t in infrastructure, databases, or code.

Making APIs efficient hinges on rethinking data and flows to fit real needs. Replace multi-step, client-assembled workflows with purpose-built operations that encapsulate business logic; enrich list models and right-size page limits to trim sequential calls; and only move data that matters. Use caching and conditional requests so the best call is the one that isn’t made: set explicit cache policies based on data volatility and context, return cache directives, and let consumers validate freshness with entity tags and 304-not-modified responses. Reduce payloads by letting consumers select models (via content negotiation or preferences) and fields, centralize repetitive code/label dictionaries, and prefer partial updates with JSON Merge Patch over full replacements. Finally, tune pagination: choose sensible defaults and maxima, and favor cursor-based pagination for volatile or large datasets unless random page jumps are a hard requirement.

Optimize call flows further with bulk operations that process many items at once. Design clear requests (IDs in bodies for updates, ID lists or filters for deletes), allow same-input bulk updates via filters, and choose an error policy that fits the domain—mixed (with per-item results and 207 Multi-Status) or all-or-nothing—documenting statuses, headers, and bodies per element when needed. Let clients control response volume in bulk outcomes (e.g., IDs only vs. full models) and restrict bulk features via dedicated scopes or endpoints. When deep, consumer-specific optimizations would contort a versatile business API, introduce an experience layer (such as a backend-for-frontend) that composes and tailors responses on top of reusable business APIs, keeping performance high without sacrificing clarity, reuse, or maintainability.

An API can negatively impact consumers with slow response times and high data volumes, as well as providers with costly overloaded infrastructure and massive total outbound data.
CH13 F01 lauret3
Creating a versatile API that does the job and is user-friendly and interoperable puts us on the right track. Still, we can improve data, operation, and flow design to be totally efficient.
CH13 F02 lauret3
The home screen information flow is slow due to numerous sequential calls, which stresses the infrastructure with up to 100 parallel calls. Also, three months of transactions mean a lot of data.
CH13 F03 lauret3
Due to relevant data additions and larger transaction list pages, the flow is faster and infrastructure-stress-free. However, the process may slow down with more owners and accounts, and the data volume remains substantial.
CH13 F04 lauret3
The real issue is delegating business logic to the consumer. It’s more efficient to create an operation that fulfills actual needs. It is fast and returns only necessary ready-to-use data.
CH13 F05 lauret3
The application must call the API to show data when it isn’t cached. When data is cached for 10 minutes, the application gets data from the cache, which may be inaccurate. Before using it, the application can call the API to ensure its cache is up to date.
CH13 F06 lauret3
The Cache-Control response header contains directives indicating if and how the returned data can be cached.
CH13 F07 lauret3
The If-None-Match header allows us to return data only if it has changed compared to the provided Etag value.
CH13 F08 lauret3
We can leverage a custom media type or preference to get the complete or summarized model on any read, list, or search operation.
CH13 F09 lauret3
If field selection is enabled, consumers can, for example, get only the account balance instead of all its data.
CH13 F10 lauret3
Updating the home address city with JSON Merge Patch requires sending the whole addresses array. With JSON Patch, we only describe the modification of the city property of the first element without the need to send the addresses array.
CH13 F11 lauret3
The bulk requests body contains the data of multiple resources (if any). If each element needs to be identified, the final path parameter is moved at each resource data level in the body (PATCH or PUT) or in a list query parameter (DELETE).
CH13 F12 lauret3
Each element of the bulk response contains the same data a unitary call would return. Response elements are ordered as in the request.
CH13 F13 lauret3
Possible design for all-or-nothing operations if we don’t care about element-specific HTTP statuses or headers. The errors list contains all errors of all errored elements.
CH13 F14 lauret3

FAQ

What are the telltale signs my API is inefficient, and what principles improve it?Common symptoms include long wait times from many sequential calls, over-fetching large payloads, repeated requests for the same data, and high outbound data cost. To improve: minimize the number of calls (especially sequential ones), return only necessary data, design list models that already contain the essentials, and avoid delegating business logic to clients. Favor purpose-focused operations that deliver ready-to-use data.
Before redesigning for performance, what runtime checks or config should I verify?Confirm the true root cause first. Verify HTTP/2 is enabled (or HTTP/1.1 with compression and keep-alive), load balancers are correctly configured, servers and networks are sized appropriately, and database indexes and queries are optimized. Many performance issues originate from infrastructure and databases rather than API design.
How should I enforce and communicate rate limits?Apply rate limiting at the gateway and return 429 Too Many Requests with a Retry-After header when limits are exceeded. Help clients be proactive with RateLimit and RateLimit-Policy headers (preferred over legacy X-RateLimit-* headers) to convey remaining quota and reset windows. Keep error details consistent with your shared error format.
How do I define safe, effective client-side caching?Do not let consumers invent caching rules. Define explicit policies per operation based on data composition, volatility, and usage context, and document them (e.g., in OpenAPI). Some data can be cached for a period; others must always be validated before use; some must not be cached at all. Align with security, business, and regulatory constraints.
Which HTTP headers enable caching and conditional reads?Use Cache-Control to express directives such as no-store, max-age, and no-cache. Provide an ETag so clients can validate with If-None-Match and receive 304 Not Modified when unchanged. When content negotiation affects representations, include Vary (e.g., Accept, Accept-Language). Optionally support If-Modified-Since.
How can I reduce payload size without hurting usability?- Let clients choose the model: via custom media types (e.g., application/vnd.example.summarized+json) or Prefer: model=summarized/complete. - Allow field selection (e.g., fields=balance or hypermedia-specific mechanisms like JSON:API sparse fieldsets). - Centralize redundant lookups (e.g., codes/labels) in dedicated endpoints that are cacheable. - Toggle returning bodies on create/update using Prefer (e.g., model=none or return-no-content). - Prefer partial updates (PATCH) over full replacements (PUT) to reduce ingress.
When should I use PATCH vs PUT, and do I need JSON Patch?Use PATCH (JSON Merge Patch) to send only changed fields; use PUT to replace the whole resource. JSON Merge Patch is simpler and widely adopted. Only consider JSON Patch for special array mutation cases; it adds complexity and is uncommon. If needed, support both via content negotiation, but default to JSON Merge Patch.
How do I set good pagination defaults and choose cursor vs offset?Pick a default page size that’s helpful yet conservative; let clients request from 1 up to a subject-matter-appropriate maximum. Cursor-based pagination generally performs better and avoids duplication/skips on changing datasets; choose it unless users must jump to arbitrary pages or your data/DB cannot support cursors. Document limits clearly.
How do I design efficient bulk operations and their responses?Allow creating/updating multiple items in one call (POST with a data array; PUT/PATCH with ids in each item; DELETE with ids or selection filters). Decide error policy: mixed (partial success) vs all-or-nothing. For mixed outcomes, return 207 Multi-Status with per-item status, headers, and body; for all-or-nothing, keep responses consistent and simple. Support Prefer: model to reduce response payloads. Restrict access via scopes or separate bulk endpoints.
When should I create a separate optimized API layer?If heavy optimizations make your API ultra-specific to a consumer, keep the business API versatile and introduce an experience API (e.g., a BFF) on top that aggregates and tailors responses. This preserves reuse while delivering performance for targeted clients. Coordinate architecture to avoid layer sprawl and duplication.

pro $24.99 per month

  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose one free eBook per month to keep
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime

lite $19.99 per month

  • access to all Manning books, including MEAPs!

team

5, 10 or 20 seats+ for your team - learn more


choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • The Design of Web APIs, Second Edition ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • The Design of Web APIs, Second Edition ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • The Design of Web APIs, Second Edition ebook for free