Skip to content
rusthacks.dev
Databases

SQLx Versus Diesel and SeaORM and How to Choose for New Code

SQLx runs your SQL, Diesel builds queries in Rust's type system and SeaORM is an async ORM on top of SQLx. Compare them on the work you actually do and pick one.

2 min read
Summarize in AI
Flat illustration for the post “SQLx Versus Diesel and SeaORM and How to Choose for New Code”, composed around async.

Rust's database story splits along a single line: do you want to write SQL, or write Rust that generates it? SQLx is the first, Diesel the second, and SeaORM the second with relations and async included. This post compares them on the same task, a query by filter, and ends with a recommendation. It is the decision piece in the SQLx explained cluster.

SQLx 0.8, Diesel 2.2, SeaORM 1, Rust 1.90.

The same query three ways

Find users older than 30, newest first.

SQLx:

rust
let users = sqlx::query_as!(
    User,
    "SELECT id, name, age FROM users WHERE age > $1 ORDER BY id DESC",
    30
)
.fetch_all(&pool)
.await?;

Diesel:

rust
use crate::schema::users::dsl::*;

let result = users
    .filter(age.gt(30))
    .order(id.desc())
    .load::<User>(&mut conn)?;

SeaORM:

rust
use entity::user;

let result = user::Entity::find()
    .filter(user::Column::Age.gt(30))
    .order_by_desc(user::Column::Id)
    .all(&db)
    .await?;

All three are type safe in their own way. A renamed column breaks the build in SQLx (against the database), in Diesel (against schema.rs) and in SeaORM (against the generated entity).

Where they differ

SQLxDieselSeaORM
Styleraw SQLquery DSLentities and relations
Asyncnativediesel-async cratenative
Compile-time checkdatabase or offline cacheschema.rsentity code
Relationsby handbelongs_to, joins in DSLbuilt in, with loading helpers
MigrationsSQL filesSQL files via diesel_cliRust or SQL via sea-orm-migration
Learning curveSQL knowledgetype heavy errorsan ORM's API

What hurts in practice

SQLx leaves you writing the same SELECT column lists and join mappings repeatedly, and dynamic filters need QueryBuilder. Diesel produces long type errors when a query is slightly wrong, and some SQL features need raw fragments or sql_query. SeaORM hides SQL, so performance surprises such as N+1 loads (one query per parent row) need attention.

Compile time

Diesel's heavy generic types and SeaORM's entity generation both increase build time compared with SQLx. We do not publish a number here, because it depends on the number of tables and features; cargo's --timings report on your own project tells you.

So which one

  • Small to medium service, SQL-comfortable team: SQLx.
  • Domain with many simple CRUD tables and relations, ORM-comfortable team, async: SeaORM.
  • Existing synchronous code, or a preference for the DSL and its guarantees: Diesel.

Do not run an ORM to avoid learning SQL; you will meet SQL when the ORM's query is slow.

When the decision matters less

Isolate access behind a repository module with functions that return your domain types, as described in layers and error boundaries. Then the cost of switching is that module. The projects document themselves at Diesel and SeaORM.

Share

Keep reading

Get new posts by email

We send one email when a new post is published. No spam.

Unsubscribe in one click. No spam, ever.