[TOOLS] 9 min readOraCore Editors

Build a Rust REST API with Actix, SQLx, Postgres

Actix Web, SQLx, and PostgreSQL give Rust teams a fast path to production APIs, with compile-time query checks and lean Docker images.

Share LinkedIn
Build a Rust REST API with Actix, SQLx, Postgres

Rust teams keep circling the same stack for backend APIs: Actix Web, SQLx, and PostgreSQL. That combination is not trendy for its own sake. It is popular because it gives you async handlers, compile-time SQL checks, and a database that can take real traffic without forcing you into a rewrite later.

Marcus Chen’s tutorial, which Prism News highlighted this week, makes a simple argument: if you want a production API in Rust, this stack gets you there with fewer surprises than most alternatives. The real work is in the details people usually skip on day one, like pool sizing, migration workflow, and error mapping.

Why this stack keeps winning

Get the latest AI news in your inbox

Weekly picks of model releases, tools, and deep dives — no spam, unsubscribe anytime.

No spam. Unsubscribe at any time.

The first decision is the web framework. Actix Web 4 is still one of the fastest Rust frameworks in common use, and the comparison point is usually Axum. Axum is built around the Tower ecosystem and feels very natural if your team already lives in Tokio middleware. Actix, though, has a longer production track record and a wider set of examples people can copy without translating everything from scratch.

Build a Rust REST API with Actix, SQLx, Postgres

That matters because backend teams do not ship benchmarks. They ship systems that survive bad requests, slow queries, and the occasional dependency upgrade that changes runtime behavior. In that context, Actix’s maturity often matters more than a small throughput edge.

SQLx makes the database side more interesting. Instead of hiding SQL behind an ORM, it keeps your queries in plain text and checks them at compile time against a live database or a cached offline plan. That gives you real SQL control while still catching typos and schema mismatches before deployment.

  • Actix Web 4 is the framework in the tutorial, with typed extractors and Tokio integration.
  • Axum 0.8.8 remains the main alternative for teams already invested in Tower.
  • SQLx supports PostgreSQL, MySQL, and SQLite, but its async story is native rather than bolted on.
  • PostgreSQL handles pooled connections and concurrent writes far better than SQLite for most public APIs.

PostgreSQL is the least controversial part of the stack. SQLite is great for local tools and small apps, but once you need connection pooling, concurrent workers, and a migration history that lives in version control, Postgres is the cleaner choice. If you start with Postgres in Docker locally, your production setup becomes an environment change instead of a redesign.

What the project setup actually looks like

The tutorial’s project setup is refreshingly ordinary, which is a good thing. Your Cargo.toml usually pulls in actix-web, sqlx with the postgres, runtime-tokio, and macros features, plus serde, dotenvy, tracing, and tracing-subscriber. The dev tool that matters most is sqlx-cli, which handles migrations and the offline query cache.

Actix runs on Tokio, and that runtime detail is one of the easiest places to trip. If another crate in your app expects a different Tokio version or runtime setup, the code may compile and still behave badly once the service starts handling real traffic. That is the kind of bug that shows up after the demo, which is exactly why the tutorial spends time on it.

The other setup choice that pays off early is logging. Structured logs from tracing give you request IDs, spans, and query timing without forcing you to manually thread context through every function call. For a REST API, that is the difference between guessing and knowing why a request slowed down.

  • #[actix_web::main] boots the Tokio runtime for the server.
  • web::Data stores shared state such as the Postgres pool.
  • web::Json, web::Path, and web::Query parse inputs before your handler runs.
  • sqlx migrate and cargo sqlx prepare are part of the workflow, not afterthoughts.

The part most tutorials skip

Marcus Chen’s framing is strongest when he gets into the day-two issues. Pool sizing is one of those details that looks boring until it breaks your service. If your pool is too small, requests queue and latency climbs. If it is too large, Postgres becomes the bottleneck and starts rejecting work under load.

Build a Rust REST API with Actix, SQLx, Postgres

That is why a starting point such as two connections per async worker thread is only a starting point. You still need to account for your CPU count, your database’s max_connections, and the average latency of your queries. The right answer is usually empirical, not theoretical.

“Building production-grade APIs in Rust has never been more accessible.” — Marcus Chen

That quote lands because the stack really does remove a lot of friction. SQLx catches schema problems at compile time, Actix handles typed extraction cleanly, and Postgres gives you the durability and concurrency model most serious APIs need. The catch is that each layer has sharp edges if you treat it like a toy project.

Migrations are another example. SQLx’s timestamped migration files are easy to commit and review, but the offline query cache can break builds if you forget to prepare it. If your CI pipeline does not have access to a live database, you need the .sqlx directory checked in and refreshed before the build step.

Numbers that matter in practice

There are a few comparisons worth keeping in mind if you are choosing a Rust API stack today. The tutorial cites Actix Web as handling roughly 10 to 15 percent more requests per second than Axum under heavy load. That is real, but it is rarely the deciding factor for a CRUD service or internal API.

The more meaningful numbers are operational. A well-built Rust container image often lands in the 20 to 50 MB range when you use a multistage Docker build. That is much smaller than the typical JVM image and usually smaller than a Python service with a full dependency tree. Smaller images mean faster deploys, less registry churn, and fewer surprises when you roll back.

On the database side, the comparison between SQLx and Diesel is about query shape and async ergonomics. Diesel’s type system is impressive, but dynamic queries get painful fast. SQLx trades some of that compile-time abstraction for direct SQL and async-native behavior, which is easier to live with once your API has optional filters, joins, and evolving endpoints.

  • Actix Web vs Axum: roughly 10 to 15 percent higher throughput for Actix under heavy load, according to the tutorial’s cited benchmarks.
  • Docker runtime images: often 20 to 50 MB for a Rust API built with a multistage Dockerfile.
  • SQLx vs Diesel: SQLx keeps raw SQL and async-first behavior; Diesel favors compile-time query construction.
  • PostgreSQL vs SQLite: Postgres handles pooled async workers and concurrent writes more cleanly for production APIs.

Testing is where the stack starts to feel serious. Integration tests against a Dockerized Postgres instance, plus sqlx::test macros, catch issues that unit tests miss. In CI, a GitHub Actions workflow with a Postgres service container is usually enough to keep the build honest without extra infrastructure.

What I would do if I were starting today

If I were building a new Rust API this week, I would take this stack almost exactly as written. I would use Actix Web for the HTTP layer, SQLx for database access, and PostgreSQL from the first commit. I would also make a few decisions early: commit migrations, run cargo sqlx prepare in CI, and map database errors to a central ResponseError enum instead of scattering ad hoc status codes through handlers.

The biggest mistake is treating the stack like a tutorial toy. The second biggest is assuming async code means the hard parts disappear. They do not. They just move into places like connection pooling, migration discipline, and runtime compatibility.

For teams that want Rust’s safety guarantees to extend beyond memory management and into request handling, SQL validation, and deployment shape, this is a practical stack with a clear operating model. My prediction is simple: the next wave of Rust backend adoption will come from teams that standardize on Actix, SQLx, and Postgres because it is easier to reason about than a pile of abstractions. If you are choosing a backend stack now, the better question is whether you want your compiler to catch schema mistakes before lunch or your pager to catch them at midnight.

Related reading: rust-analyzer changelog 321 for editor-side Rust workflow updates, and OxiRS v0.2.4 for another example of Rust moving deeper into production infrastructure.