Websites & apps

Event-driven vs process-based web servers: how they handle connections

Why Nginx, LiteSpeed and Caddy handle thousands of connections with little memory while classic Apache needs a process or thread each: the C10k problem, event loops, epoll and what it means for you.

IntermediateAll hosting3 min read

All web servers do the same job, but they differ in how they juggle many visitors at once. Process-based servers dedicate a process or thread to each connection; event-driven servers let a few workers handle thousands of connections each. This architectural difference explains most of the performance gaps between Apache, Nginx and LiteSpeed.

Before you start

The problem: most connections are idle

A visitor's browser opens a connection, sends a request, then spends most of its time doing nothing: reading the page, waiting on a slow mobile network, or keeping the connection alive for the next click. In the late 1990s this became known as the C10k problem: how can one server hold 10,000 connections at once when most of them are idle?

Process-based (and thread-based) servers

Classic Apache with the prefork MPM gives each connection its own process. The worker MPM uses one thread per connection.

  • Simple model: code runs top to bottom; a slow operation just blocks that one worker.
  • Isolation: a crash affects only one connection (prefork).
  • Cost: each process or thread needs its own memory and stack. Thousands of idle keep-alive connections mean thousands of mostly sleeping workers, and the OS spends time switching between them.

When all workers are busy, new visitors wait, even if the existing workers are only waiting on slow clients.

Event-driven servers

Nginx, LiteSpeed, OpenLiteSpeed and Caddy run a small number of workers, typically one per CPU core. Each worker runs an event loop:

  1. Ask the kernel which of its thousands of sockets are ready (Linux epoll, BSD kqueue).
  2. For each ready socket, do a small piece of non-blocking work: read some bytes, write some bytes, accept a connection.
  3. Go back to step 1.

An idle connection costs only a few kilobytes of state and no CPU. One worker can serve tens of thousands of connections.

Comparison

AspectProcess/thread per connectionEvent-driven
ExamplesApache prefork, Apache workerNginx, LiteSpeed, OpenLiteSpeed, Caddy, Apache event (hybrid)
Memory per idle connectionHigh (a process or thread)Very low
Slow clientsTie up a worker eachAlmost free
Static file servingGoodExcellent
Running app code inside the serverEasy (mod_php)Not done; code runs in separate processes

Apache event: a hybrid

Apache's event MPM keeps threads for active requests but hands idle keep-alive connections to a dedicated listener thread. It closes much of the gap for keep-alive, though each active request still occupies a thread. See Apache MPMs explained.

Where does PHP fit?

PHP code is blocking: a script that queries a database waits. Event-driven servers therefore never run PHP inside the event loop. They pass the request to a pool of separate PHP processes (PHP-FPM, or LSAPI on LiteSpeed) and carry on serving other connections while waiting for the answer. So the limit on dynamic pages is the number of PHP workers, while the web server itself rarely becomes the bottleneck. Background: application servers explained.

What it means in practice

  • Static files, TLS and slow clients: event-driven servers win clearly in memory and concurrency.
  • Dynamic pages: speed depends on PHP and the database; caching helps far more than the server model.
  • Traffic spikes: event-driven servers degrade gracefully; process-based servers can hit their worker limit and queue requests.
  • Shared hosting: MdmHost uses LiteSpeed, an event-driven server that still reads Apache-style .htaccess, combining both worlds.

FAQ: event-driven vs process-based

Is Apache obsolete?

No. With the event MPM and PHP-FPM it performs well for most sites and remains very flexible.

Why does Node.js feel similar to Nginx?

Node.js also uses an event loop, which is why it handles many concurrent connections well, and why blocking code hurts it.

Does an event-driven server use all CPU cores?

Yes, by running one worker process per core.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.