Skip to content

Instantly share code, notes, and snippets.

@oddmario
Last active January 25, 2025 09:28
Show Gist options
  • Save oddmario/3782033e4efac2b09b48f135a9273060 to your computer and use it in GitHub Desktop.
Save oddmario/3782033e4efac2b09b48f135a9273060 to your computer and use it in GitHub Desktop.
Tuning a Golang (Go) HTTP server

Tune a Go http.Server

by adjusting its default buffer sizes


In some situations, you may need to adjust the default buffer sizes of a Golang HTTP server.

Adjusting the default buffer sizes allows you to benefit from higher throughput and improve the performance of your HTTP servers overall.

For the cherry on the top,

You may also tune the performance of your Linux kernel overall [if you are hosting your application on a Linux system]

I recommend https://github.com/klaver/sysctl as a good starting point on this.

To avoid the occurrence of any inconveniences, please make sure not to blindly copy and then paste things. Feel free to check the documented comments above each kernel parameter before actually using it to learn what each parameter does :)


Tuning the ResponseWriter buffer size

At the present, the Golang HTTP server does not have an option that allows you to configure the write buffer size for unknown reasons.

The net/http package will use a hard coded 4 KB buffer size for the response writer.

To modify this, check out https://github.com/oddmario/go-http-server-custom-write-buffer-patch

  • Recommended tuned value: a value of 8 KB to 1 MB should be optimal for a higher throughput.

Tuning the TCP socket read & write buffer sizes

This is achievable by wrapping the TCP listener around our own custom interface that sets the TCP buffer size(s) right after accepting a connection.

// customListener wraps a TCPListener and sets the write buffer size for each connection
type customListener struct {
	*net.TCPListener
	writeBufferSize int
}

// Accept waits for and returns the next connection to the listener, setting the write buffer size
func (ln *customListener) Accept() (net.Conn, error) {
	conn, err := ln.TCPListener.Accept()
	if err != nil {
		return conn, err
	}

	tcpConn, ok := conn.(*net.TCPConn)
	if ok {
		tcpConn.SetWriteBuffer(ln.writeBufferSize)
	}

	return conn, err
}

func main() {
	listenerAddr := ":8080"

	srv := &http.Server{
		Addr:              listenerAddr,
		WriteBufferSize:   256 * 1024, // requires https://github.com/oddmario/go-http-server-custom-write-buffer-patch
		Handler:           /* handler here */,
	}

	ln, err := net.Listen("tcp", listenerAddr)
	if err != nil {
		fmt.Println("Error starting listener:", err)

		return
	}

	tcpListener := &customListener{ln.(*net.TCPListener), 256 * 1024}

	err := srv.Serve(tcpListener)
	if err != nil {
		fmt.Println(err)

		return
	}
}

If you would like, you can also modify the above code to adjust the TCP read buffer size.

Note that Golang can't set a TCP buffer size that exceeds the kernel's max rmem/wmem value. So make sure to adjust the kernel parameters accordingly for the application-level TCP buffer size(s) to take effect.

  • Recommended tuned value: a value of 4 KB to 4 MB.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment