Oct 23, 20268 min read

Best Python Framework for Microservices in 2026

FastAPI, Litestar, Nameko and Django compared for Python services that call each other and share events, plus how Encore adds the databases, topics and cloud resources underneath whichever one you choose.

Python teams building microservices rarely pick a framework designed for them, since the popular choices are general web frameworks and the service boundaries come from how the team splits the code. FastAPI has become the default for new services, and the JetBrains Python Developers Survey 2024 shows its usage among respondents rising from 21 percent in 2021 to 38 percent in 2024, ahead of Django at 35 percent and Flask at 34 percent.

The framework decides how one service handles requests and leaves open how services find each other, how events move between them, and where each service's database comes from.

What to weigh when choosing:

  • Whether the framework is async, since services spend much of their time waiting on other services.
  • How request and response types are declared, which decides how reliable the contract between services is.
  • Whether the framework has any notion of inter-service communication, or leaves RPC and messaging to you.
  • How each service gets its own database, broker and secrets locally and in production.

Python microservice frameworks at a glance

OptionApproachBest fit
FastAPIAsync framework with Pydantic models and OpenAPI generationMost new HTTP services
LitestarAsync framework with dependency injection, DTOs and plugins built inTeams that want more structure than FastAPI
NamekoService framework built around RPC and events over AMQPTeams that want RPC between services as the main primitive
DjangoFull-stack framework with ORM, admin and migrationsData-heavy services that benefit from an admin
Compare features across all four options
CapabilityFastAPILitestarNamekoDjango
RoleWeb frameworkWeb frameworkService frameworkFull-stack framework
AsyncYesYesEventlet basedPartial (async views)
Service discoveryYou configure URLsYou configure URLsThrough the AMQP brokerYou configure URLs
Events between servicesBring your own brokerBring your own brokerBuilt in over RabbitMQBring your own broker
Database per serviceBring your ownBring your ownBring your ownBuilt-in ORM
Local infrastructureYou run itYou run itYou run RabbitMQYou run it
Production infrastructureYou provision itYou provision itYou provision itYou provision it

FastAPI: the default for new services

FastAPI

FastAPI builds on Starlette and Pydantic, so a service's request and response models are Python classes and the OpenAPI schema other teams consume is generated from them.

from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() class Order(BaseModel): user_id: int @app.post("/orders", status_code=201) async def place_order(order: Order) -> dict: return {"user_id": order.user_id}

Key features

  • Async handlers with dependency injection through Depends.
  • OpenAPI and JSON Schema generated from type hints, which other services can use to generate clients.
  • A large ecosystem of extensions and a lot of examples in the wild.

Good to know

FastAPI is a single-service framework, so service URLs, the broker and each database are configured by the team, usually through environment variables per environment.

Try FastAPI →

Litestar: more included

Litestar

Litestar has a similar async, type-driven model with more in the box, including layered dependency injection, DTOs for shaping responses, and plugins for SQLAlchemy and Pydantic.

Key features

  • Controllers group routes with shared dependencies and guards.
  • DTOs separate the internal model from what each endpoint exposes.
  • Built-in support for channels, caching and OpenAPI.

Good to know

Litestar has a smaller community than FastAPI, so there are fewer third-party examples, and like FastAPI it leaves inter-service communication to you.

Try Litestar →

Nameko: RPC and events first

Nameko

Nameko is one of the few Python frameworks built specifically for microservices, with RPC calls and event dispatch between services carried over RabbitMQ.

from nameko.events import EventDispatcher from nameko.rpc import rpc class OrdersService: name = "orders" dispatch = EventDispatcher() @rpc def place_order(self, user_id): self.dispatch("order_placed", {"user_id": user_id}) return {"user_id": user_id}

Key features

  • @rpc methods are callable from other Nameko services by name.
  • Events and handlers are part of the framework.
  • Dependency providers inject resources such as database sessions.

Good to know

Nameko depends on eventlet and RabbitMQ, its 3.0 line has been in release candidates since 2018, with the latest, 3.0.0rc11, published to PyPI in December 2021, and it predates the asyncio ecosystem most Python libraries target now, so check how well its dependencies fit your stack before adopting it.

Try Nameko →

Django: when the service owns a rich data model

Django

Django brings an ORM, migrations and an admin, which suits a service that owns a complex model and needs internal tooling around it.

Key features

  • ORM and migrations included.
  • An admin interface generated from the models.
  • Django REST Framework or Django Ninja for APIs.

Good to know

Each Django service carries a full project layout and settings module, which is more overhead per service than FastAPI, and async support covers views but not every part of the ORM.

Try Django →

Encore: the infrastructure SDK you add to your framework

Encore

Encore combines each Python service with its own infrastructure through an infrastructure SDK that you install into the service, so FastAPI or Django keeps handling requests while each service declares its own Postgres database, Pub/Sub topics, buckets, cron jobs and secrets as module-level objects. Encore reads those declarations and the calls between services from the code, encore run starts Postgres locally with the topics and buckets next to the services, and a deploy provisions the same resources in your own AWS or GCP account. Whichever option above you pick, Encore can add the databases, topics and buckets to the same services.

An orders service built on FastAPI declares its database and topic in one module:

# orders/resources.py from encore import pubsub from encore.storage import postgres from pydantic import BaseModel db = postgres.Database("orders", migrations="./migrations") class OrderPlaced(BaseModel): order_id: int user_id: int order_placed = pubsub.Topic[OrderPlaced]("order-placed")

The endpoint calls the users service through the URL Encore resolves for it, writes the order and publishes the event:

# orders/main.py from contextlib import asynccontextmanager import encore import httpx from encore.services import base_url from fastapi import FastAPI from resources import OrderPlaced, db, order_placed @asynccontextmanager async def lifespan(app: FastAPI): await encore.start() yield app = FastAPI(lifespan=lifespan) @app.post("/orders", status_code=201) async def place_order(user_id: int) -> dict: async with httpx.AsyncClient() as client: resp = await client.get(f"{base_url('users')}/users/{user_id}") resp.raise_for_status() row = await db.query( "INSERT INTO orders (user_id) VALUES ($1) RETURNING id", user_id ).one() await order_placed.publish(OrderPlaced(order_id=row["id"], user_id=user_id)) return {"order_id": row["id"]}
FastAPI handles the route, while the database, topic and the address of the users service come from Encore.

A notifications service subscribes to the topic by name, without importing the orders code:

# notifications/resources.py from encore import pubsub from pydantic import BaseModel class OrderPlaced(BaseModel): order_id: int user_id: int order_placed = pubsub.Topic[OrderPlaced].named("order-placed") async def send_receipt(message: pubsub.Message) -> None: print("Sending receipt for order", message.data.order_id) receipts = pubsub.Subscription[OrderPlaced]( order_placed, "send-receipt", handler=send_receipt, max_retries=3 )

Key features

  • Each service declares its own database, so the boundary between services is also a boundary between schemas.
  • Calls through base_url are read from the code, which gives Encore a map of which service depends on which.
  • Subscriptions take retry, backoff and concurrency settings in the declaration.
  • A deploy provisions the declarations in your own AWS or GCP account, such as RDS and SNS/SQS on AWS.
  • An AI coding agent that splits out a new service adds a FastAPI app and a resources module, and can run the whole system locally before anyone reviews it.

Good to know

Encore leaves request handling to your framework, so the comparison below still decides how each service is written. When Encore deploys to your cloud, the cloud access sits with Encore's IAM role, not the developer or the agent writing the service. Python support is in beta, and you can sign up for access.

Try Encore →

How to choose

Each service's contract is easier to share when it is published as an OpenAPI document, which FastAPI and Litestar generate from the code, and the database per service pattern keeps each service's data private to it. Pick the framework for how you want each service written, and plan the infrastructure separately.

  • FastAPI for most new HTTP services.
  • Litestar when you want dependency injection and DTOs built in.
  • Nameko when RPC over a broker is the communication model you want.
  • Django for a service that owns a large data model and needs an admin.

Every service also needs its own environment for testing changes, and Encore's preview environments give each pull request one with real infrastructure on paid plans. Python support in Encore is in beta, and you can sign up for access.

Frequently asked questions

What is the best Python framework for microservices?

FastAPI is the most common choice for new Python services because it is async, small and generates OpenAPI schemas from type hints. Litestar offers a similar model with more built in, Nameko is built around RPC and events between services, and Django suits services that need an ORM and admin. Encore is not a competing framework but an infrastructure SDK you add to the framework you pick, giving each service its own Postgres database and Pub/Sub topics.

Is Django a good choice for microservices?

Django works for services with a rich data model and an admin, but its project structure and synchronous history make it heavier per service than FastAPI or Litestar. Many teams run Django as one larger service next to smaller FastAPI services.

How do I call one Python microservice from another with Encore?

Look up the other service with encore.services.base_url, passing the service name as a string literal, and send an HTTP request to the returned URL with httpx. Encore reads the call from the code, records the dependency between the two services, and resolves the URL locally under encore run and in each deployed environment.

Should I start with microservices in Python?

Usually not. Most teams start with one service and split when a part of the system needs to scale or deploy on its own. Keeping each module behind its own database and API from the start makes that split cheaper later.

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.

~/orders — claude
Claude Code
Claude Code v2.1.180Opus 5.5~/orders