Rust Tutorial #23: Database with SQLx

In the previous tutorial, we built a REST API with Axum using in-memory storage. Now we add a real database with SQLx. SQLx is an async database library for Rust. It supports PostgreSQL, MySQL, and SQLite. Unlike ORMs, SQLx lets you write plain SQL while still being type-safe. It can even check your queries at compile time against a real database. In this tutorial, we use SQLite because it needs no server setup. Everything you learn applies to PostgreSQL and MySQL too — just change the connection string and SQL dialect. ...

March 26, 2026 · 10 min

Rust Tutorial #22: Web API with Axum

In the previous tutorial, we learned to make HTTP requests. Now we build the other side — a REST API server with Axum. Axum is a web framework built on top of Tokio and Tower. It is fast, type-safe, and ergonomic. Unlike some other frameworks, Axum uses standard Rust types and traits. There are no macros on your handler functions. Everything is just regular async functions. Setting Up Add these dependencies to your Cargo.toml: ...

March 26, 2026 · 8 min

Rust Tutorial #21: HTTP with Reqwest

In the previous tutorial, we learned Serde for serialization. Now we use those skills to make HTTP requests with Reqwest — the most popular HTTP client in Rust. Most real applications talk to APIs. Whether you fetch data, send forms, or call microservices, you need an HTTP client. Reqwest makes this easy while staying fully async. Setting Up Add these dependencies to your Cargo.toml: [dependencies] tokio = { version = "1", features = ["full"] } reqwest = { version = "0.12", features = ["json"] } serde = { version = "1", features = ["derive"] } serde_json = "1" The "json" feature on reqwest enables built-in JSON parsing with Serde. ...

March 26, 2026 · 7 min

Rust Tutorial #20: Serde and JSON

In the previous tutorial, we learned advanced error handling. Now we learn Serde — the serialization framework that powers most data handling in Rust. Serde converts Rust structs and enums to and from formats like JSON, TOML, YAML, and more. It is not just a JSON library. Serde separates “what to serialize” from “what format to use.” You write #[derive(Serialize, Deserialize)] once, and your type works with every supported format. Setting Up Add Serde and the formats you need to Cargo.toml: ...

March 26, 2026 · 7 min

Rust Tutorial #19: Advanced Error Handling (thiserror, anyhow)

In the previous tutorial, we learned testing in Rust. Now we take error handling to the next level with thiserror and anyhow — the two crates that every production Rust project uses. In Tutorial #8, we learned the basics: Result, Option, the ? operator, and custom error types. That works fine for small programs. But as your project grows, writing Display, From, and Error implementations by hand gets tedious. That is where thiserror and anyhow come in. ...

March 26, 2026 · 10 min

Rust Tutorial #18: Testing in Rust

In the previous tutorial, we learned modules and project organization. Now we learn testing – one of Rust’s best features. Rust has testing built into the language and toolchain. You do not need to install a separate testing framework. Write #[test], run cargo test, and you are done. The compiler and test runner handle everything. Good tests give you confidence to refactor code, add features, and fix bugs without breaking existing functionality. ...

March 26, 2026 · 9 min

Rust Tutorial #17: Modules and Crates

In the previous tutorial, we learned Rust collections. As projects grow, putting everything in one file becomes unmanageable. In this tutorial, we learn modules – Rust’s system for organizing code into logical units. Good project structure makes code easier to read, test, and maintain. Rust’s module system is simple once you understand the rules. Let us learn them step by step. What is a Module? A module is a named container for functions, structs, enums, and other items. Modules control: ...

March 26, 2026 · 8 min

Rust Tutorial #15: Async/Await and Tokio

In the previous tutorial, we learned threads, channels, and Mutex for concurrency. Now we learn async/await – a different way to handle concurrent work. Threads are good when you have CPU-heavy tasks. But many programs spend most of their time waiting – for network responses, file reads, or database queries. Creating one thread per request wastes memory. Async programming solves this problem. It lets one thread handle thousands of waiting tasks. ...

March 26, 2026 · 8 min

Rust Tutorial #16: Channels and Message Passing

In the previous tutorial, we learned async programming with Tokio. Now we dive deeper into channels — the primary way async tasks communicate with each other. Channels let tasks send and receive messages without sharing memory directly. This is the “message passing” model of concurrency. Instead of locking shared data with a Mutex, you send data through a channel. The task that receives it owns it completely. Tokio provides four channel types. Each one solves a different problem. By the end of this tutorial, you will know when to use each one. ...

March 26, 2026 · 10 min

Rust Tutorial #14: Concurrency — Threads, Channels, and Message Passing

In the previous tutorial, we learned smart pointers. Now we learn concurrency — running code on multiple threads at the same time. Concurrency is hard in most languages. Data races, deadlocks, and race conditions cause bugs that only show up in production. Rust prevents most of these bugs at compile time. The ownership system guarantees that you cannot share data unsafely between threads. This is called fearless concurrency. The compiler catches mistakes before your code runs. ...

March 26, 2026 · 8 min