Oxyde ORM¶
Oxyde ORM is a type-safe, Pydantic-centric asynchronous ORM with a high-performance Rust core designed for clarity, speed, and reliability.
Inspired by the elegance of Django’s ORM, Oxyde focuses on explicitness over magic, providing a modern developer-friendly workflow with predictable behavior and strong typing throughout.
Quick Links¶
-
Installation
Install Oxyde and set up your environment
-
Quick Start
Build your first app in 5 minutes
-
Guide
Learn Oxyde step by step
-
API Reference
Complete API documentation
Features¶
- Django-style API — Familiar
Model.objects.filter()syntax - Pydantic v2 models — Full validation, type hints, serialization
- Async-first — Built for modern async Python with
asyncio - Rust performance — SQL generation and execution in native Rust
- Multi-database — PostgreSQL, SQLite, MySQL support
- Transactions —
transaction.atomic()context manager with savepoints - Migrations — Django-style
makemigrationsandmigrateCLI
Why Oxyde?¶
Performance¶
Oxyde's Rust core handles SQL generation and query execution, releasing Python's GIL during database I/O. This enables true parallelism for database operations.
Benchmarks vs popular Python ORMs (avg ops/sec, higher is better):
| Database | Oxyde | Tortoise | Piccolo | SQLAlchemy | SQLModel | Peewee | Django |
|---|---|---|---|---|---|---|---|
| PostgreSQL | 924 | 748 | 746 | 336 | 324 | 61 | 59 |
| MySQL | 1037 | 1019 | — | 434 | 420 | 371 | 313 |
| SQLite | 1232 | 1477 | 295 | 342 | 336 | 449 | 434 |
Type Safety¶
Built on Pydantic v2, Oxyde provides full type checking for models and queries. Your IDE understands your database schema.
Familiar API¶
If you know Django ORM, you know Oxyde. The QuerySet API follows Django conventions:
# Django
User.objects.filter(age__gte=18).exclude(status="banned").order_by("-created_at")
# Oxyde (identical)
await User.objects.filter(age__gte=18).exclude(status="banned").order_by("-created_at").all()
Async Native¶
No sync wrappers or thread pools. Oxyde is async from the ground up:
from oxyde.db import transaction
async with transaction.atomic():
user = await User.objects.create(name="Alice")
await Profile.objects.create(user_id=user.id)
Database Support¶
| Database | Min Version | Status | Notes |
|---|---|---|---|
| PostgreSQL | 12+ | Full | RETURNING, UPSERT, FOR UPDATE/SHARE, JSON, Arrays |
| SQLite | 3.35+ | Full | RETURNING, UPSERT, WAL mode by default |
| MySQL | 8.0+ | Full | UPSERT via ON DUPLICATE KEY, FOR UPDATE/SHARE |
SQLite < 3.35: Falls back to
last_insert_rowid()which may return incorrect IDs with concurrent inserts.MySQL: No RETURNING clause — uses
last_insert_id(). Bulk INSERT returns calculated ID range which may be incorrect with concurrent inserts.