Frequently Asked Questions
General
What is CRUDCrate?
CRUDCrate is a Rust library that generates complete REST APIs from Sea-ORM entities using derive macros. It eliminates boilerplate code for CRUD operations, filtering, sorting, pagination, and relationships.
How does it compare to other solutions?
| Feature | CRUDCrate | Manual Axum | Diesel | Other ORMs |
|---|---|---|---|---|
| Code Generation | ✅ Derive macro | ❌ Manual | ❌ Manual | Varies |
| Filtering | ✅ Built-in | ❌ Manual | ❌ Manual | Varies |
| Pagination | ✅ Built-in | ❌ Manual | ❌ Manual | Varies |
| Relationships | ✅ Automatic | ❌ Manual | ❌ Manual | Varies |
| Type Safety | ✅ Full | ✅ Full | ✅ Full | Varies |
What security features are included?
CRUDCrate includes:
- SQL injection prevention
- Pagination DoS protection
- Comprehensive error handling
- Proper logging integration
Installation
What are the minimum Rust version requirements?
Rust 1.70+ is required for stable proc-macro features.
Do I need to install Sea-ORM separately?
Yes. CRUDCrate works alongside Sea-ORM:
[dependencies]
crudcrate = "0.1"
sea-orm = { version = "1.0", features = ["runtime-tokio-rustls", "sqlx-postgres"] }
Usage
Can I use CRUDCrate with an existing Sea-ORM project?
Yes! Just add #[derive(EntityToModels)] and #[crudcrate(...)] attributes to your existing entities.
How do I customize the generated endpoints?
Three ways:
- Attributes: Configure behavior with
#[crudcrate(...)] - CRUDOperations: Implement hooks for business logic
- Custom Handlers: Replace entire handlers when needed
Can I have some entities without routers?
Yes. Only add generate_router when you want endpoints:
// With router
#[crudcrate(generate_router)]
// Without router (just models)
#[crudcrate()]
How do I add authentication?
Use Axum middleware:
let app = Router::new()
.merge(protected_router())
.layer(middleware::from_fn(auth_middleware));
See Security for details.
Can I have different auth for different routes?
Yes. Use nested routers:
let public = Router::new().merge(public_routes());
let protected = Router::new()
.merge(admin_routes())
.layer(admin_auth_layer);
let app = Router::new().merge(public).merge(protected);
Filtering & Search
Which fields can be filtered?
Only fields marked #[crudcrate(filterable)]:
#[crudcrate(filterable)] // Can filter
pub status: String,
pub secret: String, // Cannot filter
How does fulltext search work?
Fields marked #[crudcrate(fulltext)] are searched with ?q=:
GET /items?q=search terms
The query uses database-optimized search (GIN for Postgres, FULLTEXT for MySQL).
Can I combine filters and search?
Yes:
GET /items?filter={"status":"active"}&q=urgent&sort=["created_at","DESC"]
Relationships
How do I load related entities?
- Define Sea-ORM relations
- Add join field with
#[crudcrate(non_db_attr, join(one))]
#[sea_orm(ignore)]
#[crudcrate(non_db_attr, join(one))]
pub comments: Vec<Comment>,
Why are relationships not loading?
Check that:
#[sea_orm(ignore)]is present#[crudcrate(non_db_attr)]is present- Sea-ORM
Relatedtrait is implemented join(...)specifiesoneand/orall
How do I prevent circular references?
Use depth limit:
#[crudcrate(non_db_attr, join(one, depth = 2))]
Performance
Is CRUDCrate slow?
No. Generated code has zero runtime overhead. All generation happens at compile time.
How do I optimize for large tables?
- Add database indexes on filtered/sorted fields
- Use pagination (built-in limits: 1000 items max)
- Exclude heavy fields from lists:
#[crudcrate(exclude(list))] - Limit join depth
Does loading relationships cause N+1 queries?
No — get_all() with join(all) uses batch loading that reduces N+1 queries to just 2 queries (1 for parents + 1 per join field) using WHERE parent_id IN (...). This applies to depth=1 joins; deeper joins (depth > 1) may issue additional queries for nested relations. Single-item get_one() uses per-item queries, which is acceptable for individual lookups.
Troubleshooting
Compilation error: “cannot find derive macro”
Import it:
use crudcrate::EntityToModels;
Error: “field not found” when filtering
The field must be marked filterable:
#[crudcrate(filterable)]
pub status: String,
Relationships return empty
Ensure:
- Database has related records
- Sea-ORM
Relatedtrait is implemented - Join is configured:
join(one)orjoin(one, all)
“Too many items” error on bulk delete
Built-in safety limit is 100 items. Split into multiple requests.
Timestamp fields not auto-updating
Check:
on_createandon_updateare set- Field is excluded from update model:
exclude(update)
#[crudcrate(exclude(create, update), on_create = chrono::Utc::now(), on_update = chrono::Utc::now())]
pub updated_at: DateTimeUtc,
Migration
Can I migrate from manual handlers?
Yes. CRUDCrate is additive. You can:
- Start with one entity
- Keep existing handlers for others
- Gradually migrate
How do I migrate to a new version?
Check the Changelog for breaking changes. Most updates are backward compatible.
Contributing
How can I contribute?
See Contributing for guidelines.
Where do I report bugs?
Open an issue on GitHub.
Is there a roadmap?
Planned features:
- GraphQL support
- OpenAPI generation
- More database optimizations
- Cursor-based pagination option
Learn More
- Getting Started: First Steps Tutorial
- Examples: Minimal Example
- Reference: Field Attributes