go 21 lines · 1 tab

HTTP server timeouts that prevent slowloris and stuck connections

Leah Thompson Jan 2026
1 tab
package main

import (
  "context"
  "net/http"
  "time"
)

func newServer(handler http.Handler) *http.Server {
  return &http.Server{
    Addr:              ":8080",
    Handler:           handler,
    ReadHeaderTimeout: 2 * time.Second,
    ReadTimeout:       10 * time.Second,
    WriteTimeout:      10 * time.Second,
    IdleTimeout:       60 * time.Second,
    BaseContext: func(net.Listener) context.Context {
      return context.Background()
    },
  }
}
1 file · go Explain with highlit

The default http.Server will happily keep connections open longer than you intended, which is how you end up with “mysterious” goroutine growth during partial outages. I set ReadHeaderTimeout to protect against slowloris-style attacks, keep IdleTimeout tight to reclaim keep-alive sockets, and set ReadTimeout/WriteTimeout as a coarse guardrail for handlers that forget to enforce per-request deadlines with context.WithTimeout. I also use a custom BaseContext so every connection inherits a root context that can be canceled on shutdown. The win is operational: when something goes wrong, connections drain predictably and you don’t end up with thousands of half-open clients pinning memory. This is a small config block, but it’s a big reliability upgrade.


Related snips

Share this code

Here's the card — post it anywhere.

HTTP server timeouts that prevent slowloris and stuck connections — share card
Link copied