Intermediate everything in Backend Dev, page 22
Go Memory Profiling with pprof
pprof takes a snapshot of your Go app's memory usage, showing which functions allocate the most. Use it to diagnose high memory consumption or find leaks. A common footgun is profiling total allocations (allocs) instead of current memory use (heap).
Go's pprof: Finding Your Code's Hotspots
pprof is a heat map for your code, revealing which functions consume the most CPU. It samples your program's call stacks to find performance hotspots. Use it to diagnose slow API endpoints or high-CPU background jobs. The footgun: profiling under no load.
Mocking in Go: Swap Real Code for Test Doubles
Mocking in Go uses interfaces to swap slow dependencies like time.Sleep with fast fakes in tests, keeping your test suite quick. Use it for network calls or database access. The footgun is testing implementation details instead of observable behavior.
Regex Engines: Backtracking vs. Finite Automata
A backtracking regex engine tries one path at a time, which can be fast but also exponentially slow. A finite-automata engine (like Go's) checks all paths at once, guaranteeing linear time. The footgun is using a backtracking engine on untrusted user input.
Go's `net/http`: A Production-Ready Web Server
Go's net/http package provides a powerful, production-ready web server without external frameworks. You build services by creating handlers—functions that process a request and write a response. It's ideal for APIs and microservices.

Buffered I/O: Batch System Calls for Speed
Buffered I/O batches many small reads or writes into fewer, larger system calls, trading a small amount of memory for a huge speed boost. It's essential for tasks like writing log files line-by-line, preventing a system call for every single line.
cargo doc: Turn Code Comments into a Website
cargo doc turns your Rust doc comments into a searchable HTML website for your crate and its dependencies. Use it to generate a local API reference or explore a dependency's API.
Go's Race Detector: Find Concurrency Bugs at Runtime
The Go race detector finds data races by watching memory access at runtime. Use go test -race in CI or on a canary instance, but remember: it only catches races that actually execute. If your tests don't trigger the race, it won't be found.
Go Benchmarking: Measure, Don't Guess
Go's benchmark runner finds stable performance numbers by repeatedly calling your code in a loop controlled by b.N. Use it to optimize hot paths or compare algorithm implementations. Forgetting b.ResetTimer() will include setup costs, skewing your results.
Cargo Clippy: Your Opinionated Rust Code Reviewer
cargo clippy is an automated code reviewer that goes beyond the compiler, catching subtle bugs, performance issues, and style violations. Run it in CI to enforce idiomatic Rust.
cargo add: Stop Editing Cargo.toml By Hand
Stop editing Cargo.toml by hand. cargo add lets you add, remove, and modify Rust dependencies from the command line. Use it to pull crates from registries, git repos, or local paths.
Rust's `std::sync::Mutex`: Guarding Shared Data
A Rust Mutex guards shared data, granting access only via a temporary RAII "guard" that auto-releases the lock. It's used inside an Arc for safe multi-threaded mutation.
Rust Async Runtimes: The Engine for `async/await`
Rust's async/await is just syntax; an async runtime like Tokio is the engine that runs the code. It polls Futures until they complete, managing I/O and scheduling. This is essential for web servers.
Rust's async/await: Cooperative Concurrency
Rust's async/await is cooperative concurrency, where tasks explicitly yield control with .await. This is ideal for I/O-bound work like managing thousands of network connections. The biggest footgun: calling an async function without .await does nothing.
Go Channels: Buffered vs. Unbuffered
Unbuffered channels are a synchronous rendezvous, blocking until both sender and receiver are ready. Buffered channels are an async mailbox, letting senders drop messages and go. The footgun is using a buffer to hide a deadlock instead of fixing it.
Rust's `impl Trait`: Hiding Concrete Types
Rust's impl Trait specifies a type by its behavior, not its name. Use it in function arguments for cleaner generics (fn f(x: impl Debug)) or in return types to hide complex types like closures and iterators, avoiding heap allocation.
Static Dispatch: Zero-Cost Abstraction via Monomorphization
Static dispatch resolves function calls at compile time, avoiding runtime overhead. Rust does this via monomorphization, creating specialized code for each concrete type. This is the default for generics, but the trade-off is larger binary sizes.
Result: Handling Recoverable Errors in Rust
Rust handles recoverable errors with the Result<T, E> enum, forcing you to deal with both success (Ok) and failure (Err) paths. This shows up when a function like File::open might fail.
Rust's Question Mark Operator (?): Propagate Errors, Not Boilerplate
The ? operator cleans up Rust error handling by propagating Err values. Instead of a verbose match block, you append ? to a Result or Option, and it automatically returns the error if present, letting you focus on the happy path.
Go Error Wrapping: Preserving Context, Not Just Text
Go's error wrapping adds context without losing the original error's type. Use fmt.Errorf with %w to create a chain of errors, then inspect it with errors.Is or errors.As. The footgun is using %v, which just formats the error as a string.
We are hiring for this. Every open role lists the topics its interview covers, so you can prepare for the real thing rather than guessing.
See open roles