FastAPI, Django, Flask, Litestar and Starlette compared for teams building Python backends that have to run in production, plus how Encore adds the infrastructure none of them provide.
Most new Python APIs now start on FastAPI, while Django still runs a large share of the data-heavy apps that need an admin and an ORM, and Flask remains the small core people reach for when they want to choose every library themselves. The framework decides how requests are routed and validated, but none of these frameworks provision anything, so once the app needs a Postgres database, a queue and a bucket the team ends up maintaining Docker Compose for local development and Terraform for production next to the application code.
What to weigh when choosing:
Encore combines the Python web framework you already use with infrastructure declared in the same code, as an SDK you install into the existing app, so routing, validation and request handling stay in the framework while Postgres databases, Pub/Sub topics, object storage buckets, Redis, cron jobs and secrets are module-level declarations that Encore finds and provisions. It works with any Python framework, encore run starts the databases, topics and buckets locally next to the app, and a deploy provisions the same declarations in your own AWS or GCP account.
The SDK is the same whichever framework you choose, so the comparison below still decides how your requests are handled. For code that attaches it to FastAPI, Django and Flask, see FastAPI vs Django vs Flask, and for a full deploy and a multi-service layout, see deploying FastAPI to AWS and Python microservices. An AI coding agent working in any of these codebases can declare a topic or bucket in the change that needs it and try it locally right away.
Python support is in beta, and you can sign up for access.
FastAPI builds on Starlette and Pydantic, and function signatures declare the path, query and body parameters that FastAPI validates and turns into an OpenAPI schema.
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Signup(BaseModel):
email: str
@app.post("/users", status_code=201)
async def create_user(req: Signup) -> dict:
return {"email": req.email}
Depends handles dependency injection for auth, database sessions and shared logic.FastAPI is an API framework rather than an application framework, so the ORM, migrations tool, auth, background jobs and project layout are your choice, and larger codebases need conventions that the framework does not enforce. BackgroundTasks runs in the same process as the request, which means long-running work that must survive a restart belongs in a queue.
Django ships an ORM, migrations, an admin interface, authentication, forms and templating, and most API work adds Django REST framework or django-ninja on top.
# models.py
from django.db import models
class User(models.Model):
email = models.EmailField(unique=True)
created_at = models.DateTimeField(auto_now_add=True)
Django is the fastest path when the app is mostly CRUD over a relational schema and someone needs an admin. Async views and parts of the async ORM exist, although much of the ecosystem is still sync-first, and the conventions that help large teams get in the way when you only need a few JSON endpoints.
Flask gives you routing, request and response objects and templating, and everything else comes from extensions.
from flask import Flask, request
app = Flask(__name__)
@app.post("/users")
def create_user():
data = request.get_json()
return {"email": data["email"]}, 201
Flask fits small services, internal tools and teams that want to pick every library, but it is WSGI and synchronous by default with no built-in validation, and the structure of the project is up to you, which is why most new async JSON APIs start on FastAPI instead.
Litestar is an ASGI framework with typed route handlers, dependency injection and generated OpenAPI docs, and it includes more than FastAPI out of the box, such as a SQLAlchemy plugin and DTOs for shaping data.
from litestar import Litestar, post
from msgspec import Struct
class Signup(Struct):
email: str
@post("/users")
async def create_user(data: Signup) -> dict:
return {"email": data.email}
app = Litestar(route_handlers=[create_user])
Litestar suits teams that like the FastAPI style and want more structure built in, although its community and third-party ecosystem are smaller, so there are fewer tutorials, integrations and published examples than for FastAPI.
StarletteStarlette is the ASGI toolkit that FastAPI is built on, with routing, middleware, WebSockets and background tasks but no validation layer.
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route
async def health(request):
return JSONResponse({"ok": True})
app = Starlette(routes=[Route("/health", health)])
Starlette works well for small services, proxies and custom framework layers, and anything that takes request bodies ends up with validation code that FastAPI would have provided.
Whichever framework you pick, the Postgres database, queue, bucket and cron schedule still have to exist locally, in preview environments and in production. Python support in Encore is in beta, and you can sign up for access if you want to declare that infrastructure in the framework app you already have.
For new JSON APIs, FastAPI is the common default. Django fits apps that want an ORM, admin and auth out of the box, and Flask fits small services where the team wants to pick every library. Litestar suits typed async APIs that want more built in than FastAPI, and Starlette is a minimal ASGI toolkit. Encore is not a framework but an infrastructure SDK you add to whichever framework you pick, such as FastAPI or Django, and it provisions the databases, Pub/Sub topics and buckets the app declares in Python.
Use Django when you want a full application framework with an ORM, migrations, admin and auth included. Use FastAPI when you are building an API, want async handlers with type-hint-driven validation, and are fine choosing your own ORM and auth.
Yes, for small services and internal tools. Flask is synchronous by default and leaves structure, validation and data access to extensions you choose, so larger async APIs usually start on FastAPI instead.
Yes. Encore is an infrastructure SDK you add to the app you already have, with the encore-dev package and an encore.service.json file, so routing, validation and request handling stay in FastAPI, Django or any other framework, while Postgres databases, Pub/Sub, object storage, Redis, cron jobs and secrets are declared in Python. encore run starts the databases, topics and buckets locally, cron jobs run only where the app is deployed, and a deploy provisions everything in your own AWS or GCP account. Python support is in beta.
Install the encore-dev package in the app you already have, await encore.start() in the FastAPI lifespan handler, and declare postgres.Database, pubsub.Topic and pubsub.Subscription as module-level variables. encore run starts them locally and a deploy provisions them in your own AWS or GCP account, and the same SDK works with whichever framework you pick, such as Django.
Deploy to your cloud on AWS and Google Cloud
without managing infrastructure
Encore lets developers and agents define application infrastructure directly in code, then automatically provisions it from local development to production in your AWS or GCP account.