Database Tutorial #1: SQL vs NoSQL — When to Use What

You are building a new app. You need to store data. Now comes the question: should I use SQL or NoSQL? This is one of the most common decisions in backend development. The wrong choice can hurt performance, scalability, and developer experience. The right choice makes everything simpler. This article explains both options clearly so you can make the right call. What Is SQL? SQL databases are relational databases. Data is stored in tables. Tables have rows and columns. Every row has the same structure, defined by the table schema. ...

August 3, 2026 · 6 min

Rust Cheat Sheet 2026 — Syntax, Ownership, and Common Patterns

Bookmark this page. Use Ctrl+F (or Cmd+F on Mac) to find what you need. This cheat sheet covers Rust syntax, ownership, traits, error handling, and common patterns. Try examples at play.rust-lang.org. Last updated: March 2026 Variables and Types let name = "Alex"; // immutable (default) let mut count = 0; // mutable let age: i32 = 25; // explicit type const MAX: u32 = 100; // compile-time constant Type Description Example i8, i16, i32, i64, i128 Signed integers let x: i32 = -42; u8, u16, u32, u64, u128 Unsigned integers let x: u32 = 42; f32, f64 Floating point let x: f64 = 3.14; bool Boolean true, false char Unicode character 'A', '🚀' &str String slice (borrowed) "hello" String Owned string (heap) String::from("hello") () Unit type (void) fn do_thing() { } [T; N] Fixed array [1, 2, 3] Vec<T> Dynamic array vec![1, 2, 3] (T, U) Tuple (42, "hello") Option<T> Nullable value Some(42) or None Result<T, E> Success or error Ok(42) or Err("fail") Type Conversions let x: i32 = 42; let y: f64 = x as f64; // 42.0 let s: String = x.to_string(); // "42" let n: i32 = "42".parse().unwrap(); // 42 let n: i32 = "42".parse().unwrap_or(0); // 42 (or 0 on error) Strings // &str — string slice, borrowed, immutable let greeting: &str = "hello"; // String — owned, heap-allocated, growable let mut name = String::from("Alex"); name.push_str(" Smith"); // append name.push('!'); // append char // Conversions let s: String = "hello".to_string(); let s: &str = &name; // String → &str (auto-deref) // Common methods name.len() // byte length name.is_empty() // true if empty name.contains("Alex") // substring check name.starts_with("A") name.to_uppercase() name.to_lowercase() name.trim() // remove whitespace name.replace("Alex", "Sam") name.split(" ") // iterator of parts // Format let msg = format!("Hello {name}, age {age}"); Ownership and Borrowing // Ownership — each value has one owner let s1 = String::from("hello"); let s2 = s1; // s1 is MOVED to s2 // println!("{s1}"); // ERROR: s1 no longer valid // Clone — deep copy let s1 = String::from("hello"); let s2 = s1.clone(); // both valid // Borrowing — reference without taking ownership fn print_len(s: &String) { // immutable borrow println!("{}", s.len()); } fn add_excl(s: &mut String) { // mutable borrow s.push('!'); } // Rules: // 1. Many immutable references (&T) OR one mutable reference (&mut T) // 2. References must always be valid (no dangling) Structs struct User { name: String, age: u32, active: bool, } let user = User { name: String::from("Alex"), age: 25, active: true, }; // Access println!("{}", user.name); // Update syntax let user2 = User { age: 26, ..user }; // Tuple struct struct Point(f64, f64); let p = Point(1.0, 2.0); // Methods impl User { // Constructor (convention) fn new(name: &str, age: u32) -> Self { Self { name: name.to_string(), age, active: true } } // Method (takes &self) fn greet(&self) -> String { format!("Hi, I'm {}", self.name) } } Enums and Pattern Matching enum Direction { North, South, East, West } // Enums with data enum Shape { Circle(f64), // radius Rectangle(f64, f64), // width, height Triangle { base: f64, height: f64 }, } // Pattern matching with match match shape { Shape::Circle(r) => std::f64::consts::PI * r * r, Shape::Rectangle(w, h) => w * h, Shape::Triangle { base, height } => 0.5 * base * height, } // if let — match a single pattern if let Some(value) = optional { println!("Got: {value}"); } // let else — match or diverge let Some(value) = optional else { return; }; Option and Result // Option<T> — value or nothing let name: Option<&str> = Some("Alex"); let empty: Option<&str> = None; name.unwrap() // "Alex" (panics if None) name.unwrap_or("Unknown") // "Alex" (or default) name.is_some() // true name.is_none() // false name.map(|n| n.len()) // Some(4) // Result<T, E> — success or error fn divide(a: f64, b: f64) -> Result<f64, String> { if b == 0.0 { Err("division by zero".to_string()) } else { Ok(a / b) } } // ? operator — propagate errors fn read_file(path: &str) -> Result<String, std::io::Error> { let content = std::fs::read_to_string(path)?; // returns Err early Ok(content) } // Handle Result match divide(10.0, 3.0) { Ok(result) => println!("{result}"), Err(e) => println!("Error: {e}"), } Traits // Define a trait trait Greet { fn greet(&self) -> String; // Default implementation fn hello(&self) -> String { format!("Hello from {}", self.greet()) } } // Implement for a type impl Greet for User { fn greet(&self) -> String { self.name.clone() } } // Trait as parameter fn print_greeting(item: &impl Greet) { println!("{}", item.greet()); } // Trait bound syntax fn print_greeting<T: Greet>(item: &T) { println!("{}", item.greet()); } // Common derive traits #[derive(Debug, Clone, PartialEq, Eq, Hash)] struct Point { x: i32, y: i32 } Collections // Vec — dynamic array let mut v = vec![1, 2, 3]; v.push(4); v.pop(); // Some(4) v.len(); // 3 v[0]; // 1 (panics if out of bounds) v.get(0); // Some(&1) (safe) v.contains(&2); // true v.iter().filter(|&&x| x > 1).collect::<Vec<_>>(); // HashMap use std::collections::HashMap; let mut map = HashMap::new(); map.insert("name", "Alex"); map.get("name"); // Some(&"Alex") map.contains_key("name"); // true map.entry("age").or_insert("25"); for (key, value) in &map { } // HashSet use std::collections::HashSet; let mut set = HashSet::new(); set.insert(1); set.contains(&1); // true Iterators let nums = vec![1, 2, 3, 4, 5]; nums.iter().map(|x| x * 2).collect::<Vec<_>>(); // [2, 4, 6, 8, 10] nums.iter().filter(|&&x| x > 2).collect::<Vec<_>>(); // [3, 4, 5] nums.iter().sum::<i32>(); // 15 nums.iter().any(|&x| x > 3); // true nums.iter().all(|&x| x > 0); // true nums.iter().find(|&&x| x > 3); // Some(&4) nums.iter().position(|&x| x == 3); // Some(2) nums.iter().enumerate(); // (index, &value) nums.iter().zip(other.iter()); // pair elements nums.iter().take(3).collect::<Vec<_>>(); // [1, 2, 3] nums.iter().skip(2).collect::<Vec<_>>(); // [3, 4, 5] nums.iter().flat_map(|x| vec![x, x * 10]); nums.iter().fold(0, |acc, &x| acc + x); // 15 Control Flow // if / else (is an expression) let status = if age >= 18 { "adult" } else { "minor" }; // loop (infinite, break with value) let result = loop { if condition { break 42; } }; // while while count > 0 { count -= 1; } // for for i in 0..5 { } // 0, 1, 2, 3, 4 for i in 0..=5 { } // 0, 1, 2, 3, 4, 5 for item in &vec { } // iterate by reference for item in vec { } // iterate by value (moves) Closures let add = |a: i32, b: i32| -> i32 { a + b }; let double = |x| x * 2; // types inferred let greet = || println!("Hello"); // Closures capture variables let name = String::from("Alex"); let greet = || println!("Hello {name}"); // borrows name let greet = move || println!("Hello {name}"); // takes ownership Cargo Commands Command Description cargo new my_app Create a new project cargo run Build and run cargo build Build (debug) cargo build --release Build (optimized) cargo test Run tests cargo check Fast compile check (no binary) cargo clippy Lint your code cargo fmt Auto-format code cargo add serde Add a dependency cargo doc --open Generate and open docs Lifetimes // Lifetimes tell the compiler how long references are valid fn longest<'a>(a: &'a str, b: &'a str) -> &'a str { if a.len() > b.len() { a } else { b } } // Struct with a reference needs a lifetime struct Excerpt<'a> { text: &'a str, } Rule: if a function returns a reference, it must come from one of the inputs (annotated with the same lifetime). ...

July 13, 2026 · 7 min

Kubernetes Tutorial #3: Pods, Deployments, and Services

When you deploy an application to Kubernetes, you work with three objects almost every time: Pods, Deployments, and Services. A Pod is the unit that runs your containers A Deployment manages a set of Pods and handles updates A Service gives your Pods a stable network address Understanding these three is the foundation for everything else in Kubernetes. Prerequisites: A running Kubernetes cluster. See Kubernetes Tutorial #2: Installing Kubernetes Locally. Pods — The Smallest Unit A Pod is the smallest deployable unit in Kubernetes. It wraps one or more containers that share the same network and storage. ...

July 12, 2026 · 7 min

Kubernetes Tutorial #2: Installing Kubernetes Locally (minikube + kind)

You cannot learn Kubernetes from docs alone. You need a real cluster to practice on. The good news: you can run a full Kubernetes cluster on your laptop for free. In this tutorial, you will install Kubernetes locally, run your first pod, and learn the essential kubectl commands. Prerequisites: Docker must be installed. If not, see Docker Tutorial #2: How to Install Docker. Options for Running Kubernetes Locally There are four main ways to run Kubernetes on your laptop: ...

July 11, 2026 · 6 min

Kubernetes Tutorial #1: What is Kubernetes? Architecture Overview

You have 10 containers running in production. One crashes at 2 AM. Another gets too much traffic and slows down. A third needs an update, but you cannot take the whole app offline. Who restarts the crashed container? Who routes traffic away from the slow one? Who handles the update without downtime? Kubernetes does all of that. Automatically. This is the first article in the Kubernetes section of our Docker & Kubernetes Tutorial series. If you are new to containers, start with Docker Tutorial #1: What is Docker? first. ...

July 10, 2026 · 7 min

Docker Tutorial #3: Docker Images and Containers Explained

Docker has two core concepts you must understand before anything else: images and containers. Beginners often confuse them. Once you understand the difference, everything else in Docker makes sense. What is a Docker Image? A Docker image is a read-only template. It contains everything your application needs to run: the OS filesystem, libraries, dependencies, and your application code. An image is built from a Dockerfile. Think of an image like a class in object-oriented programming. It defines what a container will look like. ...

June 19, 2026 · 6 min

Docker Tutorial #2: How to Install Docker (Desktop + Engine)

Before you can run any containers, you need to install Docker. This tutorial covers every installation option: Docker Desktop for macOS and Windows, and Docker Engine for Linux servers. Last updated: June 2026. Docker pricing and features change frequently. Always check docker.com/pricing for the latest information. Docker Desktop vs Docker Engine There are two main ways to run Docker: Docker Desktop is a GUI application for macOS and Windows. It includes Docker Engine, Docker CLI, Docker Compose, built-in Kubernetes, and a visual dashboard. It is the easiest way to get started. ...

June 18, 2026 · 5 min

Your First Vibe Coding Session: A Working Tool in 12 Minutes

You have read about vibe coding. You have picked your tool. Now it is time to actually do it. This article walks you through a complete vibe coding session — step by step, with real prompts and real AI output. We will build a working CLI tool from nothing. By the end, you will understand the core cycle of vibe coding: prompt, review, test, iterate. If you have not set up your tools yet, read the Claude Code Setup Guide or install Cursor first. For help choosing, see Choosing Your AI Coding Tool. ...

June 18, 2026 · 10 min

Docker Tutorial #1: What is Docker? Containers vs VMs Explained

Docker is the most popular containerization tool in the world. According to the 2025 Stack Overflow Developer Survey, Docker is one of the most widely used tools among professional developers, with usage continuing to grow year-over-year. But what is Docker? And how is it different from a virtual machine? In this tutorial, you will learn what Docker is, how containers work, and why developers use Docker for everything from local development to production deployments. ...

June 17, 2026 · 6 min

SQL Tutorial #3: JOINs — Combining Data from Multiple Tables

So far, you have worked with one table at a time. But real databases have many tables, and the interesting answers come from combining them. In the previous article, you learned how to add and modify data. Now you will learn how to pull data from multiple tables at once using JOINs. Why Tables Are Related In our bookstore database, we have separate tables for books and authors. Why not put everything in one table? ...

June 15, 2026 · 12 min