AutoModel — SQL-first Reverse ORM for Rust, Built for the greater DX and for the AI Era
Database access in Rust typically falls into two camps: ORMs (Diesel, SeaORM) and compile-time checked SQL (sqlx). Both have trade-offs that become sharply worse when an AI assistant — or any automated tool — is working with your code, and humans are exposed to a far more intense code-review cycle.
AutoModel is different: you write plain SQL, and the tool generates real Rust source files.
queries/users/get_user.sql → src/generated/users.rs (checked into git)
Why AutoModel
- Human or AI can read everything. Generated structs, function signatures,
error enums, and type aliases — all corresponding to the actual database
schema, including constraints exposed as structured Rust enums — are ordinary
.rsfiles in your repo. An LLM can inspect them and produce correct calling code on the first try — no database connection or special tooling required. - Plain SQL stays plain SQL. Your queries are
.sqlfiles with full syntax highlighting. No query builder, no expression DSL. Any valid PostgreSQL query works — window functions, CTEs, recursive queries, lateral joins, aggregations,UNNESTbatch inserts, partitioned tables, domain types, composite types, conditional clauses — all of SQL, with no restrictions. - Build-time code generation, not compile-time magic.
build.rsconnects to the database once, extracts types from prepared statements, and writes.rsfiles — seconds, not the minutes of a full compile. After that, builds are offline. CI can verify generated code is up-to-date without a live database. - Diff-friendly and reviewable. Because the generated code is committed, pull request reviewers (human or AI) see exactly what changed — nothing hidden inside macro expansion.
- Built-in query analytics. During generation, AutoModel runs
EXPLAINon every query. Each generated function includes the query plan in its doc comments, and a committed warnings file flags sequential scans and multi-partition access — surfaced at build and review time. - Feature-rich control over generated code. Struct reuse and deduplication,
diff-based conditional updates, custom struct naming,
multiunzipbatch inserts, strongly typedjson/jsonb, full composite-type support — and much more. - Less code to write, review, and test. The glue between SQL and Rust —
structs, parameter binding, error enums, conversions — is machine-generated.
Adding a query is a single
.sqlfile, and you get a typed Rust function on the next build.
The result: a workflow where SQL is the source of truth, types are real files, every tool in the ecosystem — IDE, AI, CI, code review — can see the full picture, and development moves faster because an entire layer of boilerplate is eliminated.
Project structure
This is a Cargo workspace with three main components:
automodel-lib/— the core library for generating typed functions from SQLautomodel-cli/— command-line interfaceexample-app/— an example application demonstrating build-time generation
Quick start
Add AutoModel to Cargo.toml:
[]
= "0.12"
[]
= "0.12"
= { = "1.0", = ["rt"] }
Write a plain SQL query in queries/users/get_user_by_id.sql:
SELECT id, name, email, created_at
FROM users
WHERE id = #{id}
Build (with a build.rs that calls automodel::AutoModel::generate), then call
the generated function:
let user = get_user_by_id.await?;
Full setup, including build.rs, is in
Installation & Configuration.
Documentation
The full documentation is a progressive, feature-by-feature guide in
docs/. Start there and work down:
Getting started
Core query features
Types & structs
Bulk & mutation patterns
Operations & reference
- Telemetry & Query Analysis
- CLI & Workspace Commands
- Supported PostgreSQL Types
- Generated Code, Modules & CI
- Metadata Block Reference
Advanced guides
- Composite Types vs JSONB — choosing between PostgreSQL composite types and JSONB columns, with side-by-side comparisons and schema-evolution best practices.
Requirements
- PostgreSQL database (for code generation only)
- Rust 1.70+
- tokio runtime
License
MIT License — see LICENSE for details.