Procedural macros operate on Rust syntax trees, enabling custom #[derive(...)], attribute macros, or function-like macros. I write proc macros for boilerplate reduction: auto-generating builders, serialization, or validation. They're more powerful than declarative macros but require a separate crate with proc-macro = true. The syn crate parses Rust code, quote generates code, and proc-macro2 bridges the APIs. Proc macros run at compile time and can introspect types. I use them to enforce invariants, generate test cases, or create DSLs. They're the foundation of serde's derive macros and many popular crates. Writing them is advanced but worthwhile for widely-used patterns.