A faster and safer web with Rust
As web developers, we’re constantly on the lookout for the perfect tech stack that balances performance, reliability, and developer experience. In recent years, Rust has emerged as a strong contender for backend development, and when combined with the Rocket.rs framework and SQLx, it forms a potent toolkit that can revolutionize your web applications. Let’s dive into the benefits of using this Rust stack and explore why it might be the right choice for your next project.
Rust, Performance and Reliability:
Rust, known for its memory safety and zero-cost abstractions, provides a solid foundation for building high-performance web backends. When paired with Rocket.rs, an async web framework, you get the best of both worlds: expressive code and blazing-fast execution. Rocket’s ease of use and intuitive syntax make it a joy to work with, even for newcomers to the Rust ecosystem. Rocket, being built on Rust, provides a strong focus on safety and memory management.
According to the Web Frameworks Benchmark, Express.js, one of the most commonly used web framework for javascript, comes in at ~24k requests per second, Rocket.rs comes in at 110k requests per second. I quickly ran some tests of my own, and I won't claim that they're indicative of any real world scenarios. Real projects are larger and inherently deal with different constraints. The environment is also much different. We can also reasonably expect that in production, people would make different decisions to squeeze out as much performance as possible. Nevertheless, in just serving a plain text hello world path, ApacheBench gave the following results for Rocket:
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.5 0 5
Processing: 6 22 2.0 21 30
Waiting: 0 13 6.0 12 29
Total: 6 22 2.0 22 30
Percentage of the requests served within a certain time (ms)
50% 22
66% 23
75% 23
80% 24
90% 24
95% 25
98% 26
99% 27
100% 30 (longest request)
and these other ones for Express.js :
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.6 0 7
Processing: 12 32 6.5 30 71
Waiting: 9 26 5.9 25 61
Total: 12 32 6.5 30 71
Percentage of the requests served within a certain time (ms)
50% 30
66% 32
75% 35
80% 36
90% 40
95% 44
98% 50
99% 51
100% 71 (longest request)
The difference does not look substancial, but once we deal with more complexity, once we start serving different types of content, dealing with JSON, doing other operations ...etc the gap will certainly widen.
For reference, the javascript and rust codes executed :
const express = require("express");
const app = express();
app.get("/", (req, res) => {
res.send("Hello from Express!");
});
app.listen(8000);
#[macro_use]
extern crate rocket;
#[get("/")]
fn index() -> &'static str {
"Hello from Rust!"
}
#[launch]
fn rocket() -> _ {
rocket::build().mount("/", routes![index])
}
and the test command :
ab.exe -n 10000 -c 100 http://localhost:8000/
Ofcourse, you can use something like hyper-express for javascript, but in a similar vein, we can use something like Actix for Rust. After all, Rocket.rs is not really a "fast Rust web framework", there are many other crates that beat it by miles, still, it's as fast as the fastest npm crate.
One of the reasons that I chose to recommend Rocket.rs is the overall developer experience, this is really important for web and I can safely say that Rocket.rs offers a really comfy developer experience, it's really enjoyable to get started with and it's easy to get things done. There are lots of resources online and it's easy to find posts on issues that you might encounter or features that you'll want to implement. Rpclet os certainly not the fastest framework. If you're looking for pure speed then you should look at something like Actix or Ntex.
SQLx, Make sure your queries are correct at runtime
SQLx, an asynchronous SQL toolkit for Rust, adds another layer of performance and reliability to your backend. But its power extends beyond simply executing SQL queries. One of its most compelling features is the ability to test SQL queries at compile time, leading to a better developer experience and fewer runtime errors.
Compile-time SQL Validation:
With SQLx, you can write SQL queries directly in your Rust code using the sqlx::query!() macro. This macro not only allows you to execute SQL queries at runtime but also enables compile-time validation of these queries. Here’s how it works:
let _account = sqlx::query!("SELECT * FROM account WHERE id = ?", 1);
When you compile your Rust code, SQLx parses the SQL query inside the query!() macro and validates it against your database schema. If there are any syntax errors or type mismatches, the compiler catches them and raises errors during compilation. This means you catch SQL errors before they ever reach your production environment, leading to more robust and reliable applications.
Improved Developer Experience:
By catching SQL errors at compile time, SQLx significantly improves the developer experience. Developers no longer have to wait until runtime to discover SQL-related issues. Instead, they receive immediate feedback within their development environment, allowing them to iterate quickly and with confidence. Additionally, the integration of SQL queries directly into Rust code streamlines the development process, reducing context switching between different languages or tools.
Safer Refactoring:
As your application evolves, you may need to refactor your SQL queries to accommodate changes in your data model or business logic. With SQLx, refactoring becomes safer and less error-prone. Since SQL queries are validated at compile time, any changes that break existing queries will be flagged immediately. This enables you to refactor with confidence, knowing that your SQL queries remain valid throughout the proces
Conclusion
Admittedly, Rust poses certain challenges, such as a smaller developer pool and a steeper learning curve compared to more established languages like JavaScript and Python. However, these challenges are mitigated by Rust's safety guarantees, which reduce the time spent fixing runtime bugs and common pitfalls. Additionally, the vibrant Rust community offers abundant resources and support, easing the learning journey for newcomers.
In conclusion, embracing Rust, along with Rocket.rs and SQLx, for web backend development brings forth a plethora of benefits – from superior performance and cost-effectiveness to unparalleled safety and stability. While challenges exist, the rewards far outweigh them, making Rust a compelling choice for the modern web development landscape. As businesses strive for excellence in their digital endeavors, Rust stands as a beacon of innovation and reliability in the realm of backend development.