Tortoise ORM

raw JSON →
1.1.7 verified Tue May 12 auth: no python install: verified quickstart: stale

Async ORM for Python inspired by Django ORM. Built on asyncio — requires async context. Current version: 1.1.7 (Mar 2026). v1.0 released 2024 — first stable release after years of 0.x. Breaking changes from 0.x: connections.close_all() removed, ConnectionHandler uses per-instance ContextVar storage. FastAPI integration changed from register_tortoise() to RegisterTortoise context manager. Does not work on serverless/Vercel without workarounds.

pip install tortoise-orm
error Tortoise is not initialised.
cause Tortoise ORM models are used before `Tortoise.init()` has been successfully called and awaited to initialize database connections and mappings.
fix
Ensure await Tortoise.init(...) is called at the application's startup, before any database operations involving models.
error sqlite3.OperationalError: no such table: <table_name>
cause The database table corresponding to a Tortoise ORM model has not been created or synchronized with the database schema.
fix
Call await Tortoise.generate_schemas() after await Tortoise.init() during application startup to create the necessary tables. For production, a proper migration tool like Aerich is recommended.
error RuntimeWarning: coroutine '...' was never awaited
cause An asynchronous method (coroutine) from Tortoise ORM was called without the `await` keyword, causing it to return a coroutine object that was never executed.
fix
Prefix all async Tortoise ORM calls with await, for example, await Tortoise.init(...), await model_instance.save(), await MyModel.all().
error AttributeError: module 'tortoise.contrib.fastapi' has no attribute 'register_tortoise'
cause The `register_tortoise` function was removed in Tortoise ORM v1.0 and replaced by the `RegisterTortoise` context manager for FastAPI integration.
fix
Use the RegisterTortoise context manager from tortoise.contrib.fastapi within your FastAPI application's startup/shutdown events to manage Tortoise ORM initialization and cleanup.
error AttributeError: module 'tortoise.connections' has no attribute 'close_all'
cause The `tortoise.connections.close_all()` function was removed in Tortoise ORM v1.0 and replaced by `Tortoise.close_connections()` for closing all database connections.
fix
Replace tortoise.connections.close_all() with await Tortoise.close_connections() to ensure all active database connections are properly closed during application shutdown.
breaking connections.close_all() removed in v1.0. Raises AttributeError.
fix Use Tortoise.close_connections() instead.
breaking Running multiple FastAPI apps in the same process (e.g., in tests) raises ConfigurationError: 'Global context fallback is already enabled'. Happens with lifespan-based testing.
fix Pass _enable_global_fallback=False to RegisterTortoise for secondary apps.
gotcha Must use 'modules' dict when calling Tortoise.init() — must list all model module paths explicitly. Missing a module means those models are unknown to Tortoise and relations fail silently.
fix modules={'models': ['myapp.models.user', 'myapp.models.post']} — list ALL model files.
gotcha tortoise-orm does not work on serverless/Vercel without workarounds. Connection pooling assumes long-running process — serverless cold starts cause 'connection pool is closed' errors.
fix Not recommended for serverless. Use asyncpg directly or a serverless-compatible ORM.
gotcha generate_schemas=True in production silently drops and recreates tables if schema changes. Use Aerich (tortoise's migration tool) for production schema management.
fix Set generate_schemas=False in production. Use aerich for migrations: pip install aerich
gotcha pydantic_model_creator() generates Pydantic models from Tortoise models. In v1.0, internal validator logic was cleaned up — custom PydanticMeta overrides may behave differently.
fix Test pydantic_model_creator() output after upgrading to v1.0.
gotcha DB-specific drivers must be installed separately. 'pip install tortoise-orm' alone raises ImproperlyConfigured when connecting to PostgreSQL or MySQL.
fix pip install 'tortoise-orm[asyncpg]' for PostgreSQL, 'tortoise-orm[asyncmy]' for MySQL, 'tortoise-orm[aiosqlite]' for SQLite.
breaking Database server is unreachable or connection refused. The application is configured to connect to a database (e.g., PostgreSQL on port 5432), but the server is not running or is not accessible at the specified host/port (e.g., 127.0.0.1:5432).
fix Ensure your database server (e.g., PostgreSQL) is running and accessible from the application's environment on the configured host and port. Verify database server logs, firewall rules, and the connection string (TORTOISE_CONFIG) used by Tortoise-ORM.
pip install 'tortoise-orm[accel]'
pip install 'tortoise-orm[asyncpg]'
python os / libc variant status wheel install import disk
3.10 alpine (musl) accel - - 0.00s 33.9M
3.10 alpine (musl) asyncpg - - 0.00s 32.0M
3.10 alpine (musl) tortoise-orm - - 0.00s 23.9M
3.10 slim (glibc) accel - - 0.00s 38M
3.10 slim (glibc) asyncpg - - 0.00s 35M
3.10 slim (glibc) tortoise-orm - - 0.00s 24M
3.11 alpine (musl) accel - - 0.00s 36.5M
3.11 alpine (musl) asyncpg - - 0.00s 34.6M
3.11 alpine (musl) tortoise-orm - - 0.00s 26.2M
3.11 slim (glibc) accel - - 0.00s 40M
3.11 slim (glibc) asyncpg - - 0.00s 38M
3.11 slim (glibc) tortoise-orm - - 0.00s 27M
3.12 alpine (musl) accel - - 0.00s 30.1M
3.12 alpine (musl) asyncpg - - 0.00s 27.8M
3.12 alpine (musl) tortoise-orm - - 0.00s 17.8M
3.12 slim (glibc) accel - - 0.00s 35M
3.12 slim (glibc) asyncpg - - 0.00s 31M
3.12 slim (glibc) tortoise-orm - - 0.00s 18M
3.13 alpine (musl) accel - - 0.00s 29.3M
3.13 alpine (musl) asyncpg - - 0.00s 27.1M
3.13 alpine (musl) tortoise-orm - - 0.00s 17.2M
3.13 slim (glibc) accel - - 0.00s 34M
3.13 slim (glibc) asyncpg - - 0.00s 31M
3.13 slim (glibc) tortoise-orm - - 0.00s 18M
3.9 alpine (musl) accel - - 0.00s 34.6M
3.9 alpine (musl) asyncpg - - 0.00s 32.7M
3.9 alpine (musl) tortoise-orm - - 0.00s 24.7M
3.9 slim (glibc) accel - - 0.00s 38M
3.9 slim (glibc) asyncpg - - 0.00s 36M
3.9 slim (glibc) tortoise-orm - - 0.00s 25M

Tortoise ORM v1.x standalone script with PostgreSQL.

# pip install 'tortoise-orm[asyncpg]'
from tortoise import Tortoise, fields
from tortoise.models import Model
import asyncio

class User(Model):
    id = fields.IntField(pk=True)
    name = fields.CharField(max_length=50)
    email = fields.CharField(max_length=120, unique=True)

    class Meta:
        table = 'users'

async def main():
    await Tortoise.init(
        db_url='postgres://user:pass@localhost/mydb',
        modules={'models': ['__main__']}
    )
    await Tortoise.generate_schemas()

    # Create
    user = await User.create(name='Alice', email='alice@example.com')

    # Query
    users = await User.filter(name='Alice').all()
    user = await User.get(id=1)
    user = await User.get_or_none(email='alice@example.com')

    await Tortoise.close_connections()

asyncio.run(main())