During my relevant searches, I've noticed that even in 2024, quite a number of people still recommend Flask as a Python web framework. However, in my view, "Flask is on the way out, and FastAPI represents the future." That's why I'm penning this article. I welcome everyone to join the discussion and offer counterarguments.
Flask vs FastAPI
Flask holds a significant place in the hearts of Python developers. If you're a web developer, I bet you've most likely used Flask, but perhaps you've never dabbled in FastAPI.
Here are two pieces of evidence:
- In the prominent new Python projects related to web development over the past one or two years, nearly all of them that involve web development have adopted FastAPI.
- As of December 25, 2024, on GitHub, the number of stars for FastAPI (78.9k) has already surpassed that of Flask (68.4k).
Let's now take a look at the changes in the proportion of web frameworks in the official Python developer surveys.
It's evident that in 2019, FastAPI wasn't even listed as an option, yet by 2023, its share had reached 25%. (Currently, we only have data up to 2023.)
It should be noted that this proportion data encompasses existing systems, so the proportions of Django and Flask won't drop rapidly. Nevertheless, the trend is clear.
We all know that the web framework field is highly prolific, with new frameworks emerging almost every year. Most of these frameworks are short-lived, while some manage to endure. FastAPI was born at the end of 2018 and started to make a name for itself around the end of 2019. So, how could it overtake Flask, which was born at the end of 2010, in terms of popularity within just five years? Next, let's trace the development history of Python web frameworks and related solutions along the timeline for a better understanding.
The Evolution of Web Frameworks (Plugins, Tools)
The author of FastAPI is a developer who pays extremely close attention to the development of the Python ecosystem. The extended reading link 2 is "Alternatives, Inspiration and Comparisons" written by the author (https://fastapi.tiangolo.com/alternatives/), which elaborates in detail on the references or inspirations that FastAPI has drawn from various libraries. The development history section of this article also refers to this piece. I'd recommend reading the original text, as it contains the rationale behind FastAPI's emergence as well as some of the author's design concepts.
Flask
Flask is a "micro" framework, which is worlds apart from Django. It only retains a handful of core functions and, to decouple, splits other functions into several libraries (such as Jinja2, Werkzeug, etc.). This gives developers ample freedom and enables them to effortlessly write third-party plugins for related functions. Its internal designs like blueprints, contexts, and decorators for representing routes, signals, etc. were quite advanced at the time. Coupled with comprehensive documentation, it's extremely newbie-friendly.
Flask REST Frameworks
Thanks to its simplicity, Flask is highly suitable for building APIs. However, since Flask itself doesn't come with any built-in functions, we need specialized REST frameworks. Consequently, frameworks such as flask-restful, Flask-RESTPlus, and flask-api have emerged one after another. Additionally, in REST services, there are requirements for data validation, parsing, and specification, which led to the emergence of Marshmallow, Webargs, and APISpec, until Flask-apispec came along. Throughout this development process, though, a Flask REST Framework comparable to DRF has never materialized.
At this stage, Flask's shortcomings have gradually come to the fore.
The original strengths of Flask lie in its flexibility and minimalism, but this also means that a large number of components need to be developed in-house. This either demands a large company with dedicated developers for development and upkeep or extremely capable individual developers. Otherwise, it's difficult for plugins to reach production quality, resulting in a mixed bag of third-party plugins for Flask, with no guarantee of long-term maintenance. As mentioned earlier, many of those libraries have already ceased to be maintained.
So, even today, if you want to build an API service with Flask, you still have to piece together various components. For some components that haven't been updated promptly, you'll have to troubleshoot on your own. Veterans might be able to handle it, but for beginners, it's rather daunting, especially when they want to apply the latest practices and concepts.
The Asyncio Ecosystem
Since Python 3.5, asyncio has been the future trend. As a result, some web frameworks that natively support asyncio have emerged, such as aiohttp, Starlette, and sanic.
At this time, Flask was reluctant to adapt. The community has been slow to add support for asyncio, and the original author of Flask has switched to writing Rust, leaving the project in the hands of two maintainers (now there's only one left).
Projects for building API services, like apistar and molten, have all provided design inspiration for the birth of FastAPI.
FastAPI
Then, FastAPI was born. The author was originally seeking a good solution, but the above situations each had their own problems or limitations. So, the author created this new framework.
Why FastAPI Stands Out
This is the core part of the article. The following reasons are precisely why FastAPI can replace Flask.
User Data Validation with Pydantic
In the process of API development, data format validation, parsing, and serialization are routine operations. Over the years, multiple solutions have emerged, and currently, Pydantic is the top choice:
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
return item
At first glance, this code might seem like the way of writing ORM or dataclass, but in fact, it uses Python's native Type Hints syntax to annotate field types. For example, in the above example, the schema of the Item
in the /items/
request has been clearly defined, and the value types of each field are explicit. Compared to the old methods of using schema descriptions or even hard coding, this approach is more concise, more in line with Python style, and has better IDE support.
Currently, Pydantic dominates the field of user data validation. Since FastAPI has it built-in, the validation process is greatly simplified, and errors are reduced. That's why the FastAPI official website mentions that this solution can cut down developers' errors by up to 40%. For a dynamic language like Python, applying Pydantic is essential if you don't use mypy for type checking.
Moreover, thanks to the integration of Pydantic, adding an ORM (such as SQLAlchemy) to the project becomes extremely easy. Objects obtained from requests can be directly passed to the database because data validation has already been completed. Vice versa, objects retrieved from the database can also be directly returned.
In contrast, Flask is lacking in this regard.
Asynchronous Design
In the era of Flask, code execution was single-threaded and synchronous. This meant that requests had to be processed one by one, and other requests would waste time waiting for I/O operations before the previous one was completed. Asyncio, on the other hand, is the optimal solution. It can make I/O operations asynchronous, allowing you to obtain task results without waiting for the tasks to finish, and then proceed to handle other task requests.
FastAPI natively supports concurrent and asynchronous code. As long as the code is written correctly, it can achieve peak efficiency. Hence, it's regarded as the fastest Python framework currently, with an efficiency similar to that of NodeJS or Go. When speed and performance are of the essence, FastAPI is undoubtedly the best choice.
Native Support for ASGI
Let's first mention WSGI. Its full name is "Python Web Server Gateway Interface", which can be referred to in "PEP 3333" (https://peps.python.org/pep-3333/). It's a Python standard written specifically for the interaction between web applications and servers. If you've used PHP or Ruby, you might find it easier to understand. Flask depends on Werkzeug, which is a WSGI suite, so Flask supports this old WSGI standard and not ASGI.
The problem with WSGI is that it can't leverage asynchrony to boost performance and efficiency. So, Django channel pioneered ASGI. Its full name is "Asynchronous Server Gateway Interface", which is an iterative and almost completely redesigned standard. It provides asynchronous server/application interfaces and supports HTTP, HTTP/2, and WebSocket. Unlike WSGI, ASGI allows each application to have multiple asynchronous events. Additionally, ASGI supports both synchronous and asynchronous applications. You can either migrate old synchronous WSGI web applications to ASGI or use ASGI to build new asynchronous web applications.
Before drawing conclusions, let's add five term explanations:
- ASGI Toolkit: Libraries that implement ASGI-related functions (such as URL routing, Request/Response objects, template engines, etc.). In this article, it mainly refers to Starlette, which corresponds to Flask's dependency, Werkzeug.
- ASGI Web Framework: Web frameworks that implement the ASGI specification (such as FastAPI), while Flask and Django are web frameworks that implement WSGI. These frameworks are designed for developers to write applications, with easy-to-use interfaces. Developers only need to fill in the business logic according to their needs. Early frameworks mostly implemented ASGI toolkits internally, while later frameworks usually combine suitable toolkits. For example, Flask uses Werkzeug (its own), and FastAPI uses Starlette (from others).
- Web Application: An application created using a web framework is a web application. Usually, web frameworks come with a test server that can be started for development and debugging. If performance and stability are not a concern, you can already access the development address in the browser to visit this application.
- Web Server: The real world is more complex than expected. After a web application is deployed to the production environment, requirements such as request load balancing, serving static files, access control, and reverse proxy need to be considered, and there are also high performance requirements. The built-in web servers of web frameworks can't meet these requirements at all, so specialized web servers are needed. Currently, Nginx is the mainstream choice.
- ASGI Server: The ASGI server acts as a bridge between the web server and the web application. The ASGI server also adheres to the ASGI specification, but its main task is to meet the performance requirements of forwarding requests, so it mainly takes care of the "G" (gateway) part of ASGI. Its code is not friendly for developers to write web application business and routing logic. Currently, the most well-known ASGI server is Uvicorn, and the uvicorn.workers.UvicornWorker, which originally comes from the WSGI server Gunicorn, is also an option. These are the recommended usage in the production environment.
In the past, the production environment solution for WSGI was usually Nginx + Gunicorn + Flask(Django), while nowadays, the production environment solution for ASGI is Nginx + Uvicorn + FastAPI.
One more thing. Judging from the name and introduction of FastAPI, it's obvious that it's designed for building API services. In fact, its core code is exactly like that. It can be said that it's not a traditional, fully self-implemented framework but more of a framework that combines the strengths of various frameworks. Starting from an empty shell, it assembles the necessary and suitable components. For example, it doesn't have a template engine. If you really need to use it to build a web application that requires template rendering, you can choose and combine the template engine you need. Of course, you can also use the Jinja2 built into Starlette (yes, it's also built into Flask).
Why It's Said That Flask Is Dead
The advantages of FastAPI mentioned above aren't enough to conclude that Flask is dead. So, why do I hold this view? It mainly comes down to the popularity among developers and users.
The "popularity" here is rather subjective. The indicators I can think of are as follows:
- Community Activity(https://github.com/pallets/flask/issues): Take the number of issues and pull requests of the project, for example. Flask only has single-digit numbers, which is completely in a different league compared to FastAPI. This actually reflects from the side that the project is no longer active. If the project is active, old users will have more needs. If they stop raising questions, it means they've left. And new users will surely have all kinds of problems. Even with detailed documentation, there should still be many users coming to ask questions and contribute code. The lack of such situations indicates fewer users.
- Discussion Heat: That is, the popularity of inquiries and discussions on blog posts, Stack Overflow, and other websites. It's quite obvious that there are very few people writing about Flask these days.
- Development Iteration Frequency(https://github.com/pallets/flask/pulls): Looking at the commit records, we can see that Flask only has one maintainer who occasionally fixes some bugs, without any major feature development.
- Influence of the Key Figure: The key figure behind Flask, the project initiator, has long stopped participating in the project. According to the project contribution records, Armin Ronacher last contributed to the development six years ago.
All these situations, in my opinion, suggest that Flask's heyday has passed, and FastAPI is the rising star.
Finally, let me introduce the ideal platform for deploying Flask/FastAPI: Leapcell.
Leapcell is a cloud computing platform designed specifically for modern distributed applications. Its pay-as-you-go pricing model ensures no idle costs, meaning users only pay for the resources they actually use.
The unique advantages of Leapcell for WSGI/ASGI applications:
1. Multi-Language Support
- Supports development in JavaScript, Python, Go, or Rust.
2. Free Deployment of Unlimited Projects
- Only charge based on usage. No charge when there are no requests.
3. Unmatched Cost-Effectiveness
- Pay-as-you-go, with no idle fees.
- For example, $25 can support 6.94 million requests, with an average response time of 60 milliseconds.
4. Simplified Developer Experience
- Intuitive user interface for easy setup.
- Fully automated CI/CD pipelines and GitOps integration.
- Real-time metrics and logs, providing actionable insights.
5. Effortless Scalability and High Performance
- Automatic scaling to handle high concurrency with ease.
- Zero operation overhead, allowing developers to focus on development.
Learn more in the documentation!
Leapcell Twitter: https://x.com/LeapcellHQ
Top comments (0)