cheat sheet
litestar
Package-level reference for Litestar on PyPI — install variants, version policy, the `[full]` extra, ecosystem companions, and alternatives.
litestar
What it is
litestar is an ASGI web framework (formerly named Starlite) maintained by the Litestar Organization, a community-led group that forked the project in 2023 to ensure broad-based governance. It pairs strict typing with native Pydantic v2, msgspec, and attrs support, and offers a richer DI container, plugin system, and OpenAPI generator than FastAPI — usually with lower per-route overhead.
Reach for Litestar when you want FastAPI-style ergonomics with stricter typing, a real plugin lifecycle, and significantly higher throughput on hot paths. Reach for FastAPI when the surrounding tutorials/SDKs assume it, or when you specifically want Pydantic-driven routes without msgspec.
Install
pip install litestar
Output: (none — exits 0 on success)
uv add litestar
Output: dependency resolved + added to pyproject.toml
poetry add litestar
Output: updated lockfile + virtualenv install
pip install "litestar[standard]" # framework + uvicorn + jinja + structlog
pip install "litestar[full]" # framework + every optional integration
pip install "litestar[sqlalchemy]" # database plugin
pip install "litestar[redis]" # redis store + caching
pip install "litestar[jwt]" # jwt auth plugin
Output: Litestar plus the named bundle of optional integrations
Versioning & Python support
- Current line is the
2.xseries (as of mid-2026). Litestar2.0shipped after the project renamed from Starlite in 2023; the1.xStarlite line is deprecated. - Supports Python 3.8+ on
2.xrecent releases; 3.9+ on the newest minor lines. - Semver-aligned — breaking changes require a major bump. The
1.x → 2.xmigration was significant; subsequent2.xminor releases have stayed compatible. - Pydantic v1 is supported but deprecated; new projects should use Pydantic v2 or
msgspec/attrsfor DTOs.
Package metadata
- Maintainer: The Litestar Organization
- Project home: github.com/litestar-org/litestar
- Docs: docs.litestar.dev
- PyPI: pypi.org/project/litestar
- License: MIT
- Governance: community-led non-profit organization (the rename from Starlite codified shared maintainership)
- First released: 2021 (as Starlite); renamed to Litestar in 2023
- Downloads: millions per month — growing share of the async-Python API space
Optional dependencies & extras
litestar[standard]— sensible default bundle:uvicorn,jinja2,structlog,picologging, plus thelitestarCLI.litestar[full]— every optional integration: standard plussqlalchemy,attrs,pydantic,msgspec,redis,jwt,cli,cryptography, and more.litestar[sqlalchemy]—advanced-alchemyplugin for SQLAlchemy 2.x integration.litestar[redis]—redis-pyfor the Redis store / pub-sub channels.litestar[jwt]—python-josefor JWT authentication helpers.litestar[cli]—click+richfor thelitestarCLI command.litestar[opentelemetry]— OTel instrumentation plugin.litestar[prometheus]— Prometheus metrics middleware.litestar[structlog]— structured logging plugin.
Common companion packages typically installed alongside:
uvicorn[standard]orgranian— ASGI server (Granian is a Rust-backed alternative with high throughput)msgspec— fastest path for DTOs / serializationpydantic— when you specifically want Pydantic v2 modelsadvanced-alchemy— opinionated SQLAlchemy 2.x repository layer (by the Litestar maintainers)httpx— forTestClientstructlog/picologging— structured logging backendspolyfactory— fixture / factory generation, also by the Litestar org
Alternatives
| Package | Trade-off |
|---|---|
fastapi | Larger ecosystem and tutorial coverage; less strict typing. Use for default async Python REST. |
starlette | The ASGI toolkit under FastAPI. Use for routing without validation/OpenAPI overhead. |
flask + extensions | Sync, WSGI, smaller surface. Use for non-async apps. |
django + DRF/ninja | Full-stack. Use when you need admin/ORM batteries. |
quart | Flask-API-compatible but async. Use when migrating Flask code to async. |
robyn / granian + raw ASGI | Rust-backed servers. Use when raw throughput dominates ecosystem maturity. |
Common gotchas
- Renamed from Starlite — the import path is
litestar, notstarlite. If you find tutorials referencingfrom starlite import ..., they're targeting the deprecated1.xline. Migrate tolitestar. - Pydantic v1 is deprecated in
2.x. It still works, but new code should use Pydantic v2,msgspec, orattrsfor DTOs. The DI container handles all three transparently. - DTOs are not Pydantic models. Litestar's DTO system is a separate abstraction over Pydantic /
msgspec/attrs. Mixing route-annotated models and DTOs can produce confusing OpenAPI output — pick one style per app. [full]is heavy. Pulls in ~15 optional deps including SQLAlchemy and Redis clients. Prefer[standard]plus only the extras you need.- The
litestarCLI requires[cli](or[standard]). Without it,litestar runandlitestar routesdon't exist on PATH. - OpenAPI rendering picks Scalar by default. Litestar serves Scalar, Swagger UI, Redoc, Rapidoc, and Elements all at once at different sub-paths. If a consumer expects
/docsto be Swagger UI, configureopenapi_config=OpenAPIConfig(..., path="/docs", render_plugins=[SwaggerRenderPlugin()]). - Plugin lifecycle vs middleware. Plugins integrate at app-build time (registering routes, DI providers, OpenAPI components); middleware runs per request. Putting cross-cutting setup in middleware that should be a plugin is a common modeling mistake.
Version migration guide
The major rename from Starlite to Litestar happened alongside the 1.x → 2.x API overhaul. Most apps need both a package change AND code-level adjustments. Subsequent 2.x minor releases have stayed compatible.
Starlite 1.x → Litestar 2.x:
# Replace the dependency
pip uninstall starlite
pip install litestar
Output: old package removed; litestar installed with current deps.
# Before — Starlite 1.x
from starlite import Starlite, get, post, MediaType
from starlite.dto import DTOFactory
from starlite.connection import Request
@get("/items/{item_id:int}", media_type=MediaType.JSON)
async def get_item(item_id: int) -> dict: ...
app = Starlite(route_handlers=[get_item])
# After — Litestar 2.x
from litestar import Litestar, get, post, MediaType
from litestar.dto import DataclassDTO # (or PydanticDTO, MsgspecDTO)
from litestar.connection import Request
@get("/items/{item_id:int}", media_type=MediaType.JSON)
async def get_item(item_id: int) -> dict: ...
app = Litestar(route_handlers=[get_item])
Output: module rename is mechanical; the DTO system is the part that requires real changes.
Other 2.x migration notes:
DTOFactory→DataclassDTO/PydanticDTO/MsgspecDTO(one base class per source format).before_request/after_requesthooks → middleware orbefore_requestparameter on the app.- Logging config moved into
LoggingConfig; pass viaLitestar(logging_config=...). - OpenAPI config moved into
OpenAPIConfigand gainedrender_plugins=[...]for picking the UI. from starlite.testing import TestClient→from litestar.testing import TestClient.- Channels API redesigned —
Channel/ChannelsPluginreplace the older websocket-event hooks.
For long-running Starlite apps, the migration is usually a 1-2 day effort plus a careful diff of the OpenAPI output.
Production deployment
Litestar is ASGI — production is the same shape as FastAPI: pick a server (uvicorn, granian, hypercorn) and run it behind a reverse proxy. granian is the differentiator — a Rust-backed ASGI server that often outperforms uvicorn on throughput-bound workloads.
# Recommended: granian (Rust runtime) for max throughput
pip install granian
granian --interface asgi myapp:app --host 0.0.0.0 --port 8000 --workers 4
Output: Rust-managed workers; typically 20-40% higher RPS than uvicorn on the same hardware.
# uvicorn — most familiar choice
pip install "uvicorn[standard]"
uvicorn myapp:app --host 0.0.0.0 --port 8000 --workers 4 --proxy-headers
Output: standard ASGI server; equivalent to FastAPI's deployment pattern.
# litestar CLI (requires litestar[standard] or [cli])
litestar --app myapp:app run --host 0.0.0.0 --port 8000 --reload # dev
Output: dev server with auto-reload; not for prod.
# Lifespan hooks — replaces FastAPI's @app.on_event
from contextlib import asynccontextmanager
from litestar import Litestar
@asynccontextmanager
async def lifespan(app: Litestar):
await db.connect()
yield
await db.disconnect()
app = Litestar(lifespan=[lifespan])
Output: on-startup and on-shutdown side effects wired in.
Granian configuration tip: pass --blocking-threads 1 --runtime-threads 1 for I/O-bound apps; raise both for CPU-mixed loads. Behind a load balancer, set --http2-keepalive-timeout and trust the LB to do TLS termination.
Real-world recipes
Concrete package-level patterns. The companion python/litestar.md covers handlers, DI, and DTOs; here we focus on plugin composition, msgspec hot paths, and structural choices unique to Litestar.
# Recipe 1 — msgspec DTOs for hottest paths
from litestar import Litestar, get
from litestar.dto import MsgspecDTO, DTOConfig
import msgspec
class User(msgspec.Struct):
id: int
name: str
email: str
class UserReadDTO(MsgspecDTO[User]):
config = DTOConfig(exclude={"email"})
@get("/users/{user_id:int}", return_dto=UserReadDTO)
async def get_user(user_id: int) -> User: ...
app = Litestar([get_user])
Output: email stripped on serialization; msgspec is roughly 5-10× faster than Pydantic for this shape.
# Recipe 2 — DI provider with caching
from litestar import Provide
from litestar.di import Provide
async def get_db_session() -> AsyncSession:
async with SessionLocal() as s:
yield s
app = Litestar(
route_handlers=[...],
dependencies={"db": Provide(get_db_session)},
)
Output: every route declaring db: AsyncSession gets a fresh scoped session.
# Recipe 3 — OpenAPI control: pick a UI and add servers
from litestar.openapi import OpenAPIConfig
from litestar.openapi.plugins import SwaggerRenderPlugin
openapi_config = OpenAPIConfig(
title="My API",
version="1.0.0",
path="/docs",
render_plugins=[SwaggerRenderPlugin()],
servers=[{"url": "https://api.example.com"}],
)
app = Litestar(route_handlers=[...], openapi_config=openapi_config)
Output: Swagger UI at /docs; OpenAPI document at /docs/openapi.json.
# Recipe 4 — Channels (websockets pub/sub)
from litestar import Litestar
from litestar.channels import ChannelsPlugin
from litestar.channels.backends.memory import MemoryChannelsBackend
channels = ChannelsPlugin(
backend=MemoryChannelsBackend(history=10),
channels=["chat"],
)
app = Litestar([], plugins=[channels])
Output: in-memory channel with last-10-message history; swap for Redis backend for multi-process.
# Recipe 5 — JWT auth with the bundled plugin
from litestar.security.jwt import JWTAuth, Token
jwt_auth = JWTAuth[User](
retrieve_user_handler=retrieve_user,
token_secret=os.environ["JWT_SECRET"],
exclude=["/login", "/docs", "/schema"],
)
app = Litestar([login_handler, ...], on_app_init=[jwt_auth.on_app_init])
Output: every non-excluded route requires a valid JWT.
Troubleshooting common errors
| Error / Symptom | Likely cause | Fix |
|---|---|---|
ImportError: cannot import name '...' from 'starlite' | Code still on the old name | Rename imports to litestar; uninstall the old package. |
ValidationException: ... on requests | DTO config mismatch | Verify DTOConfig include/exclude and that the response type matches the DTO's source. |
| OpenAPI shows wrong schema | Mixing inline Pydantic and DTOs | Standardize on one — DTO-based handlers everywhere or annotation-based everywhere. |
litestar CLI not found | Missing litestar[cli] or [standard] | pip install "litestar[standard]". |
| Async DB session leaks | Provider not using yield correctly | Use async def provider with yield so cleanup runs after the response. |
| Granian worker exits immediately | Wrong interface flag | --interface asgi (not wsgi or rsgi). |
pydantic.ValidationError not auto-handled | Custom exception handler swallows it | Remove the catch-all; Litestar maps Pydantic errors to 400 by default. |
| Channels never broadcast | Wrong backend or channel not declared | Pre-declare in channels=[...]; switch to RedisChannelsBackend for multi-process. |
Testing & CI integration
Litestar ships a TestClient (sync) and AsyncTestClient (async) — both wrap httpx and call the app in-process. For full DI/plugin coverage, use the app factory pattern so each test builds a fresh Litestar instance.
# pytest fixture for a fresh app per test
import pytest
from litestar import Litestar
from litestar.testing import TestClient
@pytest.fixture
def app():
return Litestar(route_handlers=[my_handler])
@pytest.fixture
def client(app):
with TestClient(app=app) as c:
yield c
def test_get(client):
r = client.get("/items/42")
assert r.status_code == 200
Output: test passes; lifespan startup/shutdown fire inside the with block.
# Async test
import pytest
from litestar.testing import AsyncTestClient
@pytest.mark.asyncio
async def test_get_async(app):
async with AsyncTestClient(app=app) as c:
r = await c.get("/items/42")
assert r.status_code == 200
Output: async-native; lifespan still wired.
# polyfactory for DTO fixtures
# pip install polyfactory
from polyfactory.factories.pydantic_factory import ModelFactory
class UserFactory(ModelFactory[User]):
__model__ = User
user = UserFactory.build() # auto-populated random instance
Output: fully-populated User; useful for hypothesis-style property tests.
When NOT to use this
Litestar is a strong choice for many APIs, but consider alternatives when:
- You're already deep in the FastAPI ecosystem — tutorials, courses, and a larger SDK surface make it the safer default.
- You need Django's admin + ORM — Litestar is API-first; pair Django + django-ninja instead.
- Pure sync apps — Flask is simpler and well-trodden.
- Hard pre-1.0-deps policy concerns — Litestar
2.xis stable but the project is newer than FastAPI. If "stable for a decade" matters more than throughput, weigh that. - Tiny single-route scripts —
starlettedirectly is even leaner.
See also
- Python: litestar — API tutorial, handlers, DI, DTOs
- Concept: API — REST design fundamentals
- Concept: async — async/await mental model
- Packages: pip-fastapi — the better-known alternative