This article is part of Software Foundations, where I explore networking, protocols, operating systems, and software systems from first principles. These foundations support the broader work of Software in the Grid.
What happens between a browser sending an HTTP request and a server returning a response?
In this four-part series, I build a web server in Python to work through that question. We start with HTTP and sockets, build the parsing and configuration components, then compare three server designs: blocking, multithreaded, and single-threaded with non-blocking I/O.
The goal is to understand the decisions inside a server by making them ourselves. This is a learning project, not a production-ready server.
Read the series
Part 1 — Theory and Foundations
What a web server does, how HTTP messages are structured, and how sockets connect an application to the network. We look at persistent connections, message boundaries in a TCP byte stream, and the requirements that will guide the implementation.
Part 2 — Plan and Implementation of HTTP and Configuration Parser
We build the components the server will depend on: an HTTP parser and an NGINX-style configuration system. The configuration pipeline moves from a lexer to a parser and then to a typed object the server can use.
Part 3 — Blocking Single and Multithreaded Server
We put the pieces together, starting with a blocking server. Then we add persistent connections, routing, and threads. ApacheBench experiments help us inspect how the designs behave under different request and connection patterns.
Part 4 — Single-Threaded Non-Blocking Server
We move to an event loop and explore I/O readiness, epoll, and Python’s selectors. The final implementation lets one thread work across multiple connections, and we compare its measured behavior with the earlier versions.
How to use the series
Read the parts in order if you want to follow the implementation. If you already know HTTP and sockets, Part 2 starts the build, Part 3 explores blocking and threads, and Part 4 focuses on non-blocking I/O.
The source code accompanies the articles. Treat the benchmark numbers as results from these experiments, not a general ranking of server architectures.
Where this leads: TLS
Once the server can move and interpret bytes, another question follows: how do we protect those bytes and know who we are communicating with?
My Rebuilding TLS from Scratch series explores that next layer. In Adding Homemade TLS to a Homemade Web Server, I bring the two projects together.
This series belongs to Software Foundations. It explores general networking and server architecture—the underlying software concepts that support the broader work of Software in the Grid.


