Let's talk about FastAPI

When it comes to writing Web APIs in Python, there have always been a significant number of choices, and some of the most popular ones being Django Rest Framwork (DRF) and Flask. Both these tools are powerful in their own way and I have been using both frequently over the past few years. I had been so comfortable that I never really looked for another alternative after a while. Recently though, I have been convinced that it’s time for a change. The reason: FastAPI.

FastAPI been around for about 2 years now. I had heard about it before - this new framework that makes API dev so easy! - but never got around to trying it out. Over the last two months, however, I had been using FastAPI significantly - both at work and at home - and I have to say, it’s been amazing!

The Code

When you start writing code using FastAPI (or even just look at some examples) you immediately notice the simplicity of it all - the simplicity often associated with Flask. It’s Pure Python. A quick hello world app would look this:

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def hello():
    return "hello, world!"

And most of your code will look like this. Compare this to DRF: where you had to have atleast three different imports to get the same result.

But this is just the tip of the iceberg. Where FastAPI really excels is it’s use of Data Models and Autogenerated docs.

Data Models and Validation

Remember all the input validations and error responses that we are required to write before executing the API logic? FastAPI has an elegant and automated solution to this whole thing. Two things enable this: Static Typing in Python 3.6+ and the Pydantic library. Let’s look at the code first:

from fastapi import FastAPI
from pydantic import BaseModel

class User(BaseModel):
    name: str
    age: int
app = FastAPI()

@app.post("/")
def hello(user: User):
    return "hello " + user.name+"!, Your age: "+user.age

The code is self-explanatory. What is interesting is what happens when you execute this post request with an input like this: {"name": "John", "age":"25"} or this: {"name": "Jane", "age":25.0}. You get an automatic and detailed 422: Unprocessable Entry error response that tells you which entry is wrong and where it occurs. All without a single line of Validation code!

Validation is not just restricted to requests but also for responses. It has a similar structure. You define a response model and let FastAPI handle formatting, conversion and validation for you. In case the API response doesn’t match with the response, you get a 500: Internal Server Error. Modifying the aboe example, so that it now returns only a “Unique ID” for the user:

class APIResponse(BaseModel):
    UID: str

@app.post("/", response_model: APIResponse)
def hello(user: User):
    uid = user.age+1
    return {"UID": uid}

This is a major advantage. But this way of writing code, offers another advantage - OpenAPI Compliance and automatic interactive docs.

The API documentation

Automatic Interactive Docs are nothing new. DRF had it in the form of Browseable APIs. This is FastAPI’s inspiration too. But what makes it different is that our whole API suite is OpenAPI compliant, by design! This is the biggest advantage offered by the framework.

OpenAPI

For people who are not familiar, OpenAPI(previously known as Swagger) is a set of standards that list out how to document your APIs so as to ensure interoperability and integration with other tools or frameworks. A standard specification format will also help in autogeneration of custom documentation, tests and even API code from the document. The main drawback is that this format is quite long and it is always easier to write code first and generate the spec later. FastAPI also does this!

The API Spec and Interactive docs

When you follow the coding standard (Just Modern Python!), this OpenAPI spec is autogenerated for you! Now using this spec - in the form of a json file - documentation can be generated using any of the available tools. FastAPI provides two documentation formats out of the box - Swagger UI and Redoc Documentation.

Postman Integration

Postman recognizes OpenAPI spec too! That’s a huge effort automated right there. You simply import the specification and Postman autogenerates all the queries for you! Postman is my go-to tool to test APIs and this played a major role in convincing me to move to FastAPI. What this also means is that you have to put most of your effort in one place - writing good server code - and that is something you have to do anyway! Everything else gets automated, for the most part.

The FastAPI documentation

Now, this is important. FastAPI has really good documentation and I mean it. I believe that documentation is an important factor in the success or failure of any tool or framework and FastAPI excels here too. Everytime I was stuck, the documentation had the answer. And if in the off-chance that it is not there in the docs, you could probably find the answer in the Issues discussion. I did!

Side note: The documentation is powered by Material for Mkdocs and that is another reason I love it. At one point, I had thought of having this blog styled using that too. But it has one specific purpose - to provide beautiful documentation - and does it well.

It’s toolbox

FastAPI also comes with a lot of libraries that simplify the development. Most of it is powered by its Dependency Injection mechanism. It has all the usual suspects like the status ENUMs, various response types (FileResponse, JSONResponse, StreamingResponse etc) and some very useful Security functions. The FastAPI documentation has great examples for each of these and I suggest you start there. FastAPI doesn’t come with it’s own ORM and leaves it upto the developer. This was not a problem for me as I use SQLAlchemy anyway and this became an added benefit!

Deployment

At some point you have got to deploy the API server and FastAPI has got you covered here too. FastAPI requires an ASGI server and recommends Uvicorn. A production deployment is usually a Gunicorn+Uvicorn combo and FastAPI provides a preconfigured Docker image with this setup! Now ofcourse, you don’t have to go with this and deploy it however you like, but I thought that it was nice, that this was also taken care.

An Amazing Tool, So far!

FastAPI had provided everything I needed, in an almost intuitive setup. While DRF was great, it required the Django core and served as an extension on top of the powerful web framework. From a pure Microservice standpoint, this was a lot of extra baggage. I will still continue to use Django though. Flask on the other hand, gives complete flexibilty to decide what’s needed. This was nice until I started using FastAPI. FastAPI has the best of both worlds. It provides a lot of nice tools but also keeps itself free to be extensible however desired. And this was not an accident. As the creator himself writes FastAPI has been inspired by all of these and tried to build something new from all the learnings.

From personal experience, FastAPI very recently helped me to completely develop and deploy a test integration server with useable documentation in a span of two weeks. That is the power this tool offers us. This is something that would have definitely taken more time in the other frameworks. This experience is what convinced me to seriously consider this shift.

I haven’t covered all of it’s features here. There is a lot more to FastAPI including async APIs (a major feature that I didn’t cover here) and websocket support. Do check it out and you will probably be as convinced as I was!


Subscribe to the Blog!

Want to get notified about the latest updates?

Subscribe Via RSS  rss Subscribe Via Email