ORM for Rust: comparison of Diesel, SeaORM, SQLx and code examples

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

ORM for Rust: comparison and examples



The Rust ecosystem offers several powerful solutions for working with databases. In this article, we will compare three popular ORM-like tools: Diesel, SeaORM, and SQLx. Each has its own philosophy and area of application. Let's look at their features, performance, and provide practical examples.



1. Diesel — classic ORM with type safety



Diesel is the most mature ORM for Rust, built on the principle of "compile-time type safety." It requires explicit schema definition through migrations and generates strictly typed structures.



Features:

  • Compilation checks query correctness (SQL errors — at build time)
  • Support for PostgreSQL, MySQL, SQLite
  • Synchronous engine (asynchronous support requires diesel-async)
  • Custom DSL for building queries


Code example (Diesel + PostgreSQL):

// models.rsuse diesel::prelude::*;

#[derive(Queryable, Selectable)]#[diesel(table_name = crate::schema::users)]#[diesel(check_for_backend(diesel::pg::Pg))]pub struct User { pub id: i32, pub name: String, pub email: String,}

// main.rsuse diesel::prelude::*;use diesel::pg::PgConnection;

fn get_user(conn: &mut PgConnection, user_id: i32) -> Option<User> { use crate::schema::users::dsl::*; users.filter(id.eq(user_id)) .first::<User>(conn) .ok()}


When to choose: for projects where compile-time query safety is critical, and you are ready for a strict schema.



2. SeaORM — asynchronous ORM with ActiveRecord approach



SeaORM is a modern asynchronous ORM inspired by Ruby on Rails. It supports both code-first and entity generation from an existing database.



Features:

  • Full asynchronicity (Tokio, async-std)
  • Support for PostgreSQL, MySQL, SQLite, and CockroachDB
  • Migrations, relations (has_many, belongs_to), pagination
  • Code generator sea-orm-cli


Code example (SeaORM + PostgreSQL):

use sea_orm::*;use entity::user;

async fn find_user(db: &DatabaseConnection, user_id: i32) -> Result<Option<user::Model>, DbErr> { user::Entity::find_by_id(user_id) .one(db) .await}

// Usageasync fn example() { let db = Database::connect("postgres://user:pass@localhost/db").await.unwrap(); if let Some(user) = find_user(&db, 42).await.unwrap() { println!("User: {} ({})", user.name, user.email); }}


When to choose: for asynchronous web applications (Actix, Axum) where active development and rich out-of-the-box functionality are needed.



3. SQLx — "almost ORM" with maximum flexibility



SQLx is not exactly an ORM, but rather an asynchronous SQL client with query checking. It allows you to write pure SQL, but checks its correctness at compile time.



Features:

  • Compile-time query checking (via the sqlx::query! macro)
  • Full asynchronicity
  • Support for PostgreSQL, MySQL, SQLite, MSSQL
  • Support for JSON, migrations, connection pooling


Code example (SQLx + PostgreSQL):

use sqlx::PgPool;

#[derive(sqlx::FromRow)]struct User { id: i32, name: String, email: String,}

async fn get_user(pool: &PgPool, user_id: i32) -> Result<Option<User>, sqlx::Error> { sqlx::query_as::<_, User>("SELECT id, name, email FROM users WHERE id = $1") .bind(user_id) .fetch_optional(pool) .await}


When to choose: if you prefer writing SQL

Recommendations