axum for type-safe async HTTP servers

Axum is a modern web framework built on tokio and hyper. It uses extractors (like Json<T>, Path<T>, State<S>) to parse requests into Rust types, and the compiler ensures your handlers match their routes. Middleware is just functions,

reqwest for async HTTP client with connection pooling

Reqwest is the most popular async HTTP client for Rust. It's built on tokio and hyper, with a high-level API for making requests. Connection pooling, redirects, timeouts, and TLS are handled automatically. I use the builder pattern to configure client

serde for zero-copy serialization and deserialization

Serde is Rust's serialization framework, supporting JSON, YAML, TOML, MessagePack, and more through format-specific crates. With #[derive(Serialize, Deserialize)], your structs automatically convert to and from these formats. Serde is extremely fast b

clap for CLI argument parsing with derive macros

For CLI tools, clap is the de facto standard. Version 4+ supports derive macros, letting you define arguments as a struct with attributes. The library auto-generates help text, validates inputs, and supports subcommands. I annotate fields with #[arg(s

Rc and RefCell for shared ownership with interior mutability

When you need multiple ownership without threads, Rc<T> (reference counted) is the answer. It tracks the number of owners at runtime and frees the data when the count reaches zero. For mutability, combine it with RefCell<T>, which enforces

Box<T> for heap allocation and recursive types

Box&lt;T&gt; is Rust's simplest smart pointer: it allocates T on the heap and gives you ownership. When the Box goes out of scope, the heap memory is freed. I use Box when I need indirection (like recursive types), when moving large structs is expensi

Pattern matching with match for exhaustive case handling

Rust's match expression is like a switch statement on steroids. It requires exhaustive handling of all cases, and the compiler enforces this. You can match on enums, tuples, references, ranges, and destructure nested data. Guards (if condition) add ex

Iterator trait and combinators for zero-cost collection processing

Rust's Iterator trait provides a rich set of combinators (.map(), .filter(), .fold(), etc.) that compose without allocating intermediate collections. Iterators are lazy: they don't do work until you consume them with .collect(), .for_each(), or simila

Option<T> for explicit null handling

Rust has no null. Instead, Option&lt;T&gt; represents a value that might be absent. It's an enum with two variants: Some(T) and None. You must explicitly handle both cases with match, if let, or combinator methods like .map() and .unwrap_or(). This el

Derive macros for automatic trait implementations

Rust's #[derive] attribute auto-generates trait implementations for common traits like Debug, Clone, PartialEq, and Serialize. This eliminates boilerplate and ensures consistency. For example, #[derive(Debug)] generates a debug formatter that prints a

Trait bounds for generic functions with behavior constraints

Traits define shared behavior, and trait bounds let you write generic functions that work with any type implementing a trait. The syntax T: Display means "T must implement Display." This is similar to interfaces in other languages but more powerful: y

tokio::spawn for concurrent task execution

Tokio's spawn creates a new async task that runs concurrently on the runtime's thread pool. Unlike OS threads, tasks are lightweight (kilobytes of memory) and scheduled cooperatively. Each task must be 'static and Send, meaning it can't borrow local v