Docs/1. Getting Started/Hello World & Server Basics
Preview: 0/2 free chapters read
Beginner Level 6 min read

Hello World & Server Basics

Creating your first production-grade HTTP listener with App and HttpServer.

To build an Actix Web application, you need to understand the relationship between HttpServer and App.

#1. The HttpServer Construct HttpServer is responsible for binding to the TCP socket, managing SSL/TLS certificates, configuring worker threads, and listening for incoming network packets. By default, it spawns a number of workers equal to your machine logical CPU cores.

#2. The App Factory Closure The closure passed into HttpServer::new(|| { App::new() }) is executed once per worker thread. This guarantees thread-local execution without thread locking.

#3. Route Handlers & Responders A handler is simply an asynchronous Rust function that receives zero or more Extractors as parameters and returns a type implementing Responder.

# Working Implementation

use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder};
use serde::{Deserialize, Serialize};

#[derive(Serialize)]
struct StatusResponse {
    message: String,
}

#[derive(Deserialize)]
struct EchoRequest {
    name: String,
}

#[get("/health")]
async fn health_check() -> impl Responder {
    HttpResponse::Ok().json(StatusResponse {
        message: "System operational".into(),
    })
}

#[post("/echo")]
async fn echo(req: web::Json<EchoRequest>) -> impl Responder {
    HttpResponse::Ok().json(serde_json::json!({
        "greeting": format!("Hello, {}! Welcome to Actix Web.", req.name)
    }))
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let host = "127.0.0.1";
    let port = 8080;
    println!("Server listening on http://{}:{}", host, port);

    HttpServer::new(|| {
        App::new()
            .service(health_check)
            .service(echo)
    })
    .bind((host, port))?
    .run()
    .await
}
Key Architectural Takeaways
  • App::new() is a factory closure executed once per CPU worker thread.
  • HttpServer binds to TCP sockets and manages incoming connection dispatching.
  • Handlers can use attribute macros like #[get("/")] or manual .route() declarations.
  • Always return types implementing the Responder trait.
Common Mistakes & Gotchas
  • ×Instantiating non-Clone application state inside main() without wrapping in web::Data.
  • ×Forgetting to mark the main function with #[actix_web::main].
Sponsored Infrastructure Partner
Deploy Lightweight 15MB Distroless Actix Containers

High-availability PostgreSQL connection pooling and NVMe storage.

Learn More