Actix Web: Fast as Hell, Documentation is Hell

Actix Web hits insane RPS in TechEmpower benchmarks (ignore the "1 million RPS" bullshit claims floating around). But here's what they don't tell you:
The actor system documentation is fucking garbage. You'll spend weeks figuring out basic patterns because the official examples assume you're already a message-passing expert. Learned this when our payment processing just... stopped working one Tuesday. No errors, no panics, just requests hanging forever. Took me 6 hours to figure out two actors were waiting for each other in a message ordering deadlock. Had to add debug prints to like 8 different actor handlers just to trace the message flow.
Real Production Gotcha: Actix Web 4.0 migration broke half our middleware stack. The migration guide was written by someone who apparently hates developers. Spent 3 days tracking down a single compilation error that turned out to be a breaking change buried in release notes.
Error logging? Good fucking luck. As Luca Palmieri documented, Actix only logs the last error in a request chain. When middleware fails, you lose all context about what actually went wrong. We now manually wrap every handler just to get decent error reporting.
Bottom Line: Use Actix if you love performance and hate your junior developers. Perfect for teams that already know Rust inside out.
Axum: Finally, Something That Doesn't Hate You

Look, after dealing with Actix's actor hell for months, switching to Axum felt like moving from a haunted house to a boring apartment. Which is exactly what you want in production.
Our main API has been running on Axum for 8 months now - serves around 2M requests daily. Memory usage just... stays stable. No weird spikes, no gradual leaks, no "why the fuck is this using 8GB" alerts while you're at your kid's birthday party.
What Actually Works: The type system doesn't fight you. Extractors make sense. Routing is straightforward. When something breaks, the error usually points to the actual problem instead of some deep tokio internals bullshit.
The Annoying Parts: Tower middleware is where things get hairy. Docs assume you already understand the tower ecosystem, which most people don't. Custom extractors mean digging through Tower source code because the docs are sparse. Error messages improve your vocabulary of creative profanity.
Rocket: The \"Rails of Rust\" That Actually Means It

Rocket hits 60-80k RPS which is fine for most apps, but the compilation times... jesus. Change one route parameter and go make coffee because you're waiting 3-5 minutes minimum. Add a few more routes and you're looking at 8-10 minute builds.
The type system is both a blessing and a curse. It catches tons of routing bugs at compile time, which is great. But the macro error messages are written in some alien language that requires a decoder ring to understand.
Migration Hell: The Rocket 0.5 upgrade broke our entire routing layer. Not "oh, change this syntax" broken - I mean "rewrite 40% of your route handlers" broken. The migration guide was basically "here's what changed, good luck figuring out how to fix your code."
Why People Love It: When it finally compiles, the shit just works. Guards and fairings make sense if you've used Rails before. Type-safe routing means you can't accidentally return the wrong status code or forget to validate input.
Warp: For Masochists Who Like Functional Programming
Warp will make you feel smart when you're composing elegant filter chains and like an idiot when you're debugging them at 2AM. The functional approach is beautiful in theory, nightmare fuel in practice.
The Memory Leak From Hell: Had a Warp microservice running for 6 weeks when ops started bitching about gradual memory growth. Not a sudden spike, just slow steady growth from 50MB to 800MB over weeks.
Took me and two other developers almost a month to track down that badly composed filters were creating reference cycles. The Rust compiler doesn't catch this shit, and Warp's GitHub issues were full of similar stories.
Debugging Hell: When a filter chain fails, good fucking luck figuring out which layer rejected the request. Error messages give you generic "rejection" with zero context. Spent entire evenings adding debug prints to 15-layer filter compositions just to find which filter said no.
Why Use It: Fast, minimal, and perfect for microservices if your team already thinks in functional programming terms. Don't expect to onboard anyone who hasn't done Haskell or Clojure.
