Toasty 正式发布:Rust 终于有了一个“好用“的异步 ORM
本文基于 Tokio 官方博客 Toasty, an async ORM for Rust, is now on crates.io 整理撰写。
正式发布
2026 年 4 月,Toasty 正式登陆 crates.io。
这是一个面向 Rust 的异步 ORM,由 Tokio 团队开发,核心设计目标只有一个:让它好用。Toasty 同时支持 SQL 和 NoSQL 数据库,当前 NoSQL 侧已可使用 DynamoDB,更多数据库的支持正在推进中。
用户文档和 API 文档已同步上线,可以直接开始上手。
它长什么样
Toasty 的使用方式非常直接。通过派生宏#[derive(toasty::Model)]定义数据模型,然后用配套的宏和方法完成查询。
以下是一个完整的示例:
#[derive(Debug, toasty::Model)]structUser{#[key]#[auto]id:u64,name:String,#[unique]email:String,#[has_many]todos:toasty::HasMany<Todo>,}#[derive(Debug, toasty::Model)]structTodo{#[key]#[auto]id:u64,#[index]user_id:u64,#[belongs_to(key = user_id, references = id)]user:toasty::BelongsTo<User>,title:String,}// 创建用户,ID 由数据库自动生成toasty::create!(User{name:"John Doe",email:"john@example.com",}).exec(&mutdb).await?;// 按 email 查找用户letuser=User::get_by_email(&mutdb,"john@example.com").await?;模型定义清晰,关系声明(has_many、belongs_to)直接写在字段上,唯一索引、主键、自增 ID 均通过属性标注完成。查询时无需手写 SQL,也不需要额外的 Schema 文件。
Rust 生态为什么需要一个 ORM
Rust 的适用边界正在扩大
在许多人的印象里,Rust 是一门面向底层系统、网络基础设施的语言,和 Web 应用开发关系不大。但 Toasty 的作者认为这个边界正在改变。
Rust 可以覆盖的场景正变得越来越广:高性能系统服务、命令行工具、移动端嵌入、通过 WASM 运行在浏览器里……能够用一套语言、一套工具链贯穿这些场景,本身就是一种生产力的提升,不需要在语言之间来回切换。
Rust 在 Web 应用开发上的短板,很大程度上不是语言本身的问题,而是生态不够成熟——缺少高质量的高层抽象库,而 ORM 正是其中最关键的一块。
AI 时代,Rust 的"护栏"变成了优势
原作者在文章里提出了一个有意思的观点:AI 正在成为 Rust 采用的推动力,而不是阻力。
过去,Rust 的学习曲线是一道门槛。但现在,用 AI 辅助学习已经让大量开发者以更快的速度上手 Rust——边写代码边用 AI 解释,已经成为一种有效的学习路径。另一方面,AI 生成代码的速度很快,反而让 Rust 编译慢的问题变得不那么突出。
更深层的一点:如果开发者选择让 AI 直接生成并运行代码,Rust 强类型系统和所有权模型所提供的约束就成了质量护栏。语言本身的规则越严格,AI 生成代码出问题的概率就越低,问题被控制在越小的范围内。这个逻辑在 AI 编程场景下,反而放大了 Rust 的价值。
当然,这一切的前提是 Rust 的生态要跟得上——需要有成熟的、约定明确的高层库,Toasty 正是在这个背景下被推进的。
不只是 ORM:应用级查询引擎
作者给 Toasty 的定位是"application-level query engine"(应用级查询引擎),这个说法比 ORM 更能描述它的实际工作方式。
应用 Schema 与数据库 Schema 解耦
在 Toasty 中,你面对的是应用层的数据模型,而不是数据库的表结构。应用模型更接近一张图(graph)而不是一组关系表,你写的查询也是针对这张图写的。
Toasty 的查询引擎负责在中间做转换:接收应用层的查询语句,再根据目标数据库的能力,将其翻译成一组具体的数据库操作。
SQL 与 NoSQL 的统一抽象
Toasty 对 SQL 和 NoSQL 提供统一的 API 接口。目标不是把数据库的差异完全隐藏掉,而是提供一套在两种数据库类型下都"说得通"的 API。
你仍然需要了解你使用的数据库的特性,仍然需要合理地设计数据模型,仍然需要对查询的代价有所判断——Toasty 不替你做这些决策,但它让你用同一套 API 去表达这些决策。
查询引擎做了哪些"重活"
原本的设想是:面向 SQL 数据库时,Toasty 的查询语句基本上可以直接透传给数据库;面向 NoSQL 时,查询引擎再做规划判断。但实际开发过程中,SQL 侧同样需要查询引擎介入很深。
一个具体的例子:按 key 更新一行数据,同时带一个前置条件,并且要能区分"key 不存在"和"前置条件未满足"这两种失败情况。在 PostgreSQL 里,这需要写成带多个子查询的 CTE——逻辑上并不复杂,但用原生 SQL 写很繁琐,容易出错。Toasty 的查询引擎负责把这类应用层常见的查询模式,翻译成正确的数据库操作。
为什么花了这么长时间
Toasty 的第一个 commit 是两年多以前。从公开宣布到正式发布,又过了一年多。
API 设计的大转向
最初的 Toasty 使用的是独立 Schema 文件来定义数据模型,类似于 Prisma 的做法。当时选择这条路,是因为作者认为用#[derive(Model)]宏的方式实现不了他想要的所有功能。
社区的反馈很直接:Schema 文件这条路不对。作者听进去了,推倒重来。经过进一步探索,他找到了完全用派生宏实现完整功能的方法,最终 API 就是现在看到的样子。
比预期更宏大的工程
这个项目在开始时没有一个非常清晰的终态愿景,很多设计决策是在实际推进中逐步发现的,内部也经历了几次重写。这种探索性的开发方式虽然耗时,但也带来了更扎实的基础。
当前状态与后续计划
Toasty 目前是早期版本,真实的生产使用还非常有限。作者的判断是:目前的核心能力已经足以支撑基本的应用开发,但距离全面成熟还有一段路要走。
几点值得关注的信息:
- 会有频繁的破坏性变更。0.x 阶段的版本迭代不会维持 API 稳定性,升级时需要注意。
- Bug 会有。早期使用难免遇到边界情况,作者承诺会积极响应。
- 核心已经稳固。这是作者认为可以公开发布的主要原因——基础架构是可靠的,后续功能在此之上增量添加。
反馈渠道:GitHub Discussions、Discord 的 #toasty 频道,以及 TokioConf 现场。
总结
Toasty 的发布,对 Rust Web 应用生态来说是一个实质性的进展。它解决的不只是"有没有 ORM"的问题,更试图回答"Rust 能不能成为一门主流的 Web 开发语言"这个更大的问题。
从设计上看,Toasty 的几个取舍值得关注:用#[derive]宏而不是独立 Schema 文件,这让模型定义更贴近 Rust 的惯用法;把自己定位为查询引擎而不只是 ORM 映射层,这为 NoSQL 支持和更复杂的查询模式留了空间;而对 AI 辅助编程趋势的主动适应,也说明 Toasty 在设计上考虑了更广泛的使用场景。
现在是早期,但基础已经在那里了。如果你在用 Tokio 构建异步 Rust 应用,值得花时间看一下。
相关链接
- GitHub:https://github.com/tokio-rs/toasty
- crates.io:https://crates.io/crates/toasty
- 用户文档:https://tokio-rs.github.io/toasty/nightly/guide/
- API 文档:https://docs.rs/toasty
- 原文:https://tokio.rs/blog/2026-04-03-toasty-released
