Feather: Feather: A web framework that skips Rust's async boilerplate and jus
19 comments
·May 4, 2025tczMUFlmoNk
Qwuke
Yes, if you want a mature web framework that doesn't force you to use async then Rocket already exists, which is multithreaded and quite performant - and now allows you to use async if you want to.
Feather seems fundamentally single threaded and requires more boilerplate for something pretty simple. So I'm not sure the claim about developer experience holds up to scrutiny here either.
cirego
I noticed the same thing. I would have expected an Arc<Mutex<…>> or something similar for safe concurrency. Not sure what value is delivered by a single threaded, blocking web server.
serial_dev
Not a Rust expert by any means, but what does it bring that there is no async in the framework? Wouldn’t most of the libraries use async anyway, connecting to queues, databases, external services via HTTP? It’s hard to imagine a backend that still won’t need async, so I wonder if it is even worth trying… (please do let me know if it is)
dochtman
Async is a language feature to enable scalability, but an alternative approach is just to spawn a bunch of threads and block threads when waiting for I/O to happen. That is the approach used by this framework.
wint3rmute
This is especially true for newcomers, but async Rust has significant mental overhead. You quickly run into things like the Pin marker, Tokio runtime, complex compiler errors related to ownership, basically each "normal" component of the language get some additional complexity due to async.
If you're new to Rust and you want to "just make a web app", the view at the async Rust landscape could be a turnoff for novices. I speak from experience, having started a couple Rust projects in Python/C++ teams. After writing in Rust for 3+ years I can navigate async contepts without troubles, but for someone coming from the usual popular languages (Python/C#/Java/C++), there are simply too many new things to learn when jumping straight into an async Rust codebase.
IMO this framework is going in a good direction, assuming that it will only be used for small/educational projects.
For the async Rust landscape, things are improving every year, IMO we're around 5-10 years until we get tooling which will feel intuitive to complete newcomers.
sodality2
A large application, maybe, but sometimes you have a very small scope application that won't otherwise use async, so you value binary size, compile time, etc over theoretical XXX ops/sec
roude404
It seems it goes more in the direction easy to use and quick setup of small endpoints and if you need some more you could integrate the tokio runtime (or any other async runtime) on top of it.
watermelon0
In most cases, you have both an async and blocking/sync approach, sometimes even in the same library.
wishinghand
Could be confused with Feathers, a Javascript web framework.
ivape
Do we know if a Rust webserver can provide just more pure raw metal performance? I believe I've heard the case to be true for Go. What use case do we have for this, high performance chat/game servers?
shmerl
What is DX?
ianbutler
Developer experience, like how nice it is to work with
null
firejake308
Developer experience
refulgentis
I'm curious, in this example, what does MiddlewareResult::Next do?
use feather::{App, AppContext, MiddlewareResult,Request,
Response};
fn main() {
let mut app = App::new();
app.get("/",|_req: &mut Request, res: &mut Response, _ctx: &mut AppContext| {
res.send_text("Hello, world!");
MiddlewareResult::Next
});
app.listen("127.0.0.1:3000");
}
Given my lack of experience, I'm sure it's needed, it's just unclear to me what purpose it would serve in a server app.Qwuke
You're right, it doesn't really seem necessary and makes the responses of the route end up as side effects rather than part of the return type of the route functions.
Most web frameworks in Rust don't make responses a side effect and keep them as a typed response since that's better devex and much less boilerplate.
IshKebab
Why does it not look lightweight? I think you might be seeing "middleware" and thinking that it enables a load of middleware by default, which is unlikely to be the case?
Qwuke
When you have 20 routes each being terminated with redundant `res.json(success);\n MiddleWare::Next` I think you can imagine why someone might see it as not lightweight in terms of unnecessary boilerplate - which most Rust webframeworks, async or not, don't require you to write out.
The fact that a request can happily get a mutable reference to a shared context felt suspicious to me, so I ran a quick test, and it seems like the whole server is single-threaded:
That is: when the request handler takes 2 seconds, and you fire two requests simultaneously, one of them returns in 2 seconds, but the other one takes 4 seconds, because it has to wait for the first request to finish before it can begin.It feels like this has to be the behavior from the API, because if two threads run `ctx.get_mut_state::<T>()` to get a `&mut T` reference to the same state value, only one of those references is allowed to be live at once.
It doesn't quite seem fair to call this "designed for Rust’s performance and safety". One of the main goals of Rust is to make safe concurrency achievable. But this library just throws any hope of concurrency away altogether.