Home/Code Samples/HTTP Server

HTTP server in Rust vs Go:
same endpoint, both languages, full code.

TechEmpower Round 23 - plaintext req/s

FrameworkLanguageReq/svs Go std
Actix-web 4Rust7.1M+73%
Hyper 1.xRust6.8M+66%
Axum 0.7Rust6.2M+51%
Go Fiber v2Go5.8M+41%
Go net/httpGo4.1Mbaseline
Go Echo v4Go3.9M-5%
Source: techempower.com/benchmarks · Round 23 · Plain text, single query

Minimal HTTP server with routing

RUST / Axum
use axum::{
    routing::get,
    Router,
    extract::Path,
};

#[tokio::main]
async fn main() {
    let app = Router::new()
        .route("/", get(|| async { "Hello, World!" }))
        .route("/hello/:name", get(greet));

    let listener = tokio::net::TcpListener::bind(
        "0.0.0.0:3000"
    ).await.unwrap();

    axum::serve(listener, app)
        .await
        .unwrap();
}

async fn greet(Path(name): Path<String>) -> String {
    format!("Hello, {name}!")
}
GO / net/http
package main

import (
    "fmt"
    "net/http"
    "strings"
)

func main() {
    mux := http.NewServeMux()

    mux.HandleFunc("GET /", func(
        w http.ResponseWriter,
        r *http.Request,
    ) {
        fmt.Fprintln(w, "Hello, World!")
    })

    mux.HandleFunc("GET /hello/{name}", greet)

    http.ListenAndServe(":3000", mux)
}

func greet(w http.ResponseWriter, r *http.Request) {
    name := strings.TrimPrefix(r.URL.Path, "/hello/")
    fmt.Fprintf(w, "Hello, %s!", name)
}

Go 1.22+ (Feb 2024): net/http's ServeMux now supports HTTP method routing (GET /path) and path parameters ({name}) in the pattern directly. Before 1.22, you needed a third-party router like gorilla/mux or chi. This eliminates the main reason teams reached for frameworks. Rust's Axumuses tower-service middleware, which makes adding auth, logging, and rate-limiting composable and type-safe, but adds cognitive overhead vs Go's handler function signature.

More code samples →Full benchmark data →Cloudflare's Pingora deep-dive →