Rust Web Development 2026: The Problems Nobody Talks About
RustRover
Focus on what matters
Follow
Follow:
X X
Download
RustRover<br>Web Development<br>The Unglamorous Side of Rust Web Development
Irina Mihajlovic
This is a guest post by Mateusz Maćkowski and Marek Grzelak, co-maintainers of cot.rs and speakers at Rustikon 2026. You can watch their full talk here.
In the very beginning, all we wanted to do was build a JSON API. After doing that a few times in Rust, we noticed a recurring pattern. Every new project meant choosing libraries, wiring everything together, writing the same glue code, and solving the same setup problems again.
That pattern is one of the reasons we started working on cot.rs. We wanted Rust web development to feel less like assembling a custom toolbox every time, and more like starting with the pieces you already know you’ll need.
The advantages of Rust are well known: its safety, performance, strong types, and the specific confidence you get when your code finally compiles. This post is about everything that happens before compilation.
TL;DR
Async Rust is powerful, but the debugging experience is still rough. One panic! can give you a 100-frame backtrace, with the actual issue in your code appearing between frames 9 and 10.
Rust ORMs require you to maintain the same schema in multiple places. Declarative migrations are a better direction, and several projects are exploring this.
Error handling in Rust web frameworks is inconsistent. Getting errors to behave predictably across an entire application is harder than it sounds.
Macros are everywhere in the Rust web stack. When they work, great. When they don’t, you’re reading thousands of lines of generated code.
Compile times are a real cost for web development. A single web framework dependency can grow your dependency tree tenfold.
The ecosystem is fragmented. You choose almost every part of the stack yourself, which is powerful for experienced developers and overwhelming for everyone else.
Batteries-included frameworks like Loco.rs and cot.rs are closing the gap, but we’re not at Django or Rails level yet.
Async Rust problems: debugging, backtraces, and what nobody tells you
The first problem, and arguably the most prominent one, is async.
Rust’s async model is genuinely ingenious. It was implemented in a very clever way, and it really shows that smart people worked on it. But while it’s technically impressive, the developer experience is not quite there yet.
To use it comfortably, you need to understand both async fn and how to implement Future yourself, and they’re different enough that it can feel like learning two separate things. Then there’s the question of tasks versus threads, and if you mix them up and use the wrong data structures, you can end up with deadlocks or subtler problems. There’s still no async drop in stable Rust. And if you’ve ever tried to truly understand pinning, it’s genuinely difficult to wrap your head around why it’s even needed.
Debugging is where all of this becomes very visible. When you yield from an async function, execution returns to the runtime, and when it resumes in your function, the backtrace is essentially reset. That produces backtraces that are both huge and hard to use, and it creates problems not just for debugging, but for logging, tracing, and learning.
Here is the code that produced one of our own backtraces:
One line. The backtrace ran to 100 frames, most of them async runtime machinery. The actual program, an issue from our code, was visible between frames 9 and 10. Technically correct. Practically, not very useful.
And that’s before you get into questions like why your future isn’t Send, or why a particular future is consuming an unexpected amount of memory. Async Rust gives you performance and flexibility, but for web development specifically, it makes simple things feel more complicated than they need to be. There are active initiatives in the Rust community to improve this, but the current state still has a way to go. If you want to go deeper on where the async ecosystem is heading, this conversation with Carl Lerche, the creator of Tokio, is worth reading.
Rust ORM and database access: Diesel, SeaORM, and the schema problem
The next rough edge is database access.
Rust has solid libraries for working with databases, but the workflow can feel more manual than it should be. In Diesel, you define your model in Rust, write SQL migrations, and also maintain an automatically generated schema.rs file. That’s three representations of the same data. And yes, Diesel still uses raw SQL migrations, which is why tools like diesel-guard exist, to warn you when a migration is written in a way that could cause problems on large tables.
SeaORM improves parts of the experience, but migrations can still feel like SQL written with Rust syntax on top. It’s a common pattern across the ecosystem: specialized query DSLs that each create their own little language. We want to...