What is an API and how do you design it? 🗒️✅
About this video
### Summary: Designing Good APIs 1. **Definition of an API**: - An API (Application Programming Interface) is a documented way for external consumers to interact with your code. - It specifies *how* to interact with the code, not *how* the code works internally. 2. **API Example**: - Function: `GetAdmins(groupID: string)` - Possible Errors: Group doesn’t exist or is deleted. - Response: List of Admin objects (JSON format with name, userID, etc.). 3. **API as a Contract**: - An API defines what it will do, not how it will do it. - Similar to a function: Define return type, parameters, possible errors, and function name. 4. **Checklist for API Design**: - **Where should the API be exposed?** - In a microservice architecture, place the API in the relevant service (e.g., "group service" for group-related functions). - **What does the API do?** - Clearly define the action (e.g., `getAdmins`), parameters (e.g., `groupID`), and expected response. 5. **Common Mistakes in API Design**: - **Naming Issues**: - Ensure the API name reflects its exact purpose (e.g., `getAdmins` should only return admins, not additional data like groups). - **Unnecessary Parameters**: - Avoid adding extra parameters unless absolutely necessary. - Example: If `getAdmins` needs to check a list of users, rename it to `checkAdminsForGroupAndUserList`. 6. **Optimizing APIs**: - Additional parameters can sometimes be justified for performance optimization (e.g., reducing inter-service calls). - Even then, consider renaming the API to reflect the new functionality. 7. **Response Design**: - Avoid overloading the response with unnecessary data. - Provide only the information the caller needs to reduce network load and confusion. - Extensibility should not come at the cost of clarity. 8. **Error Handling**: - Define common expected errors (e.g., group doesn’t exist, group deleted). - Avoid returning generic errors for everything; take responsibility for expected issues. - Subjective decisions: Balance between strict error definitions and flexibility. 9. **HTTP Endpoint Design**: - Use proper routing (e.g., `/v1/getAdmins`). - Choose HTTP methods appropriately: - Use `GET` for fetching data (e.g., `/admins?groupID=123`). - Use `POST` for operations requiring payloads. - Avoid mixing routing with actions (e.g., don’t use ambiguous endpoints like `/chatMessaging`). 10. **Avoiding Side Effects**: - APIs should perform one specific task without unintended side effects. - Example: `setAdmins` should not create groups or add members unless explicitly designed for such behavior. - Break complex operations into multiple APIs if needed. 11. **Atomicity**: - Ensure atomicity (all-or-nothing behavior) for critical operations. - Example: If `setAdmins` fails after creating a group, handle cleanup or require explicit steps (e.g., create group first, then set admins). 12. **Handling Large Responses**: - **Pagination**: Let clients request data in chunks (e.g., first 10 members, next 10). - **Fragmentation**: Split large responses into smaller pieces, especially in internal protocols (e.g., microservices). - Use sequence numbers (e.g., TCP-like numbering) to indicate fragments and signal the end of the response. 13. **Consistency vs. Performance**: - Decide whether the API needs strong consistency (slower) or eventual consistency (faster). - Example: Reading admins while another admin is being added may result in inconsistent data, but this may be acceptable depending on the use case. 14. **Caching and Service Degradation**: - Use caching to reduce database load, but be aware that cached data may be slightly outdated. - Implement service degradation under high load by returning only essential data (e.g., user names instead of full profiles). 15. **Final Tips**: - Test APIs rigorously to ensure clarity, consistency, and performance. - Avoid confusing or overly generic APIs; prioritize clear naming and focused functionality. - Consider trade-offs between consistency, speed, and resource usage based on the application’s requirements. By following these principles, you can design robust, efficient, and user-friendly APIs.
Course: System Design Playlist
**Course Description: System Design Playlist** This comprehensive course, titled "System Design Playlist," is designed to provide students with a deep understanding of system design principles and practices through real-world analogies and technical explanations. The course begins by using the analogy of running a pizza restaurant to illustrate fundamental concepts in system design, such as optimizing processes, scaling resources, and ensuring resilience. Students will learn about vertical scaling—enhancing the capabilities of existing resources—and horizontal scaling—adding more resources to distribute the workload. Through this engaging example, participants will grasp essential strategies for improving throughput, eliminating single points of failure, and implementing backup systems to maintain operational continuity. As the course progresses, students will delve into advanced topics like microservice architecture, where responsibilities within a system are clearly defined and divided among specialized teams or services. This approach allows for efficient scaling and management of different components based on their specific needs. Additionally, the course covers distributed systems, highlighting the importance of fault tolerance and quick response times by strategically placing servers closer to users. Concepts such as load balancing, which intelligently routes requests to optimize performance, and decoupling systems to enhance flexibility and adaptability, are thoroughly explored. Participants will also learn about logging and metrics to monitor system health and make informed decisions. The course wraps up by contrasting high-level system design, which focuses on overarching architectural decisions, with low-level system design, which deals with the actual coding and implementation details. By mapping business scenarios to technical solutions, students will gain insights into designing scalable, reliable, and extensible systems. Whether you're new to system design or looking to deepen your expertise, this course equips you with the knowledge and tools needed to tackle complex design challenges and develop robust systems capable of meeting diverse user demands.
View Full Course