You Should Start Using FastAPI Now

Python has always been a popular choice for developing lightweight web apps, thanks to the awesome frameworks like Flask, Django, Falcon and many others. Due to Python’s position as the number one language for machine learning, it is particularly convenient for packaging models and exposing them as a service.

For many years, Flask was the number one tool for the job, but in case you haven’t heard, there is a new challenger in town. FastAPI is a relatively new web framework for Python, taking inspiration from its predecessors, perfecting them and fixing many of their flaws. Built on top of Starlette, it brings a ton of awesome features to the table.

It has gained significant traction recently, and after spending the last 8 months working with it every day, I can confidently say that the hype is justified. If you haven’t tried it yet, I would like to give you five reasons to give it a shot.

Simple, yet brilliant interface

All web frameworks need to balance between functionality and giving freedom for the developer. Django is powerful yet very opinionated. On the other hand, Flask is low level enough to provide a large degree of freedom, but a lot is left for the user to do. FastAPI is more on the Flask side of the spectrum, but it manages to strike a healthier balance.

To give you an example, let’s see how an endpoint is defined in FastAPI.

from fastapi import FastAPI
from pydantic import BaseModel
class User(BaseModel):
email: str
password: str
app = FastAPI()
@app.post("/login")
def login(user: User):
# …
# do some magic
# …
return {"msg": "login successful"}
view raw main.py hosted with ❤ by GitHub

For defining the schema, it uses Pydantic, which is another awesome Python library, used for data validation. This is simple to do here, yet so much is happening in the background. The responsibility to validate the input is delegated to FastAPI. If the request is not right, for instance the email field contains an int, an appropriate error code will be returned, instead of the app breaking down with the dreaded Internal Server Error (500). And it is practically free.

This simple example app can be served with uvicorn:

uvicorn main:app

Now the app is ready to accept requests. In this case, a request would look like

curl -X POST "http://localhost:8000/login" -H  "accept: application/json" -H  "Content-Type: application/json" -d "{\"email\":\"string\",\"password\":\"string\"}"

The icing on the cake is that it automatically generates the documentation according to the OpenAPI using the interactive Swagger UI.

Swagger UI for the FastAPI app

Async

One of the biggest disadvantage of Python WSGI web frameworks compared to the ones in Node.js or Go was the inability to handle requests asynchronously. Since the introduction of ASGI, this is no longer an issue, and FastAPI is taking full advantage of this. All you have to do is simply declare the endpoints with the async keyword like this:

@app.post("/")
async def endpoint():
# …
# call async functions here with `await`
# …
return {"msg": "FastAPI is awesome!"}
view raw async.py hosted with ❤ by GitHub

Dependency injections

FastAPI has a really cool way to manage dependencies. Although it is not forced on the developer, it is strongly encouraged to use the built-in injection system to handle dependencies in your endpoints.

To give an example, let’s write an endpoint, where users can post comments to certain articles.

from fastapi import FastAPI, Depends
from pydantic import BaseModel
class Comment(BaseModel):
username: str
content: str
app = FastAPI()
database = {
"articles": {
1: {
"title": "Top 3 Reasons to Start Using FastAPI Now",
"comments": []
}
}
}
def get_database():
return database
@app.post("/articles/{article_id}/comments")
def post_comment(article_id: int, comment: Comment, database = Depends(get_database)):
database["articles"][article_id]["comments"].append(comment)
return {"msg": "comment posted!"}
view raw dependencies.py hosted with ❤ by GitHub

FastAPI automatically evaluates the get_database function at runtime when the endpoint is called, so you can use the return value as you wish. There are (at least) two good reasons for this.

  1. You can override the dependencies globally by modifying the app.dependency_overrides dictionary. This can make testing a breeze, since you can mock objects easily.
  2. The dependency (which is the get_database in our case) can perform more sophisticated checks, allowing you to separate them from business logic. This greatly simplifies things. For instance, user authentication can be easily implemented with this.

Easy integration with databases

SQL, MongoDB, Redis, or whatever you choose, FastAPI doesn’t force your hand to build your application around it. If you have ever tried to work with MongoDB using Django, you know how painful it can be. With FastAPI, you don’t need to go the extra mile, adding a database to your stack is as simple as possible. (Or to be more precise, the amount of work to be done will be determined by the database you choose, not by the complications added by the web framework.)

But really, look at this beauty.

from fastapi import FastAPI, Depends
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
engine = create_engine("sqlite:///./database.db")
Session = sessionmaker(bind=engine)
def get_db():
return Session()
app = FastAPI()
@app.get("/")
def an_endpoint_using_sql(db = Depends(get_db)):
# …
# do some SQLAlchemy
# …
return {"msg": "an exceptionally successful operation!"}

Voila! I can see you typing

pip install fastapi

into your terminal already.

GraphQL support

When you are working with a complex data model, REST can be a serious hindrance. It is definitely not fun when a tiny change in the frontend requires to update the schema for an endpoint. GraphQL shines in these situations. Although GraphQL support is not unique among Python web frameworks, Graphene and FastAPI work together seamlessly. No need to install any extensions like graphene_django for Django, it just works natively.

+1: Great documentation

Of course, a great framework cannot truly shine without an equally great documentation. Django, Flask and all the others excel in this aspect, but FastAPI is on par with them. Of course, since it is much younger, there are no books written about it yet, but it is just a matter of time.


If you would like to see FastAPI in action, I have just the perfect guide for you! I have written a detailed tutorial, where you can learn to deploy your machine learning model using Docker, Docker Compose and GitHub Actions!

To summarize, whether you are looking for a fast and lightweight framework to serve your deep learning models or something more complex, FastAPI delivers. If you haven’t tried it yet, I strongly encourage you to do so. I am pretty sure you’ll stick with it.

Share on facebook
Share on twitter
Share on linkedin

Related posts