Ecosystem

Rust’s crate ecosystem is mature for systems programming, web services, and CLI tools. Here are the go-to libraries organized by category.

Web Frameworks

axum (preferred)

Built on Tokio and Tower. Modular, composable, strong typing.

use axum::{routing::get, Router, Json, extract::Path};
use serde::Serialize;

#[derive(Serialize)]
struct User {
    id: u32,
    name: String,
}

async fn get_user(Path(id): Path<u32>) -> Json<User> {
    Json(User { id, name: "Alice".into() })
}

#[tokio::main]
async fn main() {
    let app = Router::new()
        .route("/users/{id}", get(get_user));

    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}
[dependencies]
axum = "0.8"
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }

actix-web

Higher raw throughput in benchmarks, actor-based model. More mature but less idiomatic.

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

async fn hello() -> HttpResponse {
    HttpResponse::Ok().body("Hello!")
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| App::new().route("/", web::get().to(hello)))
        .bind("0.0.0.0:3000")?
        .run()
        .await
}
FrameworkBest forNotes
axumNew projects, idiomatic RustBuilt on Tower middleware ecosystem
actix-webMaximum throughput, existing projectsLarger API surface, actor model

CLI

clap v4

The standard for argument parsing. Derive macros generate the parser from a struct.

use clap::Parser;

#[derive(Parser)]
#[command(version, about = "A fast file processor")]
struct Cli {
    /// Input file path
    input: String,

    /// Output format
    #[arg(short, long, default_value = "json")]
    format: String,

    /// Enable verbose output
    #[arg(short, long)]
    verbose: bool,
}

See CLI Tool quickstart for a full walkthrough.

Serialization

serde

The universal serialization framework. Nearly every Rust library uses it.

use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)]
struct Config {
    host: String,
    port: u16,
    #[serde(default)]
    debug: bool,
    #[serde(rename = "maxConnections")]
    max_connections: Option<u32>,
}

// JSON
let json = serde_json::to_string_pretty(&config)?;
let config: Config = serde_json::from_str(&json)?;

// TOML
let toml = toml::to_string(&config)?;
let config: Config = toml::from_str(&toml)?;
Format crateFormat
serde_jsonJSON
tomlTOML
serde_yamlYAML
csvCSV
bincodeBinary (compact, fast)

Error Handling

CratePurposeUse when
anyhowEasy error propagation with contextApplication code, CLIs, scripts
thiserrorDefine custom error types with deriveLibrary code, public APIs

See Error Handling for detailed usage.

HTTP Client

reqwest

Async HTTP client built on Tokio. Supports JSON, TLS, cookies, proxies.

use reqwest::Client;
use serde::Deserialize;

#[derive(Deserialize)]
struct Repo {
    name: String,
    stargazers_count: u32,
}

async fn fetch_repo(owner: &str, repo: &str) -> anyhow::Result<Repo> {
    let client = Client::new();
    let repo = client
        .get(format!("https://api.github.com/repos/{owner}/{repo}"))
        .header("User-Agent", "rust-app")
        .send()
        .await?
        .json::<Repo>()
        .await?;

    Ok(repo)
}
[dependencies]
reqwest = { version = "0.12", features = ["json"] }

Tip: Reuse Client instances. Creating a new client per request is wasteful - it sets up a new connection pool each time.

Database

sqlx - compile-time checked SQL

use sqlx::postgres::PgPoolOptions;

#[derive(sqlx::FromRow)]
struct User {
    id: i32,
    name: String,
    email: String,
}

async fn get_users(pool: &sqlx::PgPool) -> anyhow::Result<Vec<User>> {
    let users = sqlx::query_as::<_, User>("SELECT id, name, email FROM users WHERE active = $1")
        .bind(true)
        .fetch_all(pool)
        .await?;

    Ok(users)
}

diesel - ORM with query builder

use diesel::prelude::*;

#[derive(Queryable)]
struct User {
    id: i32,
    name: String,
    email: String,
}

fn get_users(conn: &mut PgConnection) -> QueryResult<Vec<User>> {
    users::table
        .filter(users::active.eq(true))
        .load(conn)
}
CrateStyleBest for
sqlxRaw SQL, compile-time checkedProjects that prefer SQL, need flexibility
dieselQuery builder / ORMType-safe query composition, migrations

Async Runtime

Tokio

The standard async runtime. Used by axum, reqwest, sqlx, and most of the async ecosystem.

[dependencies]
tokio = { version = "1", features = ["full"] }

See Async Rust for detailed patterns.

Other Essential Crates

CratePurposeExample use
tracingStructured loggingtracing::info!(user_id = 42, "request handled")
chronoDate and timeUtc::now(), parsing, formatting
uuidUUID generationUuid::new_v4()
regexRegular expressionsRegex::new(r"\d+")?
rayonData parallelismvec.par_iter().map(...) (drop-in parallel iterators)
randRandom number generationrand::random::<u32>()
towerMiddleware frameworkTimeouts, rate limiting, retries for services
bytesEfficient byte buffersZero-copy networking, protocol parsing

Rust vs Go

Both are modern systems-adjacent languages. Here’s how they compare:

AspectRustGo
MemoryOwnership, no GCGarbage collected
Concurrencyasync/await + Tokiogoroutines + channels (built-in)
Error handlingResult<T,E>, ? operatorMultiple return values, if err != nil
Type systemGenerics, traits, enumsInterfaces, generics (since 1.18)
Compile speedSlow (minutes for large projects)Fast (seconds)
Runtime performanceFaster (no GC pauses, zero-cost abstractions)Fast (but GC pauses under load)
Learning curveSteep (ownership, lifetimes)Gentle (simple by design)
Best forPerformance-critical, correctness-criticalMicroservices, DevOps tools, quick iteration
Binary sizeSmall (static by default)Larger (includes runtime + GC)
Ecosystemcrates.io, CargoGo modules, go get
Null safetyOption<T> (no null)nil (can panic at runtime)

Tip: Choose Go when you need fast iteration and simple concurrency. Choose Rust when you need maximum performance, memory safety guarantees, or are building something that can’t afford GC pauses (embedded, game engines, databases).

Finding Crates

  • crates.io - Official package registry
  • lib.rs - Better search and categorization
  • blessed.rs - Curated list of recommended crates by category
  • cargo add <crate> - Search and add from the command line

Tip: Check download counts and last-updated dates on crates.io. A crate with millions of downloads and recent updates is usually a safe bet. Avoid crates that haven’t been updated in over a year unless they’re feature-complete (like regex).

Next: Async Rust | Gotchas