October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PCOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk3 min

Multi-Host Routing in Go: One Binary, Many Domains

Use Go's host-specific ServeMux patterns to send multiple domains to in-process handlers, or ReverseProxy when each domain maps to a separate backend.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To route multiple domains to different handlers in one Go server, use host-specific net/http.ServeMux patterns. In Go 1.22 and later, those patterns can also match HTTP methods and path variables. If each domain should reach a separate backend service, use a reverse proxy rather than an in-process handler switch.

Route each domain to an in-process handler

Create one mux and register a pattern containing each hostname. A host pattern matches that host; a pattern without a host matches requests for any host. ServeMux ignores the port when matching the host.

As an Amazon Associate I earn from qualifying purchases.

mux := http.NewServeMux()
mux.HandleFunc("example.com/", siteHandler)
mux.HandleFunc("api.example.com/", apiHandler)

This is the documented pattern shape for Go 1.22 and later. Attach the mux to your HTTP server as its handler, and ensure DNS and any fronting load balancer or proxy direct the domains to that server.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Go 1.22 patterns can combine a method, host, and path. For example, GET example.com/posts/{id} matches a GET request for a post path. Read the named wildcard in the handler with r.PathValue("id"). A GET pattern also matches HEAD; other method patterns match only that method. Use a terminal wildcard such as {name...} to capture the rest of a path.

mux.HandleFunc("GET example.com/posts/{id}", postHandler)

A pattern ending in a slash matches a subtree, not just the slash-terminated path itself. To match a trailing slash exactly, use {$} at the end of the pattern. These distinctions matter when one domain serves both a page and nested routes.

Choose a deliberate policy for unknown hosts

Do not add a hostless fallback unless you intend it to answer for every host that reaches the mux. Because a hostless pattern matches any host, an accidental fallback can serve the wrong site or tenant. If unknown hosts should be rejected, make that policy explicit in your server or handler design rather than relying on a default tenant handler.

Understand specificity and route conflicts

ServeMux does not use registration order as a tie-breaker. It selects the most specific matching pattern: a pattern is more specific when it matches a strict subset of the requests matched by another pattern. If two patterns overlap and neither is more specific, registration panics. One documented exception gives a host-bearing pattern precedence over an otherwise-conflicting hostless pattern.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Review the full set of registrations together, especially when adding broad subtree patterns alongside method- or path-specific routes. A conflict can prevent the program from starting because it is detected while handlers are registered.

Check compatibility before adopting Go 1.22 patterns

The ServeMux pattern syntax changed in Go 1.22. Braced path segments that were literal text in Go 1.21 became wildcards, and invalid patterns can panic during registration. If compatibility with prior matching behavior is required, GODEBUG=httpmuxgo121=1 restores the old behavior; the setting is read once at startup. Check the Go version and existing registrations before changing shared routing code.

ServeMux also sanitizes request paths and host values, strips a port for host matching, and redirects paths containing dot segments or repeated slashes to a cleaned path. Escaped %2e and %2f remain escaped and are not treated as path separators during routing. Review these cases if path canonicalization affects authorization, request signatures, or tenant selection. See the ServeMux documentation and the Go 1.22 release notes for the exact pattern and compatibility rules.

Use a reverse proxy for separate backend services

Host-specific ServeMux handlers are a good fit when the handlers run inside the same Go process. If choosing a domain means forwarding the request to a separate upstream service, use net/http/httputil.ReverseProxy and configure an upstream for that route.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

ProxyRequest.SetURL sets the outbound scheme, host, and base path; by default it also rewrites the outbound Host header to the target. If the backend needs the original inbound Host, preserve it explicitly. SetXForwarded sets the standard X-Forwarded-For, X-Forwarded-Host, and X-Forwarded-Proto headers. Trust those headers only within a deliberately defined proxy boundary. The ReverseProxy documentation describes these behaviors.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Decide based on topology and routing needs

Approach Use it when Key consideration
Host-specific ServeMux handlers Domains select handlers running in the same Go process. Use Go 1.22+ syntax for method and path wildcards, and review conflicts and unknown-host handling.
httputil.ReverseProxy Domains select separate backend services. Choose the outbound Host and forwarded-header policy deliberately.
Third-party router or framework Your application already uses one, or needs routing features beyond the standard library’s fit. Changing routers is not necessary just because the server handles multiple domains.

The Go team notes that third-party web frameworks remain a fine choice for current users or programs with advanced routing needs. The standard library is a direct option for host-based dispatch, not a universal replacement for every router.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.