Meet Robyn, younger brother of the Flask web framework

NOTE: Don’t directly change your production server with Robyn web framework. The user’s discretion is advised.

Have you heard of this new gossip spreading in GitHub town!!! There is a newborn web framework that came into the town and recently it is getting a lot of popularity because of its cool features and async compatibility and its fast processing as it is built on Rust.

Photo by Jo Coenen – Studio Dries 2.6 on Unsplash

The author of the Robyn web framework Sanskar Jethi started this project on 22nd May 2021. Let’s first talk about some of its features

Features

  • Underactive development!
  • Written in Rust, btw xD
  • A multithreaded Runtime
  • Extensible
  • A simple API
  • Sync and Async Function Support
  • Dynamic URL Routing
  • Multi-Core Scaling
  • WebSocket!
  • Hot Reloading (Still experimental)
  • Query Params
  • Events (Startup and Shutdown)
  • Community First and truly FOSS!

Usage

pip install robyn

To start a server with a single super useful API of hello world

from robyn import Robyn

app = Robyn(__file__)


@app.get("/")
async def hellow_world():
    return "Hello, world!"

app.start(port=5000)

Now just run the file with the python command

python main.py

You can see the output in the terminal below

But after a while, the logs will be flooded by the below message. But it’s not a big deal, I’m also thinking to contribute in this cool project.

There is also a hot reloading feature but it’s in beta version as mentioned by the contributors. You can enable it using the below command

python main.py --dev

Somehow quitting the framework is not as smooth as I thought. It left some dangling processes alive on the port once it exited.

Writing API requests is very easy and the same as Flask 2.0

GET Request

@app.get("/")
async def h(request):
return "Hello World"

POST Request

@app.post("/post")
async def postreq(request):
return bytearray(request["body"]).decode("utf-8")

PUT Request

@app.put("/put")
async def postreq(request):
return bytearray(request["body"]).decode("utf-8")

PATCH Request

@app.patch("/patch")
async def postreq(request):
return bytearray(request["body"]).decode("utf-8")

DELETE Request

@app.delete("/delete")
async def postreq(request):
return bytearray(request["body"]).decode("utf-8")

Having Dynamic Routes

You can add params in the routes and access them from the request object.

@app.post("/jsonify/:id")
async def json(request):
print(request["params"]["id"])
return jsonify({"hello": "world"})

Some of the features are exactly like Flask. If you want to get JSON data then you can use the Jsonify function of Robyn web framework

from robyn import jsonify  @app.post("/jsonify") 
async def json(request):
print(request)
return jsonify({"hello": "world"})

Websockets

Robyn web framework is also having an outbox solution for WebSocket in it. This feature really impressed me. You can now serve WebSockets using Robyn. Firstly, you need to create a WebSocket Class and wrap it around your Robyn app.

from robyn import Robyn, static_file, jsonify, WS
app = Robyn(__file__)
websocket = WS(app, "/web_socket")

Now, you can define 3 methods for every web_socket for their life cycle, they are as follows:

@websocket.on("message")
def connect():
global i
i+=1
if i==0:
return "Whaaat??"
elif i==1:
return "Whooo??"
elif i==2:
return "*chika* *chika* Slim Shady."
elif i==3:
i= -1
return ""@websocket.on("close")
def close():
return "Goodbye world, from ws"@websocket.on("connect")
def message():
return "Hello world, from ws"

The three methods:

  • “message” is called when the socket receives a message
  • “close” is called when the socket is disconnected
  • “connect” is called when the socket connects

Usage

@websocket.on("message")
async def connect():
global i
i+=1
if i==0:
return "Whaaat??"
elif i==1:
return "Whooo??"
elif i==2:
return "*chika* *chika* Slim Shady."
elif i==3:
i= -1
return ""@websocket.on("close")
async def close():
return "Goodbye world, from ws"@websocket.on("connect")
async def message():
return "Hello world, from ws"

Performance comparison across different frameworks

I am pasting the following comparison that is done by the author of Robyn web framework on his development machine.

I used oha to perform the testing of 10000 requests on the following frameworks and the results were as follows

Flask(Gunicorn)

Total:        5.5254 secs 
Slowest: 0.0784 secs
Fastest: 0.0028 secs
Average: 0.0275 secs
Requests/sec: 1809.8082

FastAPI(Uvicorn)

Total:        4.1314 secs 
Slowest: 0.0733 secs
Fastest: 0.0027 secs
Average: 0.0206 secs
Requests/sec: 2420.4851

Django(Gunicorn)

Total:        13.5070 secs 
Slowest: 0.3635 secs
Fastest: 0.0249 secs
Average: 0.0674 secs
Requests/sec: 740.3558

Robyn(Doesn’t need a *SGI)

Total:    1.8324 secs 
Slowest: 0.0269 secs
Fastest: 0.0024 secs
Average: 0.0091 secs
Requests/sec: 5457.2339

Robyn (5 workers)

Total:    1.5592 secs 
Slowest: 0.0211 secs
Fastest: 0.0017 secs
Average: 0.0078 secs
Requests/sec: 6413.6480

Robyn web framework is able to serve the 10k requests in 1.8 seconds followed by Flask and FastAPI, which take around 5 seconds(using 5 workers on a dual-core machine). Finally, Django takes around 13.5070 seconds.

Conclusion

If you liked this story. Then you can buy me a coffee using this link. That will motivate me to write more blogs like this. Peace out.

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.