Building Scalable APIs: Lessons from the Field
After building APIs for startups that grew from zero to millions of requests, here’s what actually matters.
Start with the contract
Before writing any code, nail down your API contract. This sounds obvious, but it’s where most projects go wrong.
// Bad: vague, inconsistent
GET /getUsers
POST /user/create
DELETE /removeUser/123
// Good: RESTful, predictable
GET /users
POST /users
DELETE /users/123
Consistency beats cleverness. Your future self (and your API consumers) will thank you.
Pagination is not optional
Every list endpoint needs pagination from day one. “We’ll add it later” is technical debt that compounds fast.
interface PaginatedResponse<T> {
data: T[];
pagination: {
page: number;
limit: number;
total: number;
hasMore: boolean;
};
}
Rate limiting saves you
Implement rate limiting before you need it. When a client goes haywire (and they will), you’ll be glad you did.
We typically use:
- 100 requests/minute for authenticated endpoints
- 20 requests/minute for public endpoints
- Custom limits for heavy operations
Cache aggressively
Most API responses can be cached longer than you think. Use ETags and Cache-Control headers liberally.
Cache-Control: public, max-age=300
ETag: "abc123"
The performance gains are massive, and your database will breathe easier.
Observability from the start
Log everything. Trace everything. You can’t fix what you can’t see.
Every request should have:
- A unique request ID
- Timing information
- User context (if authenticated)
When something breaks at 3am, you’ll know exactly where to look.
These aren’t revolutionary ideas. They’re fundamentals that get skipped in the rush to ship. Don’t skip them.