Axum vs Actix

Hello there! Before we get started I just want to say that everything stated in this post is my own thoughts and opinions about the different frameworks, therefore it should be taken with a grain of salt and won’t give you the full picture of either framework.

Where it started

It all started with an idea in my head, one evening I was bored, and decided to learn a new thing about rust. More specifically, I wanted to learn web/api developement. My idea was simple, a minimal and completely anonymous paste bin clone with all your basic settings. I therefore started to research online about making web apps in rust and quickly came across the two biggest frameworks for doing just that, axum and actix-web.

I couldnt find any definitive answer about which one was better, so instead of asking others about their experience with both like most people probably would have, I decided to spin the wheel! It ended up landing on actix, and that evening I threw together pesto (github), a simple pastebin clone which I then hosted on my local, tiny homelab. One thing I couldnt get off my mind the day after though was that I never tried axum, and therefore didnt know if it was better or not.

A couple days later I therefore decided to try axum, this time I would make a simple url shortener, which in architecture is almost identical to a pastebin clone and therefore a good project to compare pesto to. After just a couple hours I had made kiln (github) and threw that up on my homelab as well.

The comparison

Okay, so im going to be real with you here: in my opinion, there wasnt too much of a difference in the frameworks and how they operate. Note that I only made 2 very small projects, and didnt even get close to testing the entirety of the 2 frameworks, but in the basics I actually used, I didnt see much of a difference.

I will show the similarities with a comparison, how you route registration works across the 2 frameworks. For this example we are going to do the following:

  • Register an api route at /api/shorten and binding it to a function called crate::api::shorten_func
  • Registering a route at / which servers a static html file at static/index.html
  • Publish it all to 0.0.0.0:8080

Alright, here is the code to do this simple task in both frameworks:

Axum

#[tokio::main]
async fn main() -> anyhow::Result<()> {
  let router = Router::new() // Creates a new router, which defines routes, appdata etc and connects your backend / functions with axum
    .nest_service("/", ServeFile::new("static/index.html")) // ServeFile returns a service, so well nest it inside our router
    .route("/api/shorten", post(crate::api::shorten_func)) // Routes POST requests from /api/shorten to the shorten_func function

  let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await?; // Defines the listener and what the listener should bind to
  let server = axum::serve(listener, router); // Serves the router
  
  Ok(()) // Returns that anyhow::Result we said we would return at the function declaration
}

Actix

// We define a function to return the raw string of the index.html file
pub async fn index() -> impl Responder { HttpResponse::Ok().body(include_str!("static/index.html")) }

#[actix_web::main]
async fn main() -> std::io::Result<()> {
  HttpServer::new(move || { // We create a new http server
    App::new() // We create a new App for the http server to route
      .route("/", web::get().to(index)) // We bind the / route to our index function, which returns our index.html
      .route("/api/shorten", web::post().to(crate::api::shorten_func)) // We bind the /api/shorten url POST requests to a shorten_func function
    }).bind("0.0.0.0:8080")?.run().await // We bind the server and run it
}

Got it? Alright. At a first glance these may look different, but in syntax I feel they are quite similar, just with different names on their functions etc. But in the end I actually decided to go with axum, for a couple reasons.

Why I chose axum

Here are some of my reasons for choosing axum:

  • It is the newest, and from the same devs who made tokio, which means it has great tokio integration for serving multiple servers at the same time
  • I liked its router system a lot, using nest_service and similar functions its really easy to make multiple routers, and then join them together to one main router
  • I have more experience with it. After these 2 projects I decided to explore axum specifically a bit further, and made wrix (github), which gave me more experience with dealing with sessions and other more complex systems in axum.
  • Axum generally feels more modern to me, and from what I’ve seen it has gained a lot of popularity in recent years.

Conclusion

Personally, I chose to go with axum for my future projects, but if its one thing you should take away from this post it should be that this is a very opinionated question, and at the end of the day its up to your preferences. I have come with some arguments why axum is better in my opinion, but I can understand why some might like actix more, and its completely fine to do so! Just dont go around and discriminate others or treat others unfairly because of their opinion on the matter, its a web framework for gods sake! Why would you discriminate someone about their preferences about web frameworks??