N
Naveen.dev
Chapter 06
6 min read2026-06-17

sample

Build maintainable APIs with proper resource modeling, pagination, rate limiting, and backward compatibility patterns.

A well-designed REST API is intuitive, scalable, and evolves gracefully without breaking existing clients. This guide covers the principles and patterns for building production-grade APIs.


REST Principles Recap

REST (Representational State Transfer) is an architectural style built on HTTP. Key principles:

  1. Client-Server: Clear separation of concerns.
  2. Statelessness: Each request is independent; no session state on server.
  3. Cacheable: Responses should define themselves as cacheable or not.
  4. Uniform Interface: Consistent API design across resources.

Dialog vs rendering in AEM process
Dialog vs rendering in AEM process

Resource Modeling

Design your API around resources, not actions.

✅ Good (Resource-Oriented)

POST   /users                 # Create a user
GET    /users                 # List all users
GET    /users/{id}            # Get a specific user
PUT    /users/{id}            # Update a user
DELETE /users/{id}            # Delete a user
GET    /users/{id}/posts      # Get posts by a user
POST   /users/{id}/posts      # Create a post for a user

❌ Bad (Action-Oriented)

POST   /createUser
GET    /getUser/{id}
POST   /updateUser
POST   /deleteUser/{id}
GET    /getUserPosts/{id}

HTTP Status Codes

Use status codes correctly to communicate request outcomes:

| Code | Meaning | When to Use | |---|---|---| | 200 | OK | Successful GET, PUT, DELETE | | 201 | Created | Successful resource creation (POST) | | 204 | No Content | Successful request with no response body | | 400 | Bad Request | Invalid input, malformed JSON | | 401 | Unauthorized | Missing/invalid authentication token | | 403 | Forbidden | Authenticated, but lacks permission | | 404 | Not Found | Resource doesn't exist | | 429 | Too Many Requests | Rate limit exceeded | | 500 | Internal Server Error | Unrecoverable server error | | 503 | Service Unavailable | Server temporarily down (maintenance, overload) |


Pagination

For endpoints returning large result sets, use pagination to prevent overwhelming clients.

Offset-Based Pagination

GET /users?limit=20&offset=40
  • Simple to implement.
  • Problem: Cursor instability. If a new user is inserted, offsets shift.
GET /users?limit=20&cursor=eyJpZCI6IDUwfQ==
  • Cursor encodes the position in the result set (e.g., encoded {"id": 50}).
  • Advantage: Stable across concurrent inserts/deletes.
  • Usage: Social media feeds, real-time data streams.

API Versioning

As your API evolves, you'll need to support multiple versions for backward compatibility.

1. URL Path Versioning

GET /v1/users
GET /v2/users  # Different response schema
  • Pros: Clear, explicit.
  • Cons: Duplicate code, maintenance overhead.

2. Header Versioning

GET /users
Header: API-Version: 2
  • Pros: Cleaner URLs, versioning is metadata.
  • Cons: Less discoverable (clients must know about header).

3. Query Parameter Versioning

GET /users?api_version=2
  • Pros: Easy for debugging (visible in URL).
  • Cons: Verbose, clutters query parameters.

Deprecation Strategy

  • Announce deprecation 6-12 months before removal.
  • Return Deprecation and Sunset headers.
  • Migrate high-volume clients proactively.

Rate Limiting

Protect your API from abuse and ensure fair resource allocation.

Token Bucket Algorithm

  • Each client gets a "bucket" of tokens.
  • Each request consumes 1 token.
  • Tokens regenerate at a fixed rate (e.g., 100 tokens/minute).
  • If bucket is empty, reject request (429 Too Many Requests).

Response Headers

HTTP/1.1 200 OK
RateLimit-Limit: 1000
RateLimit-Remaining: 999
RateLimit-Reset: 1618329600

Error Handling

Return consistent, actionable error responses.

Good Error Response

{
  "error": {
    "code": "INVALID_EMAIL",
    "message": "The provided email is not a valid format",
    "details": {
      "field": "email",
      "received": "not-an-email"
    }
  }
}

Bad Error Response

{
  "error": "Something went wrong"
}