Back to Blog
Tutorial10 min read2026-07-01

How to Deploy a Rust Actix Web App

Actix Web is one of the fastest web frameworks in any language. Learn how to package an Actix app into a small container image and deploy it to production with proper worker and database configuration.

Ajay Kumar
Ajay Kumar
Founder & DevOps, PandaStack

Actix Web is a powerhouse — consistently among the fastest web frameworks in independent benchmarks, with a mature ecosystem and an actor-influenced design. If you want maximum throughput from a Rust HTTP service, Actix is a top contender. Deploying it follows the same Rust playbook (small binary, multi-stage build) with a few Actix-specific considerations around workers and configuration. Here's the complete guide.

Why Actix Web

Actix Web is built on actix-rt/Tokio and is renowned for raw performance. It offers a rich extractor system, powerful middleware, WebSocket support, and a stable 4.x API. The deployment characteristics mirror any Rust app: a compiled binary with no runtime to install, low memory use, and fast startup. The main framework-specific knob is how many worker threads it spawns.

Step 1: A minimal Actix app

use actix_web::{get, web, App, HttpServer, Responder, HttpResponse};

#[get("/health")]
async fn health() -> impl Responder {
    HttpResponse::Ok().json(serde_json::json!({ "status": "ok" }))
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let port: u16 = std::env::var("PORT")
        .ok().and_then(|p| p.parse().ok()).unwrap_or(8080);

    HttpServer::new(|| App::new().service(health))
        .bind(("0.0.0.0", port))?
        .run()
        .await
}

Again, the two production must-dos: bind 0.0.0.0 and read PORT.

Step 2: Tune workers for the container

By default, Actix spawns one worker per logical CPU. In a container with a CPU *limit* (rather than dedicated cores), Rust may see the host's full core count and over-spawn workers, causing contention. Pin the worker count to your container's allocated CPU:

let workers: usize = std::env::var("WEB_CONCURRENCY")
    .ok().and_then(|w| w.parse().ok()).unwrap_or(2);

HttpServer::new(|| App::new().service(health))
    .workers(workers)
    .bind(("0.0.0.0", port))?
    .run()
    .await

Set WEB_CONCURRENCY to match your compute tier's CPU allocation. This is the most common Actix-in-a-container tuning mistake — fix it up front.

Step 3: The multi-stage Dockerfile

Same strategy as any Rust service — build fat, ship thin:

FROM rust:1.82 AS builder
WORKDIR /app
COPY Cargo.toml Cargo.lock ./
RUN mkdir src && echo "fn main() {}" > src/main.rs && cargo build --release && rm -rf src
COPY . .
RUN cargo build --release

FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/target/release/my-actix-app /usr/local/bin/app
EXPOSE 8080
CMD ["app"]

The dependency pre-build layer keeps incremental builds fast. Expect a final image in the ~80-120 MB range on debian:slim, or far smaller with a musl static build on distroless.

Step 4: Add a database with a shared pool

With Actix, share a connection pool across workers via app_data. Using sqlx:

use sqlx::postgres::PgPoolOptions;
use actix_web::web::Data;

let pool = PgPoolOptions::new()
    .max_connections(5)
    .connect(&std::env::var("DATABASE_URL").unwrap())
    .await.unwrap();

HttpServer::new(move || {
    App::new()
        .app_data(Data::new(pool.clone()))
        .service(health)
})

Mind your math: workers × max_connections must stay under your Postgres max_connections. With 4 workers and a pool of 5 each, that's 20 connections from one replica — multiply across replicas.

Step 5: Deploy on PandaStack

  1. 1Provision a managed PostgreSQL (16.x).
  2. 2Create a container app from your repo; PandaStack builds the Dockerfile with rootless BuildKit and streams live build logs.
  3. 3Link the databaseDATABASE_URL is auto-injected for sqlx.
  4. 4Set WEB_CONCURRENCY to match your CPU tier.
  5. 5Attach a custom domain with automatic SSL.

Step 6: Production polish

  • Graceful shutdown — Actix handles SIGTERM and drains connections; set a sensible shutdown timeout so deploys don't drop requests.
  • Logging — use actix-web's Logger middleware plus env_logger/tracing for request logs in your platform's live log stream.
  • Compression & security headers — add Compress middleware and set security headers via middleware.
  • Health/readiness — keep /health trivial; the platform polls it.

Actix vs. Axum (quick take)

Actix WebAxum
Peak throughputExcellent (benchmark leader)Excellent
ErgonomicsRich, slightly more surface areaVery clean, Tower-based
EcosystemMature, largeGrowing fast, Tokio-native

Both are outstanding. Choose Actix when you want maximum raw performance and a mature feature set; Axum when you want the cleanest Tower/Tokio composition. Either deploys identically.

Honest caveats

As with all Rust, the build is the slow part — plan for longer compile times and lean on the dependency-caching layer. The Actix-specific gotcha is worker count in CPU-limited containers; get .workers() right or you'll waste resources on thread contention. The runtime payoff is the same as Axum: tiny image, low memory, top-tier throughput.

Wrapping up

Deploying Actix Web is the standard Rust recipe plus one tuning step: multi-stage build for a small image, bind to PORT/0.0.0.0, and pin .workers() to your container's CPU. Add a shared sqlx pool against managed Postgres with an auto-injected DATABASE_URL and you have one of the fastest API stacks you can run.

PandaStack builds your Dockerfile, auto-wires the database, and serves with automatic SSL — and Actix's small footprint suits the free tier nicely. Deploy your Actix app at https://dashboard.pandastack.io.

References

  • Actix Web documentation: https://actix.rs/docs/
  • Actix Web API docs: https://docs.rs/actix-web/latest/actix_web/
  • TechEmpower framework benchmarks: https://www.techempower.com/benchmarks/
  • sqlx: https://github.com/launchbadge/sqlx
  • Multi-stage Docker builds: https://docs.docker.com/build/building/multi-stage/

Ready to deploy?

Start free on PandaStack.

Start free on PandaStack

More in Tutorial

Browse all Tutorial articles →

See also