DEV Community

Cover image for How HTTP Works Under the Hood: TCP, UDP, Keep-Alive & HTTP/3 | Deeper Dive into HTTP #3
Ashay Tiwari
Ashay Tiwari

Posted on

How HTTP Works Under the Hood: TCP, UDP, Keep-Alive & HTTP/3 | Deeper Dive into HTTP #3

When you open a website, fetch data from an API, or submit a form, HTTP makes communication between your application and a server possible.

But have you ever wondered what happens after your application sends an HTTP request?

In this third article of the Deeper Dive into HTTP series, we'll explore:

  • How HTTP fits into the networking stack.
  • How TCP establishes reliable connections.
  • What happens during the TCP three-way handshake.
  • What UDP is and how it differs from TCP.
  • How Keep-Alive enables connection reuse.
  • Why HTTP/3 uses QUIC over UDP.

Let's dive in.


1. Understanding the Networking Stack

Before exploring TCP, UDP, and HTTP, let's understand how these protocols fit together.

Imagine your frontend needs to fetch a list of users from a backend API.

GET /users

There are multiple layers involved in getting this request to the server.

A simplified view of the networking stack looks like this:

Networking Stack

Each layer has a different responsibility.

First, HTTP defines the rules for communication. It describes things like the request method, headers, status codes, and message content.

Next, TCP, when used, provides a reliable, ordered stream of bytes between two endpoints. It handles things like retransmission of lost data and flow control.

UDP provides a lightweight way to send datagrams without built-in guarantees of delivery, ordering, or retransmission.

And then there's IP, which helps route packets across networks toward their destination.

Think of it this way.

HTTP defines what the message means. TCP helps deliver a reliable stream of data. And IP helps move packets through the network.

For example, HTTP defines what a GET /users request means. TCP can provide reliable delivery of the bytes carrying that HTTP message, while IP handles packet addressing and routing.


2. How Does TCP Establish a Connection?

TCP stands for Transmission Control Protocol.

Before sending HTTP data over a new TCP connection, the client and server typically establish the connection using something called the TCP three-way handshake.

TCP Handshake

It involves three steps.

Step one: SYN.

The client sends a TCP segment with the SYN flag set.

It is essentially initiating the connection and proposing its initial sequence number.

Step two: SYN-ACK.

The server responds with a segment containing both SYN and ACK flags.

It acknowledges the client's initial sequence number and provides its own.

Step three: ACK.

The client acknowledges the server's initial sequence number.

At this point, the TCP handshake is complete, and both sides can exchange application data.

And now, the TCP connection is established.

Once the connection is ready, HTTP data can be sent over it.

Does the HTTP request come immediately after the handshake?

Not necessarily.

For HTTPS over TCP, the client and server typically also establish TLS security before exchanging ordinary HTTP application data. TLS provides encryption, integrity protection, and server authentication.

So, a simplified connection setup looks like this:

Connection Setup

Here's something important: this handshake happens when a new TCP connection is established. It doesn't need to happen before every HTTP request.

And that's where connection reuse becomes important.


3. What Is UDP, and How Is It Different from TCP?

UDP stands for User Datagram Protocol.

Like TCP, UDP operates at the transport layer. However, it provides a different set of capabilities.

TCP establishes a connection and provides reliable, ordered delivery of a byte stream.

UDP sends independent datagrams without providing built-in mechanisms for reliable delivery, retransmission, or ordered delivery.

Let's compare them.

TCP-UDP Comparison

UDP has less built-in transport machinery, but that doesn't mean every UDP application is unreliable.

An application can implement additional mechanisms on top of UDP when it needs them.

And this is exactly where QUIC becomes important.

Why does HTTP/3 use UDP?

If TCP already provides reliable delivery, why build a new transport protocol over UDP?

The answer involves connection setup, encryption, and how multiple streams behave when packets are lost.

TCP provides one ordered byte stream per connection. If TCP cannot deliver a missing portion of that stream, later bytes in the same stream cannot be delivered to the application in order until the gap is resolved.

With HTTP/2, multiple HTTP streams can share one TCP connection. A lost TCP segment can therefore delay delivery of data for multiple streams on that connection.

HTTP/3 uses QUIC to address important limitations of this architecture.

QUIC implements reliability, congestion control, stream multiplexing, and integrated TLS 1.3 security over UDP.

UDP is the underlying datagram transport; QUIC supplies the transport features needed by HTTP/3.


4. What Is Keep-Alive in HTTP?

Now let's look at another important concept: connection reuse.

Imagine your frontend needs to make five API requests to the same server.

For example:

GET /api/profile
GET /api/posts
GET /api/notifications
GET /api/settings
GET /api/followers
Enter fullscreen mode Exit fullscreen mode

If every request required a new TCP connection, the client would repeatedly incur connection setup overhead.

For HTTPS over TCP, new connections can also require a TLS handshake.

That adds work and can increase latency.

Without connection reuse

A simplified sequence might look like this:

Request 1 → Establish connection → Response 1
Request 2 → Establish connection → Response 2
Request 3 → Establish connection → Response 3
Enter fullscreen mode Exit fullscreen mode

This example assumes the client closes or doesn't reuse each connection. Real clients may reuse connections even when applications make separate requests.

With persistent connections

Instead, the client can keep a connection open and reuse it for additional HTTP exchanges.

Establish connection
        |
        v
Request 1 → Response 1
        |
        v
Request 2 → Response 2
        |
        v
Request 3 → Response 3
        |
        v
Connection remains available for reuse
Enter fullscreen mode Exit fullscreen mode

This reduces repeated connection setup overhead and can improve performance.

How does HTTP Keep-Alive work?

In HTTP/1.1, persistent connections are the default unless the connection is otherwise closed or a message explicitly indicates that it should close.

For example:

GET /api/profile HTTP/1.1
Host: example.com
Enter fullscreen mode Exit fullscreen mode

The client and server can reuse the connection for additional requests.

A server might also send:

Connection: keep-alive
Enter fullscreen mode Exit fullscreen mode

However, this header is not required to enable persistence in HTTP/1.1.

In HTTP/1.0, persistent connections were commonly negotiated using the Connection: keep-alive convention.

What happens in HTTP/2 and HTTP/3?

Connection reuse becomes even more powerful with modern HTTP versions.

HTTP/2 supports multiplexing multiple independent HTTP streams over a single TCP connection.

HTTP/3 also supports multiplexing, but it uses QUIC streams over a QUIC connection instead of HTTP/2's streams over TCP.

This means multiple requests can make progress concurrently without requiring a separate connection for every request.

We'll explore that distinction further in the next section.


5. HTTP/1.1 vs HTTP/2 vs HTTP/3

HTTP has evolved over time to improve performance, efficiency, and communication behavior.

HTTP/1.1: Persistent connections

HTTP/1.1 allows multiple requests and responses to reuse the same connection.

However, it doesn't natively multiplex independent HTTP exchanges in the way HTTP/2 does. On a single connection, responses must be sent in request order, so a slow response can delay later responses.

Browsers historically worked around some of these limitations by opening multiple connections to a server.

HTTP/2: Multiplexing over TCP

HTTP/2 introduces multiplexing, which allows multiple streams to share a single TCP connection.

For example:

One TCP connection
    ├── Stream 1: Profile request
    ├── Stream 3: Posts request
    ├── Stream 5: Settings request
    └── Stream 7: Notifications request

Enter fullscreen mode Exit fullscreen mode

The streams can be interleaved, allowing requests and responses to make progress concurrently.

But there is an important limitation.

TCP still provides one ordered byte stream. If a TCP segment is lost, TCP cannot deliver subsequent bytes to the application in order until the missing data is recovered.

As a result, data from multiple HTTP/2 streams sharing that connection can experience transport-level head-of-line blocking.

HTTP/3: QUIC over UDP

HTTP/3 uses QUIC rather than TCP.

QUIC provides reliable delivery within its streams while allowing data from independent streams to progress separately.

One QUIC connection
    ├── Stream 1: Profile request
    ├── Stream 3: Posts request
    ├── Stream 5: Settings request
    └── Stream 7: Notifications request
Enter fullscreen mode Exit fullscreen mode

If packet loss affects data belonging to one stream, other streams can continue delivering available data rather than waiting for a single ordered TCP byte stream to recover.

This doesn't mean packet loss has no impact on other streams. Streams can still share network capacity and congestion control, and loss can delay any data that depends on the missing information.

QUIC also integrates TLS 1.3 security into its connection establishment. Depending on the connection setup and whether session resumption or 0-RTT is available, it can reduce the number of round trips needed before application data is sent.

These improvements can make HTTP/3 particularly useful on networks with higher latency or changing connectivity.


6. What Should Developers Take Away?

You don't need to implement TCP, UDP, or QUIC yourself to build most web applications. Browsers, operating systems, networking libraries, and servers handle these protocols.

However, understanding them helps explain real-world behavior.

  • If a new connection is slow, connection establishment and TLS negotiation may contribute to latency.
  • If an application makes many requests to the same server, connection reuse can reduce overhead.
  • If multiple resources are fetched concurrently, HTTP/2 and HTTP/3 multiplexing can improve efficiency.
  • If a network has packet loss, the transport protocol can influence how that loss affects application data.
  • If a connection changes networks, QUIC can support connection migration in scenarios where its connection identifiers and network conditions allow it.

These concepts are useful when investigating API latency, performance bottlenecks, browser networking behavior, and modern web infrastructure.


Conclusion

HTTP is more than a format for sending requests and receiving responses. Its performance also depends on the transport protocols and connection-management mechanisms underneath it.

Here's a quick recap:

TCP provides reliable, ordered byte-stream delivery and establishes connections through a three-way handshake.

UDP sends datagrams without built-in delivery or ordering guarantees.

Keep-Alive and persistent connections allow connection reuse and reduce repeated setup overhead.

HTTP/2 adds multiplexing over TCP, but TCP-level head-of-line blocking can affect all streams sharing a connection.

HTTP/3 uses QUIC over UDP to support reliable streams, multiplexing, integrated TLS 1.3 security, and improved handling of packet loss across independent streams.

This is the third article in the Deeper Dive into HTTP series by AshayCodes. In the next article, we'll explore HTTP methods such as GET, POST, PUT, PATCH, and DELETE, along with safe and idempotent methods.

Happy learning!

Top comments (0)