
TLDR: Key Takeaways
- Pagination, filtering, and rate limiting are not nice-to-haves. They are essential from day one or your API will collapse under real usage.
- Use cursor-based pagination instead of offset pagination for any dataset that changes frequently.
- Version your API from the start (URL path versioning like /v1/ is simplest and works for most teams).
- Consistent error responses with proper HTTP status codes save your API consumers hours of debugging time.
- Cache aggressively at the HTTP level. Most API responses do not change every second, and proper cache headers can cut server load by 60-80%.
There is no shortage of API design guides on the internet. Most of them will tell you to use nouns for resources, keep URLs predictable, and return proper HTTP status codes. That is fine advice, but it is also the easy part. The hard part is building an API that does not fall over when real users start hitting it at scale.
This guide focuses on the practical decisions that matter most when you are building APIs that need to handle thousands of requests per minute and serve as the backbone of production applications.
Pagination Is Not Optional
If your API returns a list of resources, it needs pagination from day one. Returning unbounded result sets is the single fastest way to bring down an API. Even if your database only has 50 records today, it will have 50,000 next year, and that endpoint that worked fine in development will start timing out in production.
Use cursor-based pagination for any dataset that gets frequent inserts or updates. Offset-based pagination (page=2&limit=20) breaks when records are added or deleted between page requests, leading to duplicate or missing results. Cursor-based pagination (after=cursor_abc123&limit=20) is stable regardless of how the underlying data changes.
Rate Limiting Protects Everyone
Rate limiting is not just about protecting your server from abuse. It is about ensuring fair access for all consumers and preventing a single misbehaving client from degrading the experience for everyone else.
Implement rate limiting with clear response headers: X-RateLimit-Limit (the maximum), X-RateLimit-Remaining (how many are left), and X-RateLimit-Reset (when the window resets). When a client exceeds the limit, return a 429 status code with a Retry-After header. This is table stakes for any production API.
Versioning Strategy
You will need to make breaking changes to your API. It is not a question of if, but when. Having a versioning strategy from the beginning saves enormous pain later.
URL path versioning (/v1/users, /v2/users) is the simplest approach and works well for most teams. It is explicit, easy to understand, and easy to route. Header-based versioning is more "pure" from a REST perspective but adds complexity for API consumers who need to remember to set headers on every request.
Error Responses That Actually Help
A good error response tells the consumer exactly what went wrong and what they can do about it. A bad error response returns a generic message and makes them guess.
Every error response should include: an HTTP status code that accurately reflects the error category (400 for client errors, 500 for server errors), a machine-readable error code that the consumer can handle programmatically, a human-readable message that describes what happened, and for validation errors, a list of specific fields that failed with the reason for each failure.
Caching Is Your Best Friend
Most API responses do not change every second. A product catalog, a user profile, a list of categories: these resources might change a few times per day. But without caching headers, your server regenerates the same response for every single request.
Use Cache-Control headers to tell clients and CDNs how long a response is valid. Use ETags so clients can make conditional requests that return 304 Not Modified without transferring the full response body. Proper HTTP caching can reduce your server load by 60-80% for read-heavy APIs, which is most APIs.
Database Query Optimization
The most common API performance bottleneck is the database. N+1 queries, missing indexes, and full table scans will make your API slow no matter how fast your application code is. Use query logging in development to catch inefficient patterns early. Add database indexes for any column used in WHERE, ORDER BY, or JOIN clauses. Use eager loading to prevent N+1 queries when loading related resources.
At Stunzer Digital, we build APIs that are designed for production from the first commit. Pagination, rate limiting, versioning, and caching are part of our standard API architecture, not afterthoughts. If you are building an API that needs to scale, we can help you get the foundation right.
Tags
Related service
Want this built? See how we work on Web Development.


