{
  "id": 9978783,
  "title": "Epoll vs Select vs Poll: How the Linux Kernel Actually Handles 100k Concurrent Connections",
  "url": "https://urgent.news/2026/09/26/epoll-vs-select-vs-poll-how-the-linux-kernel-actually-handles-100k",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-09-26T12:36:17.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/syed_anzar/epoll-vs-select-vs-poll-how-the-linux-kernel-actually-handles-100k-concurrent-connections-3o89"
  },
  "original_language": "en",
  "account": "In 1999, Dan Kegel's paper \"The C10K Problem\" addressed the challenge of designing a web server capable of handling 10,000 concurrent client connections on a single machine. The traditional approach involved process-per-connection or thread-per-connection, as seen in Apache's prefork model. However, this model quickly became unmanageable due to stack memory overhead, context switching penalties, and I/O multiplexing bottlenecks.\n\nWith the rise of event-driven architectures such as NGINX, Node.js, Redis, and Netty, modern systems have shifted to handling 100,000+ persistent connections. This section provides a technical breakdown of how the Linux kernel handles I/O multiplexing at scale using epoll(7).\n\nThe limitations of select() and poll() are evident in their $O(N)$ architecture. Both mechanisms require user-space/kernel-space copying, kernel scans of all descriptors, and destructive mutations of bitmask arrays. This process becomes increasingly inefficient as connection counts rise.\n\nEpoll(7), introduced in Linux 2.5.44, resolves these scalability issues by introducing stateful event monitoring within the kernel. The epoll architecture consists of three system calls: epoll_create1(), epoll_ctl(), and epoll_wait(). These calls operate on three distinct data structures: a Red-Black Tree (rbr), a Ready List (rdllist), and an Epoll Item (struct epitem).\n\nThe rbr stores all monitored sockets as struct epitem nodes, allowing for efficient O(log N) operations such as lookups, insertions, modifications, and deletions during epoll_ctl() calls. The rdllist is a doubly-linked list containing only active sockets, while the Epoll Item represents each monitored socket descriptor and maintains a list of poll wait queues.\n\nThis design eliminates the need for destructive mutations and costly kernel-to-user copies, making epoll exceptionally efficient when handling large numbers of concurrent connections.",
  "summary": "In 1999, Dan Kegel published his classic paper on \"The C10K Problem,\" posing a simple question: how do you design a web server capable of handling 10,000 concurrent client connections on a single machine? At the time, the standard approach was process-per-connection or thread-per-connection. Web servers like Apache prefork spawned a dedicated thread or process for every active socket. That model…",
  "key_points": [
    "Linux kernel handles 100k+ connections via epoll(7)",
    "Introduces stateful event monitoring in kernel",
    "Uses Red-Black Tree, Ready List, Epoll Item data structures"
  ],
  "editors_take": null,
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}