Concurrency Lessons: Building Trust in Systems
In the realm of backend engineering, concurrency is a critical aspect that determines the efficiency, reliability, and scalability of a system. A recent project by a developer aimed to create a Node.js task runner capable of running tasks concurrently, retrying failures, and never overloading the system. However, the journey was not as straightforward as initially anticipated.
Understanding Tasks and Promises
The developer's realization that a task is not a promise but a function that returns a promise was a game-changer. This design choice eliminated issues like stale promises, broken retries, and phantom concurrency bugs, making the system more robust and reliable.
Mocking Reality for Testing
To test the system's behavior under various conditions, the developer created a fake API that mimicked real-world scenarios. This allowed for the testing of durations, failures, and concurrency pressure, providing a more accurate representation of the system's performance.
Enforcing Engineering Discipline
The crux of the project lay in enforcing three key laws: concurrency as a hard ceiling, deterministic retries, and a system that ends in either success or retry exhaustion. Adhering to these principles ensured the system's stability and reliability.
The Power of Controlled Failure
A pivotal moment in the project came when the logs started showing controlled failures. This was not a sign of system malfunction, but rather an indication that the system was behaving as intended, demonstrating the importance of controlled failure in building robust systems.
Lessons for North East India and Beyond
The insights gained from this project are applicable not only to the developer's personal projects but also to larger systems in the North East region and across India. By understanding the nuances of concurrency, retries, and system behavior, engineers can build more reliable, cost-effective, and scalable systems.
A New Perspective on Concurrency
This project served as a stepping stone for the developer, pushing him from a focus on learning async to a deeper understanding of system behavior. As we continue to navigate the complexities of backend engineering, it is essential to approach problems with a system-level perspective, focusing on governance, discipline, and truth.