Actix Web 4.15.0 covers the HTTP layer without choosing your database
Actix Web gives a Rust service most of the machinery between a socket and a handler. The README lists HTTP/1.x, HTTP/2, streaming, WebSockets, compression, multipart bodies, static assets, TLS choices, and middleware for concerns such as sessions and CORS. Database access remains an application decision, with separate examples for MongoDB, Diesel, SQLite, and Postgres.
The smallest example uses 1 dependency, an async handler, and an HttpServer bound to port 8080. Routes can use attribute macros or builder methods. Handlers return anything implementing Responder, so a string can stay a string while richer paths return an HttpResponse or result type. Stable Rust 1.88 is the current floor. That requirement is easy for a new service and may be a migration item in a conservative workspace.
Typed extractors make request rules visible in handler signatures
Path values, query strings, JSON, form data, raw bytes, request objects, and application state can enter a handler as typed arguments. Actix implements this through FromRequest. Extractor configuration supports practical boundaries, such as a JSON payload limit and a custom error response for invalid data.
There are 2 rules worth learning before handlers grow. Actix supports up to 12 extractors per handler, and only the first extractor that consumes the request body will succeed. The guide points to Either<Json<T>, Bytes> when a route needs JSON with a raw-body fallback. These constraints can surprise someone who adds a second body reader for signatures or logging and expects both arguments to receive the same stream.
What happened when we ran it
Our sandbox installed 216 packages in 9 seconds at commit 7e52e42. The build succeeded in 92 seconds. The test command ran for 528 seconds and reported 2,405 passed with 0 failed. We used an unprivileged container with 3 CPUs and 12 GB of RAM. The full pass is strong evidence for the checked-out source, while the 8-minute test step is long enough to matter in a local feedback loop.
The repository measured 3.2 MB before dependencies, with 427 files and about 87,190 lines of source. We found 7 CI workflow files, no Dockerfile, and no top-level tests directory. Rust projects commonly keep unit tests beside source, and the 2,405-test result proves the suite was discoverable without a root tests folder. The run did not start a production server or measure request latency, concurrency, memory use, TLS setup, or WebSocket behavior.
Every worker receives its own application instance
HttpServer creates an application instance for each worker, with the default worker count tied to physical CPUs. State constructed inside the server factory therefore belongs to that worker. The application guide warns that mutable copies can drift apart. Shared state should be created outside the factory and moved in through web::Data, which internally uses Arc; mutation then needs an appropriate synchronization strategy.
Blocking work is just as important. Each worker processes its requests sequentially, so a blocking handler prevents that worker from taking another request. The server guide directs long non-CPU-bound work toward async functions and CPU-heavy work toward a blocking thread pool. A service with 4 workers can still suffer if each one waits on synchronous database or file calls. Framework speed cannot rescue blocking application code.
Middleware executes in reverse registration order
Actix middleware can inspect requests, stop processing early, change responses, use application state, and call external services. It can be attached to an application, scope, or resource. The built-in pieces cover logging, default headers, sessions, compression, and related HTTP work, while from_fn and wrap_fn provide smaller custom paths before implementing the lower-level service traits.
Order is the sharp edge: when wrap() appears 2 times, the last registered middleware runs first. That affects logs, authentication, response mapping, compression, and headers. Version 4.15.0 added Error::add_response_mapper() so middleware can alter error-generated responses before they leave the server. Write one integration test that records the actual order around a protected route. Reading the builder chain from top to bottom gives the wrong execution sequence.
HTTP/2 is supported, while HTTP/3 is absent from the promise
The README promises HTTP/1.x and HTTP/2, including automatic version selection through TLS and an explicit plaintext H2C binding path in the server API. TLS can use OpenSSL or Rustls. Compression covers Brotli, gzip, deflate, and Zstandard. WebSockets work on both client and server sides, and awc supplies the related HTTP client. This is enough protocol coverage for many APIs and browser-facing services.
HTTP/3 is not listed, so teams with that requirement should stop before treating the framework's broad HTTP feature list as universal. The same caution applies to experimental introspection: its feature name begins with experimental, and the README permits breaking changes in any release. Keep it out of a stable application contract unless you can absorb those changes. In return, production-facing APIs stay on the regular versioned path instead of being presented as finished too early.
September 2026 releases show active maintenance across the workspace
GitHub showed 24,843 stars and 194 open issues and pull requests when fetched. The repository was pushed on September 24, 2026. Actix Web 4.15.0 arrived on August 21, while related workspace crates including awc and actix-http shipped September updates. The open queue also had recent work on response errors, compression, static-file filtering, and HTTP parsing, so the combined count reflects ongoing development rather than 194 confirmed framework defects.
Actix Web is a strong default when your team already wants Rust and prefers explicit HTTP building blocks over a full application platform. Our 2,405 passing tests make the codebase easier to take seriously than a benchmark badge alone. The final choice should turn on architecture: per-worker applications, typed extractors, and reverse middleware order need to fit how your service handles state and cross-cutting behavior. If they do, the framework gives you a lot without dictating the rest of the stack.

