Xin Ji

A Personal Journal

← Back Home

2025-08-14

The Barista Who Never Waits: The Unsung Revolution of Non-Blocking I/O

Imagine a coffee shop during the morning rush. But this coffee shop has a strange rule: the single barista must serve one customer from start to finish before even looking at the next person. He takes an order, grinds the beans, pulls the espresso shot, steams the milk, and hands over the latte. Only then does he turn to the next person in the ever-growing line. This is blocking I/O, and for decades, it’s how most web servers operated. It was simple, logical, and created a massive digital traffic jam.

This is the story of the simple, yet revolutionary, idea that changed everything: what if the barista didn't have to wait?


The Old World: One Task, One Worker

In the early days of the internet, servers handled requests like our one-track-minded barista. A popular web server like Apache used a model where each new connection was assigned its own worker (a process or a thread). If you had 500 visitors, you had 500 workers.

This worked fine at first. But there was a hidden problem. A worker’s most time-consuming job wasn’t thinking; it was waiting. It waited for the user’s slow network to send the request, or it waited for the hard drive to find a file. While waiting, the worker—and the precious CPU and memory it occupied—did absolutely nothing. It was like paying 500 baristas to stand around, each waiting for their single espresso shot to pull. As websites grew more popular, this model led to server meltdowns. The industry gave this challenge a name: the C10k problem (handling ten thousand concurrent connections).


The Hardware Enabler and an Ancient Idea

The seeds of the solution were planted long before the web existed. The concept of non-blocking I/O first appeared in early operating systems in the 1970s. The first widely-used implementation was the select() system call, introduced in BSD Unix in 1983.

select() was like giving our barista a superpower: the ability to ask, "Are any of my coffee machines ready?" He could glance at a list of 100 machines and instantly see which ones had a finished espresso shot. He could start a task, move on to another, and then come back to the first one the moment it was ready.

For years, this tool was a niche technique used for specialized applications. However, in the late 1990s, hardware evolution forced it into the spotlight. CPUs had become incredibly fast, but network and disk speeds hadn't kept up. The gap between a CPU’s processing speed and the time it took to get data from a network or disk became a chasm. The problem was no longer CPU power; it was the crippling idleness caused by I/O wait. The world was full of super-fast workers waiting on super-slow tasks. The time was ripe for a new way of thinking.


The Nginx Success Story: David vs. Goliath

In the early 2000s, a Russian engineer named Igor Sysoev was working for the search engine and portal Rambler. He was tasked with solving the C10k problem. Instead of trying to optimize Apache, he decided to build a new server from the ground up, based entirely on the non-blocking philosophy. He called it Nginx (pronounced "Engine-X").

Nginx was designed to be the ultimate multitasking barista. It operated with a small, fixed number of worker processes. A single Nginx worker could handle thousands of connections simultaneously. How? By using a highly efficient evolution of select() called epoll() (on Linux).

Here’s the magic:

  • A request comes in. The Nginx worker accepts it and asks the operating system (the coffee machine) to start the task, like reading a file.
  • Instead of waiting, the worker immediately moves on to handle another request.
  • When a task is complete (the file is ready to be sent), the operating system notifies the Nginx worker. The worker then grabs the finished task and sends the data back to the user.

There is zero waiting. The worker is always busy, either starting new jobs or handling finished ones. This event-driven, non-blocking architecture meant Nginx could manage a massive number of connections with a tiny memory footprint. On the same hardware where Apache would crash under a few thousand connections, Nginx would happily serve tens of thousands.

Initially, Nginx was a well-kept secret among high-traffic Russian sites. But its incredible performance and stability couldn't stay hidden. Word spread, and by the end of the decade, it had exploded in popularity. Today, Nginx powers over a third of the world's websites, including giants like Netflix, Airbnb, and Dropbox.

The principle of "don't wait" has since become the foundation of modern high-performance software, from Node.js on the backend to UI frameworks on the front end. It was a quiet revolution, born from an old idea and a new necessity, that is responsible for the fast, responsive web we use every day. All thanks to a simple rule: never, ever wait.