This cheatsheet provides a concise list of design principles and mobile-specific optimizations for building robust RESTful APIs. In a system design interview, demonstrating these patterns shows your ability to build scalable systems that thrive under mobile constraints (high latency, limited bandwidth, and flaky reliability).
Your Goal: Proactively suggest these optimizations to show you prioritize the mobile user experience.
REST APIs are based on resources (nouns), not actions (verbs).
- Do Use Nouns, Not Verbs: URIs should represent entities.
- Good:
GET /users,POST /orders - Bad:
GET /getUsers,POST /createOrder
- Good:
- Do Use Plural Nouns: Keep resource names consistent, typically plural.
GET /users/123(Read user 123)GET /users(List all users)
- Do Use Hierarchy: Use nesting to indicate relationships, but avoid deep nesting.
- Good:
GET /users/123/orders - Avoid:
GET /users/123/orders/456/items/789(Too deep; preferGET /orders/456/items).
- Good:
- The Signal: Shows you understand standard REST architectural patterns and can design intuitive, predictable interfaces.
Use standard HTTP methods and status codes for their intended purpose.
| Method | Action | Safety | Idempotency | Description |
|---|---|---|---|---|
| GET | Read | Safe | Yes | Retrieve data. Should never modify state. |
| POST | Create | Unsafe | No | Create a new resource. Not idempotent by default. |
| PUT | Replace | Unsafe | Yes | Replace a resource entirely. |
| PATCH | Update | Unsafe | No* | Partial update. (*Can be designed to be idempotent). |
| DELETE | Delete | Unsafe | Yes | Remove a resource. |
Avoid inventing custom error codes. Do use standard status codes to control client flow.
-
2xx (Success):
200 OK,201 Created(for POST),204 No Content(for DELETE). -
3xx (Redirection):
301 Moved Permanently,304 Not Modified(Critical for mobile caching). -
4xx (Client Error):
400 Bad Request,401 Unauthorized(auth missing),403 Forbidden(auth present but insufficient),404 Not Found,429 Too Many Requests. -
5xx (Server Error):
500 Internal Server Error,503 Service Unavailable. -
The Signal: Demonstrates you know how to leverage the HTTP protocol correctly, which is crucial for caching and intermediate proxies.
Demonstrate your mobile expertise by explicitly optimizing for the realities of cellular networks: limited bandwidth, high latency, and battery constraints.
APIs evolve, but mobile apps are not updated instantly.
- Strategy: URI Versioning (
GET /v1/users) is recommended for mobile. - Pros: Explicit, easy to test, easy to cache.
- Cons: "Pollutes" the URI.
- The Signal: You understand that old app versions will exist in the wild for years and must continue to function.
Finding the balance between "one request for everything" and "many small requests" is key.
- Over-fetching: Getting too much data.
- Solution: Field Selection. Allow clients to specify exactly what they need:
GET /users/123?fields=id,name,avatar_url.
- Solution: Field Selection. Allow clients to specify exactly what they need:
- Under-fetching: Getting too little data, requiring subsequent requests (N+1 problem).
- Solution: Resource Embedding. Allow clients to include related resources:
GET /orders/123?embed=items,payment_details.
- Solution: Resource Embedding. Allow clients to include related resources:
- The "Backend for Frontend" (BFF) Pattern: Ideally, mention creating a dedicated API layer specifically for the mobile app that aggregates data from multiple microservices into a single, mobile-optimized response.
Keep the base resource URL clean and use query parameters.
- Filtering:
GET /users?role=admin - Sorting:
GET /users?sort=-created_at(-for descending) - Searching:
GET /users?q=alex
Mobile networks are flaky. A POST request (e.g., "Pay $10") might time out. The user retries.
- How to Generate Keys: The client should generate a unique key (typically a UUID v4) for every critical mutation request.
- Where to Include: Pass this key in a custom HTTP header, e.g.,
Idempotency-KeyorX-Request-ID. - Server Logic:
- Check shared cache/DB for the key.
- If Seen: Return the cached response.
- If New: Execute logic and store result.
- The Signal: You know how to build resilient systems that handle network failures gracefully without duplicating transactions.
Protect your backend from abuse and spikes.
- Response Headers: Return
X-RateLimit-RemainingandX-RateLimit-Resetso the app can back off intelligently. - Status Code: Return
429 Too Many Requests.
- Do always use ISO 8601 strings:
2023-10-27T10:00:00Z. - Do always store and return dates in UTC. Let the mobile client handle local time formatting.
- HTTPS: Mandatory. No exceptions.
- Authentication: Use
Authorization: Bearer <token>(e.g., JWT). Avoid passing tokens in URL parameters. - Input Validation: Validate all input on the server side. Never trust the client.
When using API keys to identify the client application:
- Do Use Headers:
X-API-Key. Headers are less likely to be inadvertently logged than URLs. - Avoid Query Parameters:
/resource?api_key=xyz. URLs are logged in cleartext by proxies. - Mobile Reality: Treat any key embedded in the app as public. Use them for rate limiting, not sensitive permissions.
- Rate Limiting: Aggressive limiting per IP/User.
- App Attestation: Use Google Play Integrity / Apple App Attest to ensure requests come from your genuine app binary.
- WAF: Use a Web Application Firewall to block suspicious traffic patterns.
Return consistent, structured errors.
{
"error": {
"code": "USER_ALREADY_EXISTS", // Machine-readable
"message": "A user with this email already exists.", // Human-readable
"details": [
{ "field": "email", "issue": "duplicate" }
]
}
}- The Signal: You prioritize the developer experience (DX). Structured errors allow the mobile app to parse specific issues and show localized, helpful UI messages.
- Tunneling: Sending everything via
POST. (Breaks caching). - Returning 200 OK for Errors: Breaks HTTP-aware clients and monitoring tools. Use 4xx/5xx.
- Verbs in URIs:
POST /createOrder. (UsePOST /orders). - Chatty APIs: Designing endpoints that require N+1 requests. Fix with Compound Documents.
- Inconsistent Naming: Mixing
camelCaseandsnake_case. Pick one. - Leaking Internals: Returning raw SQL exceptions to the client.
- Missing Pagination: Returning all records in a single response (
GET /users). Always paginate lists.
- Stripe (Idempotency): Uses
Idempotency-Keyheader to safely retry payment creation requests. (Source)- Signal: Mentioning this shows you understand financial-grade reliability.
- Twitter (Versioning): Uses distinct API versions (
/1.1/,/2/) to allow radical architectural changes (like moving from Monolith to Microservices) without breaking clients. (Source) - GraphQL (Facebook): While REST is standard, mentioning GraphQL for "Mobile-Specific Data Fetching" (solving over-fetching) shows breadth of knowledge. (Source)
- Define Resources: Identify the nouns (Users, Tweets).
- Select Methods: Map actions to HTTP verbs (GET, POST).
- Optimize for Mobile: Add Versioning, Pagination, and Partial Response (BFF).
- Handle Failure: Define Error formats and Idempotency keys.
- Secure It: HTTPS, Auth headers, Rate Limiting, and Attestation.