Building Web Apps with Robyn: My First Impressions

Md. Tanjil Bhuiyan
4 min readFeb 12, 2025

--

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.

Design diagram how robyn actually works.
https://robyn.tech/documentation/en/architecture

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! 🚀

--

--

Md. Tanjil Bhuiyan
Md. Tanjil Bhuiyan

Written by Md. Tanjil Bhuiyan

DevOps Engineer | Passionate about Cloud Computing , Automation and Containerization

No responses yet