To design a safe API for concurrent requests, I would implement locking mechanisms to prevent race conditions. This might involve using mutexes or semaphores if the API is stateful, or employing optimistic concurrency control techniques such as versioning for stateless APIs.
In depth
When designing an API that allows concurrent modifications to shared resources, it's critical to ensure data integrity and prevent race conditions. Using locking mechanisms, such as mutexes or semaphores, can help manage access to shared resources by allowing only one request to modify them at a time. However, this can lead to performance bottlenecks if not carefully managed. Alternatively, optimistic concurrency control can be used, where each modification checks if the resource version has changed since it was read, allowing for safe updates without global locks. This approach is often preferred in distributed systems where scalability is vital, but it requires proper error handling for cases where a conflict occurs due to concurrent updates. Understanding the trade-offs between these techniques is essential for effective API design.
Example scenario
In a microservices architecture for an e-commerce application, we designed an API endpoint that allows users to update product stock levels. We used optimistic concurrency control, where each request to update stock includes a version number. When a request is made, the service checks if the version matches the current value in the database. If it does, the update proceeds; if not, an error response is returned. This allowed multiple services to update product stocks simultaneously without causing data corruption, ensuring high availability and responsiveness.
Common mistakes
One common mistake is neglecting to consider the implications of concurrent access, leading to race conditions that can corrupt data or produce unexpected results. Developers might also overuse locking mechanisms, which can lead to performance issues and deadlocks, especially under high concurrency. Another mistake is failing to implement proper error handling for optimistic concurrency control, which can confuse users when they attempt to update resources that have changed since they were read.
Follow-up questions
- What are the advantages of using optimistic concurrency over pessimistic locking?
- How would you handle conflicts if two requests modify the same resource?
- Can you describe a scenario where a locking mechanism might be necessary?
- What strategies would you use to test your API under concurrent load?

Preparing for a system design interview?
- A 7-step method for answering any system design question, plus estimation numbers
- 5 worked designs: URL shortener, rate limiter, chat, news feed and file storage
- Guides to caching, databases, queues, consistency and reliability, with a 4-week study plan
- 306 practice questions with answers on caching, databases, queues, microservices, APIs and more
5 worked designs, a 4-week plan and 306 practice questions with answers.
The material stays free to read online. This is the organised, offline, print-ready PDF edition. Secure payment by PayPal; your personal download link is emailed after payment is confirmed. Digital product, no shipping.