Building Web Apps with Robyn: My First Impressions
Recently, I decided to dive into API development again. Since I had worked with Python before — mostly while setting up AWS Lambda functions — it felt natural to explore Python web frameworks. Unlike JavaScript, where new frameworks pop up every other day, the Python ecosystem is a bit more stable.
I started by looking into some well-known frameworks, but I also stumbled upon a few lesser-known ones, like Blacksheep and Robyn.
Robyn, in particular, caught my attention because of its uniqueness and I knew I had to give it a try.
What is Robyn?
Robyn is a web framework that combines Python’s async capabilities with a Rust-powered runtime, making it both scalable and highly efficient. Unlike traditional Python frameworks, Robyn is designed with a multi-process, multi-threaded model. It runs a master process that manages multiple worker processes, each handling multiple threads. This architecture allows it to fully utilize system resources and handle a large number of concurrent requests.
One of the standout features of Robyn is its native Rust integration — you can write Rust code directly within your Python application for complex computational tasks, boosting performance. And if you’re in development mode, you can enable hot-reloading using the --dev
flag.
For a deep dive into Robyn’s architecture, check out their official documentation.
Now, let’s create a simple project to understand how Robyn works in practice.
We’ll use uv, a modern Python package and project manager. You can check out its documentation here.
First, let’s create a virtual environment using uv:
uv venv --python 3.12
Once the virtual environment is created, activate it with:
source .venv/bin/activate
Creating Project
Next, let’s install Robyn. Since we’re using uv, we’ll install it with:
uv pip install robyn
Once the installation is complete, we can use Robyn’s CLI to create a new project. This will generate the necessary structure and files to get started quickly.
robyn --create
? Directory Path: api
? Need Docker? (Y/N) N
? Please select project type (Mongo/Postgres/Sqlalchemy/Prisma):
❯ No DB
Sqlite
Postgres
MongoDB
SqlAlchemy
Prisma
SQLModel
For now, I’ll choose the “No DB” option while setting up the project.
Next, navigate to the newly created app folder:
cd app
As I mentioned earlier, Robyn allows seamless Rust integration within your project. To demonstrate this, we’ll create a Rust file inside our Robyn app using the following command:
robyn --create-rust-file functions
This will generate a Rust file that we can use to.
So, we will write a function in rust that will receive a number and return square of that number.
// rustimport:pyo3
use pyo3::prelude::*;
#[pyfunction]
fn square(number: i32) -> i32 {
number * number
}
Now we will modify our app.py
from robyn import Robyn
from functions import square
app = Robyn(__file__)
@app.get("/")
def index():
return "Hello World!"
@app.get("/square/:number")
def calculate_square_get(request):
try:
number = request.path_params.get("number")
num = int(number)
result = square(num)
return str(result)
except (ValueError, TypeError):
return {"error": "Invalid number provided"}, 400
if __name__ == "__main__":
app.start(host="0.0.0.0", port=8080)
Now we will run the server using
robyn app.py --dev
Starting dev server...
Reloading the server
Compiling rust file: /home/personal/Development/Gitlab/robyn/api/functions.rs
Compiled rust file: /home/personal/Development/Gitlab/robyn/api/functions.rs
INFO:robyn.logger:SERVER IS RUNNING IN VERBOSE/DEBUG MODE. Set --log-level to WARN to run in production mode.
INFO:robyn.logger:Added route HttpMethod.GET /
INFO:robyn.logger:Added route HttpMethod.GET /square/:number
INFO:robyn.logger:Added route HttpMethod.GET /openapi.json
INFO:robyn.logger:Added route HttpMethod.GET /docs
INFO:robyn.logger:Docs hosted at http://0.0.0.0:8080/docs
INFO:robyn.logger:Robyn version: 0.65.0
INFO:robyn.logger:Starting server at http://0.0.0.0:8080
INFO:actix_server.builder:starting 1 workers
INFO:actix_server.server:Actix runtime found; starting in Actix runtime
INFO:actix_server.server:starting service: "actix-web-service-0.0.0.0:8080", workers: 1, listening on: 0.0.0.0:8080
See at the beginning its compiling the rust file. Now we should be able to access the application using http://localhost:8080. To square any number use this http://localhost:8080/square/{number}
Templating in Robyn
Robyn supports the Jinja2 templating engine for rendering HTML pages. This allows you to create dynamic web pages by embedding Python-like expressions within your HTML files.
we will modify our app.py
from robyn import Robyn
from functions import square
from robyn.templating import JinjaTemplate
import pathlib
import os
current_file_path = pathlib.Path(__file__).parent.resolve()
JINJA_TEMPLATE = JinjaTemplate(os.path.join(current_file_path, "templates"))
app = Robyn(__file__)
@app.get("/")
def index():
return "Hello World!"
@app.get("/square/:number")
def calculate_square_get(request):
try:
number = request.path_params.get("number")
num = int(number)
result = square(num)
return str(result)
except (ValueError, TypeError):
return {"error": "Invalid number provided"}, 400
@app.get("/template_render")
def template_render():
context = {"framework": "Robyn", "templating_engine": "Jinja2"}
template = JINJA_TEMPLATE.render_template(template_name="hello.html", **context)
return template
if __name__ == "__main__":
app.start(host="0.0.0.0", port=8080)
Now we will create a folder templates and inside we will create hello.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to {{ framework }}</title>
</head>
<body>
<h1>Welcome to {{ framework }}!</h1>
<p>This page is rendered using {{ templating_engine }}</p>
</body>
</html>
Now we should be able to browse http://localhost:8080/template_render
Conclusion
Robyn is an exciting Python web framework that brings together the best of Python’s async capabilities with the power of Rust for high-performance tasks. Its multi-process, multi-threaded architecture allows it to efficiently handle concurrent requests, making it a solid choice for building scalable web applications. With support for Rust integration, Jinja2 templating, and an easy-to-use CLI, Robyn is definitely worth exploring for your next web project.
Happy coding! 🚀