关于 Dynoxide
Dynoxide 是用 Rust 编写、以 SQLite 为存储的 DynamoDB 模拟器,可作为 HTTP 服务、MCP 服务或嵌入式库使用。它面向本地开发、测试和 CI,启动快、内存占用低。
主要功能
- 01兼容 DynamoDB API 的 HTTP 服务
- 02可直接嵌入 Rust 与 iOS 应用的库模式
- 03通过 MCP 向编码 Agent 暴露 35 个 DynamoDB 工具
- 04基于 SQLite 的存储,支持 WebAssembly 构建
- 05支持 GSI、LSI、事务、PartiQL 与 Streams
适用场景
- 01为集成测试提供快速启动的 DynamoDB 替代环境
- 02在 Rust 测试中为每个用例创建独立的内存数据库
- 03让编码 Agent 直接操作本地 DynamoDB 表与数据
MCP 相关
Dynoxide 的 MCP 服务向 MCP 客户端暴露 35 个 DynamoDB 工具,使编码 Agent 可以直接读写本地数据库。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
35收录的工具列表 · 更新于 5 天前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| statements | any | 是 | PartiQL 语句数组。每项格式为 {Statement: "...", Parameters?: [...], ConsistentRead?: true|false, ReturnValuesOnConditionCheckFailure?: "ALL_OLD"|"NONE"}。ConsistentRead 按成员设置,决定该成员读取的计费速率,而不影响返回哪些行。ReturnValuesOnConditionCheckFailure 为 ALL_OLD 时,会在该成员的 Error 中返回条件失败的 UPDATE 或 DELETE 所针对的项目。批次必须全部为读取操作或全部为写入操作;SELECT 成员必须指定表的主键,且不得指定索引。 |
| return_consumed_capacity | enum | 否 | 要返回的消耗容量:TOTAL 表示操作总量,INDEXES 表示按表和索引细分的总量,NONE(默认值)表示不返回。数值遵循 DynamoDB 的计费规则,与 DynamoDB API 对相同请求返回的结果一致。INDEXES | TOTAL | NONE | null |
详细介绍
Dynoxide
一款由 SQLite 提供支持的 Rust DynamoDB 模拟器。可作为 HTTP 服务或供编码 Agent 使用的 MCP 服务运行,也可作为库嵌入 Rust 和 iOS 应用,并可编译为适用于浏览器的 WebAssembly。
上方的 crates.io 徽章显示的是 crate 版本,仅涵盖 Rust 库。所有需要安装而非作为依赖项引入的内容都有独立的 产品 版本:二进制文件、npm 包、容器镜像、浏览器引擎和 Action。
dynoxide --version输出的就是这个版本,提交 Bug 报告时也应注明此版本。为何有两个版本。
为什么选择 Dynoxide?
我开发 Dynoxide,是因为 DynamoDB Local 速度慢、体量大,而且无法嵌入。它需要 JVM,而常见的基于 Docker 的配置会增加约 3 秒冷启动时间、空闲时约 209 MB 内存占用,以及约 225MB 的 Docker 镜像(磁盘上约 473 MB),而此时你还什么有用的事都没做。如果你在运行集成测试,就得等待 Docker 启动、JVM 预热,以及流水线运行。
Dynoxide 是原生二进制文件。它在毫秒内启动,空闲时占用约 7.2 MB 内存,下载大小约 3 MB。将任意 DynamoDB SDK 指向它,测试即可正常运行。
对于 Rust 项目,还有一种嵌入式模式——通过 Database::memory() 直接调用 API,完全不需要 HTTP 层。每项测试都能获得独立的内存数据库,启动成本为零。由于它可编译为无运行时依赖的原生库,因此也能在 DynamoDB Local 无法运行的平台上运行,包括 iOS。
性能
本地开发(Apple Silicon)
| 指标 | Dynoxide(嵌入式) | Dynoxide(HTTP) | DynamoDB Local |
|---|---|---|---|
| 冷启动 | 约 0.2ms | 约 15ms | 约 2,287ms |
| GetItem(p50) | 9µs | 0.1ms | 0.8ms |
| PutItem 吞吐量 | 约 51,613 ops/s | 约 6,703 ops/s | 约 945 ops/s |
| 50 项测试套件(顺序运行) | 约 484ms | 约 569ms | 约 2,407ms |
| 50 项测试套件(4 倍并行) | 约 203ms | 约 235ms | 约 1,189ms |
CI(GitHub Actions)
数据来自 ubuntu-latest(4 核 AMD EPYC 7763,16GB RAM)。提交 17be96a。
| 指标 | Dynoxide(嵌入式) | Dynoxide(HTTP) | DynamoDB Local | LocalStack(所有服务) | Floci | MiniStack |
|---|---|---|---|---|---|---|
| 冷启动 | <1ms | 约 2ms | 约 2,605ms | 约 12,217ms | 约 228ms | 约 2,636ms |
| GetItem(p50) | 16µs | 0.3ms | 0.8ms | - | - | - |
| 50 项 CI 测试套件 | 828ms | 859ms | 2,628ms | - | - | - |
| 完整工作负载(10K 项) | - | 3.2s | 12.2s | - | - | - |
| 二进制文件 / 镜像(下载) | 约 3 MB | 约 3 MB | 225 MB | 1.1 GB | - | - |
| 二进制文件 / 镜像(磁盘占用) | 8 MB | 8 MB | 473 MB | 1.1 GB | 234 MB | 162 MB |
| 空闲内存(RSS) | 约 7.2 MB | 约 8 MB | 约 209 MB | 约 387 MB | 约 23 MB | 约 47 MB |
在 Apple Silicon 上,差距更大,因为更快的 CPU 放大了原生代码与 JVM 开销之间的差异。两组数据都是通过同一基准测试套件测得的真实结果。完整方法说明和各操作的详细数据 →
一致性
Dynoxide 由 Parity Suite 持续通过真实 DynamoDB 验证。Parity Suite 是 DynamoDB 一致性测试套件,它使用同一套测试矩阵测试 AWS 本身以及所有主流 DynamoDB 模拟器。随着测试套件扩充和各引擎变化,通过率也会随之变化,因此我们不固定一个容易过时的快照,而是提供实时排名:
- 实时排名:所有引擎的当前通过率,按级别细分
- paritysuite/dynamodb-conformance:测试套件本身、原始结果,以及各测试目标的运行方式
声明:Dynoxide 和 Parity Suite 由同一人维护。该测试套件使用与其他所有引擎相同的公开矩阵为 Dynoxide 评分,测试结果和测试代码均为开源。
以上针对原生构建。WebAssembly 构建作为单独一行计分:它通过了所有已实现的测试,但跳过的测试数量远高于其他目标,因为仍有多项操作尚未实现。
对比
| Dynoxide | DynamoDB Local | LocalStack(所有服务) | Floci | MiniStack | dynalite | |
|---|---|---|---|---|---|---|
| 语言 | Rust | Java | Python + Java | Java(GraalVM 原生映像) | Python | Node.js |
| 存储 | SQLite | SQLite | SQLite(通过 DDB Local) | 自有存储(内存、持久化或 WAL) | 自有存储(内存,可选磁盘状态) | LevelDB |
| 运行时依赖 | - | JVM | Docker + LocalStack 账户(身份验证令牌) | Docker | Docker 或 Python | Node.js |
| 可嵌入(Rust / iOS) | ✓ | - | - | - | - | - |
| 面向 Agent 的 MCP 服务 | ✓ | - | - | - | - | - |
LocalStack 在内部使用 DynamoDB Local 作为其 DynamoDB 引擎,因此其启动和内存开销包括 DynamoDB Local 的 JVM,以及 LocalStack 自有的 Python 路由层。自 2026 年 3 月起,即使是过去免费的服务,启动其映像也需要 LocalStack 账户和 LOCALSTACK_AUTH_TOKEN。Floci 和 MiniStack 与 LocalStack 一样,都是通用 AWS 模拟器,各自使用自己的 DynamoDB 引擎,而非 DynamoDB Local。
快速开始
无需安装即可运行本地服务:
npx dynoxide --port 8000
或者将其安装到项目中以固定版本,之后 npx dynoxide 会使用该副本:
npm install --save-dev dynoxide
或者在 Docker 中运行,它可直接替代 amazon/dynamodb-local:
docker run --rm -p 8000:8000 ghcr.io/nubo-db/dynoxide
将任意 AWS SDK 或 DynamoDB 客户端指向 http://localhost:8000。有关 Homebrew、Cargo、预构建二进制文件,以及将其嵌入为 Rust 库的信息,请参阅安装指南。
添加 --log quiet 可禁止在
stderr 中输出信息性启动和关闭消息(适用于测试套件)。此选项适用于 serve、mcp 和 import --serve
或 --mcp,警告和错误仍会输出。不添加 --log 时,输出保持不变。
文档
- 安装 - npm、Homebrew、Cargo、二进制文件、GitHub Actions 和 Docker
- HTTP 服务 - 运行兼容 DynamoDB 的 HTTP API
- Testcontainers - 在测试套件中驱动容器,以及所需的等待策略
- MCP 服务 - 面向编码 Agent 的 Model Context Protocol 服务
- DynamoDB Streams - 启用并读取流记录
- 导入 CLI - 加载数据、筛选表和匿名化
- WebAssembly - 浏览器构建版本和嵌入契约
- 用作 Rust 库 - 嵌入式模式和功能标志
- 兼容性 - 与 DynamoDB 相比的操作、表达式和 PartiQL 覆盖情况
- 版本管理 - 版本号的承诺,以及触发主版本更新的条件
- 发布 - 发布周期和流程
支持的操作
Dynoxide 实现了 DynamoDB API,涵盖表、项目、查询和扫描、批处理、事务、PartiQL、流、TTL 和标签,并支持 GSI 和 LSI、完整的表达式语法,以及兼容 DynamoDB 的分页、验证和错误代码。有关逐项操作说明和比较,请参阅兼容性摘要。
限制
Dynoxide 面向本地开发、测试和 CI,并非用于替代生产环境中的 DynamoDB,因此有意不实现以下两类功能。
没有本地对应功能的云端专属操作不会实现:备份和时间点恢复、全局表、Kinesis 流、资源策略和容量管理。调用这类操作会收到 UnknownOperationException。
使用它进行测试时,还需注意以下一些行为差异:
ConsistentRead会被接受,但不会产生任何影响。SQLite 具有强一致性,因此每次读取本来就具有强一致性——你无法复现最终一致性读取。- 流只公开一个分片。
DescribeStream会返回一个分片,其ExclusiveStartShardId和Limit分页参数会被接受,但会被忽略。 - 不会模拟事务竞争错误(
TransactionConflictException、TransactionInProgressException)——单个进程中不会发生并发竞争。
有关各项功能的支持矩阵,请参阅实时能力矩阵;逐项操作的完整说明请参阅兼容性摘要。
致谢
Dynoxide 的 DynamoDB API 语义和验证逻辑参考了 dynalite。这款优秀的 DynamoDB 模拟器基于 LevelDB 构建,由 Michael Hart 开发,目前由 Architect 团队维护。
Dynoxide 是以洁净室方式实现的 Rust 项目。没有直接移植任何代码,但 dynalite 在匹配线上 DynamoDB 行为(包括边缘情况和错误消息)方面所做的深入工作,是极其宝贵的参考。
Dynoxide 使用 SQLite 作为存储层。(AWS 的 DynamoDB Local 内部也使用 SQLite。)
许可证
采用 MIT 和 Apache 2.0 双重许可。请参阅 LICENSE-MIT 和 LICENSE-APACHE。
商标
Amazon DynamoDB、DynamoDB 和 AWS 是 Amazon.com, Inc. 或其关联公司的商标。Dynoxide 是一个独立项目,与 Amazon 没有关联,未获得其认可或赞助,本文中的任何内容均不授予使用这些名称或商标的权利。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。