logoalt Hacker News

Show HN: Oxyde – Pydantic-native async ORM with a Rust core

123 pointsby mr_Fatalystlast Friday at 1:35 PM64 commentsview on HN

Hi HN! I built Oxyde because I was tired of duplicating my models.

If you use FastAPI, you know the drill. You define Pydantic models for your API, then define separate ORM models for your database, then write converters between them. SQLModel tries to fix this but it's still SQLAlchemy underneath. Tortoise gives you a nice Django-style API but its own model system. Django ORM is great but welded to the framework.

I wanted something simple: your Pydantic model IS your database model. One class, full validation on input and output, native type hints, zero duplication. The query API is Django-style (.objects.filter(), .exclude(), Q/F expressions) because I think it's one of the best designs out there.

Explicit over implicit. I tried to remove all the magic. Queries don't touch the database until you call a terminal method like .all(), .get(), or .first(). If you don't explicitly call .join() or .prefetch(), related data won't be loaded. No lazy loading, no surprise N+1 queries behind your back. You see exactly what hits the database by reading the code.

Type safety was a big motivation. Python's weak spot is runtime surprises, so Oxyde tackles this on three levels: (1) when you run makemigrations, it also generates .pyi stub files with fully typed queries, so your IDE knows that filter(age__gte=...) takes an int, that create() accepts exactly the fields your model has, and that .all() returns list[User] not list[Any]; (2) Pydantic validates data going into the database; (3) Pydantic validates data coming back out via model_validate(). You get autocompletion, red squiggles on typos, and runtime guarantees, all from the same model definition.

Why Rust? Not for speed as a goal. I don't do "language X is better" debates. Each one is good at what it was made for. Python is hard to beat for expressing business logic. But infrastructure stuff like SQL generation, connection pooling, and row serialization is where a systems language makes sense. So I split it: Python handles your models and business logic, Rust handles the database plumbing. Queries are built as an IR in Python, serialized via MessagePack, sent to Rust which generates dialect-specific SQL, executes it, and streams results back. Speed is a side effect of this split, not the goal. But since you're not paying a performance tax for the convenience, here are the benchmarks if curious: https://oxyde.fatalyst.dev/latest/advanced/benchmarks/

What's there today: Django-style migrations (makemigrations / migrate), transactions with savepoints, joins and prefetch, PostgreSQL + SQLite + MySQL, FastAPI integration, and an auto-generated admin panel that works with FastAPI, Litestar, Sanic, Quart, and Falcon (https://github.com/mr-fatalyst/oxyde-admin).

It's v0.5, beta, active development, API might still change. This is my attempt to build the ORM I personally wanted to use. Would love feedback, criticism, ideas.

Docs: https://oxyde.fatalyst.dev/

Step-by-step FastAPI tutorial (blog API from scratch): https://github.com/mr-fatalyst/fastapi-oxyde-example


Comments

outlinestoday at 12:38 PM

This is pretty similar to what django-ninja offers as well with their Schema modeling [1]. I found it to be a big help personally and always wanted something for fastapi.

Django-ninja is essentially the fastapi of the django world so this library would be enough for me to go all in on fastapi. I just never felt like I found a python orm with the level of ergonomics of django + async of modern python

[1] https://django-ninja.dev/guides/response/django-pydantic/

roel_vyesterday at 10:37 PM

Why would one want to couple these two? Doesn't that couple, say, your API interface with your database schema? Whereas in reality these are separate concepts, even if, yes, sometimes you return a 'user' from an API that looks the same as the 'user' in the database? Honest question, I only just recently got into FastAPI and I was a bit confused at first that yes, it seemed like a lot of duplication, but after a little bit of experience, they are different things that aren't always the same. So what am I missing?

show 6 replies
throwawayffffaslast Friday at 1:57 PM

Lol I never knew django orm is faster than SQLAlchemy. But having used both that makes sense.

> Why Rust? ... Rust handles the database plumbing. Queries are built as an IR in Python, serialized via MessagePack, sent to Rust which generates dialect-specific SQL, executes it, and streams results back. Speed is a side effect of this split, not the goal.

Nice.

So what does it take to deploy this, dependency wise?

show 2 replies
murkttoday at 7:54 AM

Seeing a new library in 2026 that uses Django-style filter syntax is really surprising.

With SQLAlchemy approach I can easily find all usages of a particular column everywhere.

    .filter(Folder.user_id == user_id)
Versus

    .filter(user_id=user_id)
Grepping by user_id will obviously produce hundreds and thousands of matches, probably from dozens of tables.
show 1 reply
luckycharms810today at 12:27 AM

As a non ORM person - I do love the Pydantic functionality that comes out of the box w pyscopg3.

https://www.psycopg.org/psycopg3/docs/advanced/typing.html#e...

show 1 reply
ryan14975today at 3:41 AM

The coupling concern is valid but I think it's the right trade-off for most CRUD apps. In practice, 80% of your endpoints are thin wrappers around your models anyway. The remaining 20% where you need separate request/response schemas — you just write those by hand.

The auto-generated admin panel is a nice touch. That alone saves days on internal tooling.

show 1 reply
jgauthyesterday at 11:47 PM

This looks great, and like it could address a need in ecosystem. Also, the admin dashboard is such a great feature of django, nice job building it from the get-go.

show 1 reply
Gri22lyBeartoday at 11:37 AM

interesting! the django filter syntax is a nice touch, i've always found it pretty intuitive. i've bounced between django and sqlalchemy, and it makes sense that a tighter integration like this could be faster for simpler apps.

kevinqitoday at 12:22 AM

I think Prisma does type-safe ORM really well on the typescript side, and was sad it doesn't seem to be super supported in python. This feels sort of similar and makes a lot of sense!

show 1 reply
JSR_FDEDtoday at 4:18 AM

This is great, you’ve taken the pieces of Django I’m most envious of (the amazing ORM and Admin panel), and made them available separately. Timing couldn’t be better just as I’m starting to use Quart in earnest.

show 1 reply
fishgoesblubtoday at 3:51 AM

Is it possible to initialise a fresh database without manually running commands to run migrations? I'm not seeing anything in the docs to do so.

show 1 reply
knrzyesterday at 10:59 PM

Lowkey hope this replaces Django ORM

show 1 reply
never_inlinetoday at 5:00 AM

1. AI Slop Post

2. """You define Pydantic models for your API, then define separate ORM models for your database, then write converters between them.""" So you could've written something that let you convert between two. That would not warrant a whole new ORM.

3. """But infrastructure stuff like SQL generation, connection pooling, and row serialization is where a systems language makes sense."""

This makes no sense to me (except row serialization - maybe, but you're incurring a messagepack overhead instead). Unnecessary native dependency.

show 1 reply
ForHackernewsyesterday at 10:14 PM

This sounds great and there's a real gap in the ecosystem for a tool like this. https://sqlmodel.tiangolo.com/ looked promising but it's actually worse than useless because if you add it to your Pydantic models, it disables all validation: https://github.com/fastapi/sqlmodel/issues/52

show 1 reply
waterTanukiyesterday at 11:08 PM

We need more creative names for rust packages because this is going to cause confusion

There's already Oxide computers https://oxide.computer/ and Oxc the JS linter/formatter https://oxc.rs/.

show 1 reply
unconscionabletoday at 2:51 AM

This is great. Are there any live sites running it in production?

Django + async is a nightmare so this is a very welcome project.

show 1 reply
TZubiriyesterday at 10:51 PM

Didn't the committee agree that ORMs were a mistale and a thing of the past?

show 3 replies
instig007yesterday at 10:50 PM

> But infrastructure stuff like SQL generation, connection pooling, and row serialization is where a systems language makes sense.

not really, what makes sense is being JIT-able and friendly to PyPy.

> Type safety was a big motivation.

> https://oxyde.fatalyst.dev/latest/guide/expressions/#basic-u...

> F("views") + 1

If your typed query sub-language can't avoid stringly references to the field names already defined by the schema objects, then it's the lost battle already.

show 1 reply
catlover76yesterday at 11:48 PM

[dead]

openclaw01today at 6:28 AM

Oxyde looks like a solid project. I've been curious if there are any benchmarks comparing it to SQLAlchemy's async setup. Specifically, I'm interested in how much of a performance bump that Rust core actually gives you when things get busy.

show 1 reply