Introduction
Tortoise ORM brings a Django-style ORM experience to the async Python ecosystem. It supports PostgreSQL, MySQL, MariaDB, and SQLite through async database drivers, making it a natural choice for FastAPI, Starlette, Sanic, and other ASGI frameworks that benefit from non-blocking database access.
What Tortoise ORM Does
- Defines models with typed fields, primary keys, and validators using a declarative syntax
- Supports ForeignKey, OneToOne, and ManyToMany relations with eager and lazy loading
- Provides Django-style queryset chaining with filter, exclude, annotate, and aggregate
- Runs all database operations asynchronously using asyncpg, aiomysql, or aiosqlite drivers
- Includes a schema generator and an Aerich migration tool for managing database changes
Architecture Overview
Tortoise ORM uses a registry-based model system where model classes register themselves at import time. Queries are built using a queryset API that constructs SQL lazily and executes via an async database backend. The backend layer abstracts driver differences between asyncpg (PostgreSQL), aiomysql (MySQL), and aiosqlite (SQLite). Relations are resolved through descriptor-based field access that triggers additional queries or uses prefetched data. The Aerich companion tool tracks schema changes and generates migration files.
Self-Hosting & Configuration
- Install with an async driver extra: tortoise-orm[asyncpg] for PostgreSQL, [aiomysql] for MySQL
- Initialize Tortoise with a database URL and module paths in your application startup
- Use generate_schemas() for quick prototyping or Aerich for production migration management
- Configure connection pools, timeouts, and read replicas through the database URL and config dict
- Integrate with ASGI frameworks using the built-in register_tortoise helper for lifecycle management
Key Features
- Async-native ORM built on asyncio with no synchronous fallback overhead
- Django-inspired model definitions with typed fields and relation descriptors
- Queryset API supporting filters, annotations, aggregations, and subqueries
- Aerich migration tool for versioned schema management in production
- Native support for PostgreSQL JSON fields, array fields, and database functions
Comparison with Similar Tools
- SQLAlchemy (async) — More mature, broader SQL dialect support; steeper learning curve for ORM patterns
- Django ORM — Synchronous by design; familiar API but requires sync-to-async wrappers in ASGI apps
- Peewee — Lightweight synchronous ORM; simpler but lacks native async support
- SQLModel — Combines Pydantic and SQLAlchemy; good for FastAPI but limited relation support
- Prisma Client Python — TypeScript-inspired query builder; strong typing but less Pythonic
FAQ
Q: Which async frameworks work with Tortoise ORM? A: FastAPI, Starlette, Sanic, Quart, and any ASGI framework. Tortoise provides integration helpers for lifecycle management.
Q: How do I handle database migrations? A: Use Aerich, the companion migration tool. It generates, applies, and rolls back schema changes similar to Django migrations.
Q: Does Tortoise ORM support raw SQL? A: Yes. Use Tortoise.get_connection() to execute raw SQL queries alongside ORM operations within the same transaction context.
Q: Can I use Tortoise ORM with synchronous code? A: Tortoise is async-first. Use run_async() for scripts or asyncio.run() to bridge from synchronous entry points.