HNHacker News
TopNewBestAskShowJobs

mr_Fatalyst

148 karma · joined March 22, 2025

submissionscomments
mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
Thanks, appreciate the support (^_^)!
mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
The way I see it, having everything as Pydantic makes this natural. Your DB model, your request schema, your response DTO are all BaseModels. Converting between them is just model_dump() and model_validate(), or plain inheritance. No adapters, no mapping layers. So when you need to split things apart, it's straightforward rather than painful.
mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
One thing that might help here: if you subclass an Oxyde model without defining class Meta: is_table = True, the child class won't be a table and won't have ORM behavior. So you can inherit the fields and validation but without save()/delete(). Not exactly a Protocol-based approach, but it gives you a clean read-only DTO derived from the same model.
mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
Right now makemigrations detects add/drop/alter columns, indexes, foreign keys, and constraints. Rename is treated as drop + create, same as Django's default. Automatic rename detection is on the roadmap but not there yet. For now you'd edit the generated migration manually if you need a rename. Splitting a model into two would be detected as one dropped table and two new ones, so you'd also want to adjust that migration by hand to preserve data.
mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
That's exactly why Oxyde has no lazy loading at all. If you don't call .join() or .prefetch(), related data simply won't be there. N+1 is impossible by design, not by discipline.
mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
Yep, there's a full comparison including SQLAlchemy async: https://oxyde.fatalyst.dev/latest/advanced/benchmarks/
mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
Thanks! Not yet, it's still v0.5 and the API hasn't fully stabilized. But it's getting there.
mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
1. We're all AI agents in a simulation anyway...

2. A converter still means maintaining two model systems. The point was to not have two in the first place.

3. MessagePack overhead is negligible compared to actual DB round-trips. And the Rust core isn't just SQL generation, it bundles the full driver stack (sqlx), pooling, and streaming, so you don't need asyncpg/aiosqlite as separate dependencies.

mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
Well said, that's pretty much how I see it too. Thanks!
mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
Right now it's CLI-based: 'oxyde migrate'. You can call 'apply_migrations()' programmatically, but that's not a publicly documented API yet. Good point though, worth adding.
mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
Thanks! The admin panel supports Quart out of the box, so you should be good to go.
mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
Good question. Working with Python objects in PyO3 requires holding the GIL. With MessagePack, Python serializes to bytes, hands them off, and Rust works completely GIL-free from that point. Same on the way back. So the GIL is held only for the brief serde step, not during SQL generation or execution.
mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
You can't call filter() without a model. It's always Folder.objects.filter(user_id=user_id), so the context is right there in the code. Plus the generated .pyi stubs give your IDE full type info per model, so "go to usages" works through the type system.
mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
Exactly, that's the idea.
mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
For Oxyde specifically, it's still a young project, so the best public examples I have are the FastAPI tutorial (https://github.com/mr-fatalyst/fastapi-oxyde-example) and the admin panel examples (https://github.com/mr-fatalyst/oxyde-admin). Bigger real-world showcases will come with time. But in general, ORMs pay for themselves when you have lots of models, relations, and standard CRUD with validation. The moment you hand-write the same INSERT/UPDATE/SELECT with joins for every endpoint, it adds up fast.
mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
Thanks! Haven't used Prisma much myself, but glad the approach resonates.
mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
Thanks, appreciate it! Felt wrong to ship an ORM without one.
mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
Right, it's not DBAPI compliant. The whole IO stack goes through Rust/sqlx, so PEP-249 doesn't apply. Oxyde has its own exception hierarchy (OxydeError, IntegrityError, NotFoundError, etc.). In practice most people catch ORM-level exceptions rather than DBAPI ones, but fair to call out.

On F(), good point. The descriptor approach is something I've been thinking about. Definitely on the radar.

mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
Yeah, we're running out of ways to spell oxide (^_^)
mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
Thanks! Not really trying to replace Django ORM though, it's great at what it does. Just trying to build the ORM I'd personally want to use in 2026.
mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
Must have missed that meeting. ORMs are not for everything, but for CRUD-heavy apps with validation they save a lot of boilerplate. And there's always execute_raw() for when you need to go off-script.
mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
The Rust core is not just about speed. It bundles native database drivers (sqlx), connection pooling, streaming serialization. It's more about the full IO stack than just making Python faster. On F("views"), fair point. It's a conscious trade-off for now. The .pyi stubs cover filter(), create(), and other query methods, but F() is still stringly-typed. Room for improvement there.
mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
The ORM doesn't force you to use the DB model as your API schema. It's a regular Pydantic BaseModel, so you can make separate request/response schemas whenever you need to. For simple CRUD, using the model directly saves boilerplate. For complex cases, you decouple them as usual. The goal is not one model for everything, it's one contract. Everything speaks Pydantic, whether it's your API layer or your database layer.
mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
I was surprised too when I saw the results. The benchmarks test standard ORM usage patterns, not the full power of any ORM. SQLAlchemy is more flexible, but that flexibility comes with some overhead. That said, the ORM layer is rarely the bottleneck when working with a database. The benchmarks were more about making sure that all the Pydantic validation I added comes for free, not about winning a speed race.
mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
Thanks! Yeah, that SQLModel issue is actually one of the things that pushed me to build this. In Oxyde the models are just Pydantic BaseModel subclasses, so validation always works, both on the way in and on the way out via model_validate().
mr_Fatalyst··on Show HN: Oxyde – Pydantic-native async ORM with a Rust core
Just pip install oxyde, that's it. The Rust core (oxyde-core) ships as pre-built wheels for Linux, macOS, and Windows, so no Rust toolchain needed. Python-side dependencies are just pydantic, msgpack, and typer for the CLI. Database drivers are bundled in the Rust core (uses sqlx under the hood), so you don't need to install asyncpg/aiosqlite/etc separately either.
mr_Fatalyst··on [dead]
Hi all,

About a month ago I shared FastOpenAPI on Show HN. The response was far beyond what I expected with thoughtful feedback, feature requests, technical questions and even a great PR. I tried to sum it all up in this write-up including what the community focused on, what was improved and how it shaped the project going forward.

Thanks again to everyone who took part!

mr_Fatalyst··on Show HN: FastOpenAPI – automated docs for many Python frameworks
Big thanks to everyone for the feedback and your reactions! I've started working on version 0.5.0 and will try to include as much as possible of what was highlighted here.
mr_Fatalyst··on Show HN: FastOpenAPI – automated docs for many Python frameworks
I added the draft in 0.5.0-dev

https://github.com/mr-fatalyst/fastopenapi/tree/0.5.0-dev

Example: https://github.com/mr-fatalyst/fastopenapi/tree/0.5.0-dev/ex...

mr_Fatalyst··on Show HN: FastOpenAPI – automated docs for many Python frameworks
Thanks! I have a draft for aiohttp integration. I think I'll add it later.
Page 1 of 2Next →