Go FastHTTP

Go FastHTTP replaces the web server with a Go binary that carries the site inside it. A Node Alpine stage builds the React and Vite app, a Go stage embeds the build output into the binary, and the build uses CGO_ENABLED=0, strips the file, and compresses it with UPX. The runtime image is scratch and holds a single file. The server maps the request path to an embedded file, sets the content type from the extension, and falls back to index.html so client-side routes work. The note is honest about the cost. FastHTTP has no native HTTP/2 and fewer features than nginx, compression has to be coded, and the Go handler must be maintained. It suits microservices and internal APIs that serve static files at high speed.

Techniques

  • Base image: scratch
  • Go server: FastHTTP (high-performance HTTP server)
  • Embedded files: Uses //go:embed to embed static files into the binary
  • Single binary: Everything in one file, no separate web server needed
  • UPX compression: Compresses the binary with UPX ultra-brute LZMA
  • Static linking: CGO_ENABLED=0 to produce a static binary

Advantages

  • Extremely small size: A single binary, possibly <5MB after UPX
  • High performance: FastHTTP is much faster than Nginx for simple use cases
  • Simple: No web server configuration needed
  • SPA routing: Handles SPA routing automatically (falls back to index.html)
  • No dependencies: No external files or libraries needed
  • Easy deployment: Just copy one file

Disadvantages

  • No HTTP/2: FastHTTP does not natively support HTTP/2
  • Limited features: Fewer features than Nginx (caching, rate limiting, etc.)
  • Go dependency: The Go code must be maintained
  • No gzip_static: Compression logic must be implemented in code
  • Less battle-tested: FastHTTP is used less widely than Nginx

Use Cases

  • Microservices with high performance requirements
  • Internal APIs that need to serve static files
  • When you want to minimize size as far as possible
  • When Nginx's advanced features are not needed

FastHTTP is aimed at simple serving, where it can beat Nginx and skip a separate web server config. The embed directive pulls the built files into the binary, and UPX ultra-brute LZMA can leave it possibly under 5MB. Deployment is a copy of one file, with no extra libraries beside it. There is no native HTTP/2, no gzip_static, and no caching or rate limiting.

Code Highlights

# Embed files into the binary
//go:embed dist
var distFiles embed.FS

# Build with optimization
CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -trimpath -o server main.go
strip server
upx --ultra-brute --lzma server

See also: Optimization Techniques · BusyBox Httpd · Scratch Nginx