Zero-boilerplate Repository Pattern for modern Rust applications.
Automatic SQLx parameter binding and result parsing with trait-based repositories. Write SQL traits, get async implementations with sophisticated pagination, streaming, batch operations, and more. Seamlessly integrates with existing SQLx code โ continue using SQLx queries normally, override generated methods, and reuse generated _query methods across different contexts.
Features
๐ฏ Core
- Zero boilerplate โ Write traits, not implementations
- Compile-time safety โ Always uses SQLx's compile-time macros (
query_as!,query!,query_scalar!) ensuring type safety and SQL validation at build time - Smart type inference โ Returns
T,Option<T>,Vec<T>, tuples, scalars and others - Multi-database โ PostgreSQL, MySQL, SQLite
๐ Advanced
-
Pagination & Dynamic Queries Built-in Serial, Slice, and Cursor strategies. Automatically generates the correct
COUNT(*)query for pagination metadata and handles complex dynamic filters viaParamsBuilder. -
Parameter Naming Use named parameters with
@parameter_namesyntax for cleaner, more readable queries. Parameters can appear in any order and be reused multiple times within the same query. -
Aliases Keep your SQL DRY by defining reusable fragments (like common column sets or table joins) and injecting them using
{{mustache}}syntax. -
Scopes Rails-inspired query composability. Define reusable
WHEREclauses or orderings that are automatically injected into every query in the repository. Supports Alias interpolation (e.g.,age > {{min_age}}). Ideal for global patterns like 'SoftDeletable', 'Multi-tenancy', or 'Activable'. -
Batch Operations Perform ultra-fast bulk inserts (up to 40x faster) by taking
Vec<T>arguments, automatically generating efficient multi-value SQL statements. -
JSON Support First-class JSON support. Use the
jsonattribute to automatically serialize/deserialize complex Rust structs into database JSON columns without manual boilerplate. -
Unchecked Queries An escape hatch for DDL, legacy queries, or dynamic SQL that cannot be verified at compile time. Use
uncheckedto bypass the macro's strict validation when necessary. -
Method Variants Automatically generate
_with_tx,_with_conn, and_with_poolvariants for every repository method, ensuring you never get stuck with the wrong executor type. -
Streaming Return
impl Stream<Item = Result<T>>to process large datasets efficiently row-by-row, keeping memory usage constant. Leverages SQLx's nativefetchfor zero-overhead streaming. -
Tracing Zero-config observability powered by the
tracingcrate. Automatically instruments every query with#[instrument]spans, capturing execution time, arguments, and errors. -
Generics & Lifetimes Full support for Rust's generic type system, allowing repositories to handle generic executors, lifetimes, and complex trait bounds.
-
Hover to inspect Hover over any repository method in your IDE to see the exact SQL query and generated implementation code.
Feature Flags
SQLx-Data uses feature flags to enable database and type support. You must specify both a database and typically json:
Database Features (choose one)
sqliteโ SQLite database supportmysqlโ MySQL database supportpostgresโ PostgreSQL database support
Type Features
jsonโ JSON support with automatic serialization (recommended)chronoโ Chrono date/time typestimeโ Time crate supportuuidโ UUID type supportbigdecimalโ BigDecimal supportrust_decimalโ Rust Decimal supportipnetโ IP network typesbit-vecโ Bit vector supportmac_addressโ MAC address types
Other Features
tracingโ Automatic query instrumentationtls-nativeโ Native TLS supporttls-rustlsโ Rustls TLS support
Example Usage
# For SQLite with JSON
[]
= { = "0.1.4", = ["sqlite", "json"] }
= { = "0.8", = ["sqlite", "runtime-tokio", "macros", "migrate"] }
# For PostgreSQL with multiple types
[]
= { = "0.1.4", = ["postgres", "json", "chrono", "uuid"] }
= { = "0.8", = ["postgres", "runtime-tokio", "macros", "migrate"] }
# For MySQL with tracing
[]
= { = "0.1.4", = ["mysql", "json", "tracing"] }
= { = "0.8", = ["mysql", "runtime-tokio", "macros", "migrate"] }
Quick Start
[]
= { = "0.1.4", = ["sqlite","json"] }
= { = "0.8", = ["sqlite", "runtime-tokio"] }
= { = "1", = ["full"] }
use ;
async
Under the Hood
When you define a repository trait with #[repo] and #[dml], the macros generate additional _query methods that contain the actual SQL execution logic. Your original methods become default implementations that call these generated methods, giving you the flexibility to override them with custom logic.
// What you write:
// What gets generated (simplified):
This design allows you to:
- Use generated methods directly by just implementing
get_pool() - Override specific methods with custom logic while still calling
_querymethods - Reuse
_querymethods in different contexts or custom implementations
Pagination & Dynamic Queries
Handle complex pagination scenarios with the fluent ParamsBuilder API.
1. Zero-Boilerplate Filters
Combine pagination, filtering, and sorting in a single object:
use ;
// Client usage:
let params = new
.serial
.page // Page 1, 20 items per page
.done
.filter
.gt // WHERE age > 18
.like // AND name LIKE '%Alice%'
.done
.sort
.desc // ORDER BY id DESC
.asc // THEN BY name ASC
.done
.build;
let result = repo.find_users.await?;
2. Cursor Pagination (Infinite Scroll)
Best for high-performance feeds. Supports after, before based on specific fields.
use ;
// Initial Request:
let params = new
.cursor
.first_page // Start from beginning
.done
.sort
.desc // Critical: Cursor relies on stable sorting
.done
.limit // Set limit on ParamsBuilder
.build;
let page = repo.user_feed.await?;
// Next Page:
if let Some = page.next_cursor
3. Dynamic Search
Built-in text search construction:
let params = new
.slice
.page
.done
.search
.query // Search term
.fields // Columns to search
.case_sensitive
.done
.build;
// Generates:
// WHERE ... AND (username LIKE '%alice%' OR email LIKE '%alice%')
Parameter Naming
Clean, readable queries with named parameters using @parameter_name syntax. Parameters can be defined in any order and reused multiple times.
Basic Named Parameters
Parameter Reuse
Same parameter can be used multiple times in a single query(only for postgres and sqlite):
Mixed with Positional
Named parameters work alongside traditional positional parameters:
Complex Queries
Named parameters shine in complex queries with many conditions:
Benefits:
- ๐ Readable: Parameter names explain their purpose in the query
- ๐ Flexible Order: Function parameters can be in any order
- โป๏ธ Reusable: Same parameter used multiple times without repetition
- ๐ Compatible: Works with existing positional parameter code
- ๐ก๏ธ Type Safe: Same compile-time verification as positional parameters
Aliases
Reusable SQL fragments for DRY code:
```rust
Scopes
Automatic query enhancement โ define once, apply everywhere:
Pro tip: Perfect for Rails-like patterns such as multi-tenancy (tenant_id = ?), soft deletes (archived_at IS NULL), and active records (status = 'active').
```rust
Generated SQL:
-- find_all() becomes:
SELECT * FROM users
WHERE age >= 18
AND name IS NOT NULL
AND birth_year > 2000
ORDER BY age DESC
-- find_alphabetical() becomes:
SELECT * FROM users
WHERE age >= 18
AND name IS NOT NULL
AND birth_year > 2000
ORDER BY name
Batch Operations
Efficient bulk inserts:
// Usage
let users = vec!;
repo.insert_batch.await?;
Generated Code:
// The macro generates this optimized batch insert method:
async
Performance: Inserts 1000 rows in ~50ms vs ~2000ms with individual inserts
Streaming
Best for: Large datasets, memory efficiency
Uses SQLx's native fetch method for zero-overhead row-by-row processing, keeping memory usage constant regardless of result set size.
use Stream;
// Usage
let mut stream = repo.stream_active;
while let Some = stream.next.await
JSON Support
Automatic JSON serialization/deserialization:
use Json;
use ;
Unchecked Queries
Bypass compile-time verification for complex queries or DDL:
Binary Data (BLOBs)
Efficient handling of binary data:
use Bytes;
Generics & Lifetimes
Full support for Rust's type system:
Method Variants
Generate multiple executor variants automatically:
// Generates 5 methods:
// - update_name(&self, ...) // uses get_pool()
// - update_name_with_pool(&self, pool: &Pool, ...) // explicit pool
// - update_name_with_tx(&self, tx: &mut Transaction, ...)
// - update_name_with_conn(&self, conn: &mut Connection, ...)
// - update_name_with_executor(&self, exec: impl Executor, ...)
// Usage
let mut tx = pool.begin.await?;
repo.update_name_with_tx.await?;
repo.update_name_with_tx.await?;
tx.commit.await?;
Tracing
Built-in observability powered by the tracing library. Zero configuration required to get detailed logs automatically instrumented with #[instrument]:
use instrument;
// Automatically logs:
// - Method entry/exit
// - Parameters (except skipped ones)
// - Execution time
// - Errors
Hover to Inspect
See the generated SQL and implementation in your IDE:

Pro tip: Copy the generated code to override methods or call _query methods from custom logic:
Complex Queries
File-based Queries
Supported Return Types
| Return Type | Example | Fetch Strategy |
|---|---|---|
T |
User |
fetch_one |
Option<T> |
Option<User> |
fetch_optional |
Vec<T> |
Vec<User> |
fetch_all |
| Scalar | i64, String, bool |
fetch_one |
| Tuple | (String, i64) |
fetch_one |
Vec<Tuple> |
Vec<(String, i64)> |
fetch_all |
Serial<T> |
Serial<User> |
Paginated |
Slice<T> |
Slice<User> |
Paginated |
Cursor<T> |
Cursor<User> |
Paginated |
| Database-specific | MySqlQueryResult, PgQueryResult |
execute |
Database Support
| Database | Placeholder | Example |
|---|---|---|
| MySQL | ? |
WHERE id = ? |
| PostgreSQL | $1, $2 |
WHERE id = $1 |
| SQLite | $1, $2 |
WHERE id = $1 |
Performance
- Compile-time overhead: ~20-90ยตs per query (macro expansion)
- Runtime overhead: Zero โ generates the same code you'd write manually
- Batch inserts: 40x faster than individual inserts (1000 rows: 50ms vs 2000ms)
Examples
hello-worldโ A minimal setup to get started.axum-crud-apiโ A full-featured REST API using Axum, showcasing pagination, filtering, and best practices.
Contributing
Contributions are welcome! Please see CONTRIBUTING.md.
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT license (LICENSE-MIT)
at your option.
Acknowledgments
Built on top of the excellent SQLx library. Powered by syn, quote, and proc-macro2 for macro expansion. SQL parsing and validation leverage sqlparser.