Open-source project
tonbo-io/tonbo avatar
tonbo-io/tonbo

Tonbo: an embedded database with no server, Parquet on S3, and a manifest for coordination

Tonbo is an embedded database for serverless and edge runtimes.

1,631 stars105 forksRustApache-2.0

At a glance

What is it?
Tonbo is a Rust embedded database aimed at serverless and edge runtimes, where the compute is stateless but the data is not. The answer is a merge tree over object storage, with writes going to a write ahead log, then a memtable, then immutable Parquet tables, and a manifest committed by compare and swap so that no long lived coordinator has to exist.
Who is it for?
Adopt Tonbo if you are running functions on serverless or edge infrastructure and need durable, queryable state without operating a database, and if your data is append heavy or event shaped, since that is the case the design serves. Do not adopt it as a general purpose relational replacement, because the storage model is a merge tree over Parquet objects rather than a row store, and the README positions it for append heavy and event like data.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 97 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem: stateless compute does not make your data stateless

Tonbo is an embedded database for serverless and edge runtimes, and the README states the design in one sentence: your data is stored as Parquet on S3, coordination happens through a manifest, and compute stays fully stateless. The motivation is the mismatch the project names directly, that serverless compute is stateless but your data is not. The list of reasons is built around that. It is async first, with the whole storage and query engine fully async for serverless and edge environments. There is no server to manage, because the data lives in S3, the coordination goes through the manifest and the compute stays stateless. It is Arrow native, so you define a rich data type with declarative schemas and query with zero copy `RecordBatch` objects. It runs anywhere, on Tokio, on WASM, on edge runtimes, or as a storage engine for building your own data infrastructure. And it uses open formats, since the data is standard Parquet files that any tool can read. The list of use cases follows from that shape, and it is a narrow list, which is the point.

WAL, memtable, Parquet tables, and a manifest that does the locking

The architecture section describes a merge tree optimized for object storage, and the write path is three stages: writes go to the WAL, then to the MemTable, then to Parquet SSTables, with MVCC for snapshot isolation and a manifest for coordination via compare and swap. Three consequences follow from that design. The first is stateless compute, where a worker only needs to read and update the manifest, and no long-lived coordinator is required, which is what makes it work on infrastructure that cannot hold a process open. The second is object storage compare and swap, so the manifest is committed with a CAS on S3 and any function can safely participate in commits, which is how concurrency is handled without a lock service. The third is immutable data, because the data files are write-once Parquet SSTables, which matches the strengths of S3 and other object stores rather than fighting them. For anyone who has operated a database, the interesting part is that the coordination problem has been pushed into a single mutable object, which is cheap to read and cheap to swap, at the cost of a round trip per commit.

Arrow native queries, snapshots and time travel

The query side is where the Arrow decision shows up. Records are defined with a `Record` derive, the schema is derived from the type, and results are `RecordBatch` values moved without copying, with a filter expressed as an `Expr` such as a greater-than comparison against a scalar, applied through a scan and collected into a result set. The example list in the README maps out the feature surface, and it is worth reading as the library's syllabus. There is a basic example that defines a schema, inserts and queries in 30 lines, a transaction example with MVCC transactions covering upsert, delete and read-your-writes, a snapshot example for consistent point in time reads while writes continue, a filter example covering equality, greater than, in, is null, and the boolean combinators, a scan options example for projection pushdown so a query reads only the columns it needs, a composite key example for multi-column keys in time series and partitioned data, a streaming example to process millions of rows without loading them into memory, a nested types example that stores deeply nested structs and lists as an Arrow StructArray, a time travel example that queries historical snapshots via MVCC timestamps, a dynamic schemas example that works without the derive, and an observability example. The dynamic schema example is the one that matters most for a serverless workload, since a function deployed today must still be able to read what a function wrote last month.

One abstraction across Tokio, WASM and object storage

The Cargo manifest shows how the portability is achieved, and the mechanism is the Fusio crate, which is pulled in as a git dependency at a pinned revision with a set of features, and the features differ per platform. The default feature set is `tokio` plus `typed-arrow`. The `tokio` feature turns on the Fusio executor, filesystem and HTTP client for the Tokio runtime. The `web` feature is the interesting one, described in the manifest as the web and WASM build using Fusio's WebExecutor and the WASM HTTP client stack, and `web-opfs` layers optional OPFS, which is the browser's origin private file system, on top of that. There is also an `s3-smoke` feature that compiles the optional S3 smoke test in `tests/s3_smoke.rs`. The dependencies underneath are the Arrow crates at version 57.1.0 for arrays, buffers, IPC, schema and selection, plus datafusion-common, a skiplist, crc32c and bytes, and a second in-house crate, `aisle`, also pulled from git. The examples directory includes a `cloudflare-worker/` project, which is the concrete answer to the question of what the web feature is for.

A library that emits traces but never installs a subscriber

The observability section describes a stance rather than a feature set. Tonbo uses the `tracing` crate for structured logging and distributed tracing, and as a library it emits spans and events but never initializes a global subscriber, so your application stays in control of the observability configuration. The README then shows three setups: the quick development one with the fmt subscriber and an environment filter, the production one adding JSON output, and the OpenTelemetry integration that builds a tracer with the OTLP pipeline, installs the tracing layer over a registry, and layers the formatter on top. This is the correct default for a library that will run inside someone else's function, and it is a small design decision that says something about how the project thinks about embedding. The project also documents itself the way a database team does, with a user guide of tutorials and concepts, an API reference on docs.rs, and a directory of RFCs, one of which is the logs and traces design document numbered 0012.

Coverage, compaction benchmarks and what they measure

The development section is specific about tooling, and the benchmark is the interesting part. Coverage uses the standard Rust route, adding the llvm-tools-preview component, installing cargo-llvm-cov at a pinned version with the locked flag, and then running it over the workspace to produce an lcov file with a summary, or an HTML report. The compaction benchmark has a default run of `cargo bench --bench compaction_local`, and the tuned run is configured entirely through environment variables with a `TONBO_COMPACTION_BENCH_` prefix, covering the number of ingest batches, the rows per batch, the key space, the artifact iterations, the criterion sample size and the WAL sync mode, and the README states that benchmark configuration is environment only. That last point is a design decision worth reading twice, because it means the benchmark can be swept in CI without editing code, which is what you want from a storage engine where compaction behaviour is the thing most likely to regress quietly.

Version skew, maturity and the shape of the project

The install line in the README, and the manifest it is meant to match:

bash
cargo add [email protected] tokio

The version numbers need reading carefully, because they disagree in a way that matters. The Cargo manifest declares version 0.4.0-a2, the README's install line uses `[email protected]`, the docs badge points at 0.4.0-a1 on docs.rs, and the published release tags in the list are 0.3.0, 0.3.1 and 0.3.2 from February to April 2025, while the last push to the branch was on 2026-07-18. So the current line is a pre-release in the 0.4 series, the README lags the manifest by one pre-release, and the stable published versions are from early 2025. The repository itself is compact, with `src/`, `benches/`, `tests/`, `examples/`, `docs/`, an `AGENTS.md`, a `rust-toolchain.toml`, a `rustfmt.toml` and a `LICENSE`, and the documentation points out to the website, the blog and a Discord community. The honest summary is that this is a young project with a serious storage design, published under Apache 2.0, and that you should expect the crate version to move while the on-disk format settles.

Editorial conclusion

Adopt Tonbo if you are running functions on serverless or edge infrastructure and need durable, queryable state without operating a database, and if your data is append heavy or event shaped, since that is the case the design serves. Do not adopt it as a general purpose relational replacement, because the storage model is a merge tree over Parquet objects rather than a row store, and the README positions it for append heavy and event like data. Before you start, check the version numbers carefully, since the manifest in the repository declares 0.4.0-a2 while the README's install line uses 0.4.0-a1, so pin deliberately rather than following the README blindly. Also read the local development path, because `.on_disk` is how you develop without S3, and decide whether the manifest compare and swap pattern is acceptable for your consistency needs. The licence is Apache-2.0, the last push was on 2026-07-18, and the released versions are 0.3.x from early 2025.

Frequently asked questions

How does Tonbo store and coordinate data?

Writes go to a WAL, then to a MemTable, then to Parquet SSTables, with MVCC for snapshot isolation, and a manifest committed by compare and swap on object storage provides coordination. A worker only reads and updates the manifest, so no long-lived coordinator is required and the compute stays stateless.

Where does Tonbo run?

On Tokio, on WASM and on edge runtimes, with the Cargo manifest providing a `web` feature that uses Fusio's WebExecutor and the WASM HTTP client stack, and a `web-opfs` feature that adds browser origin private file system support. The examples directory includes a cloudflare-worker project, and local development uses `.on_disk`.

Does Tonbo need an S3 bucket to develop against?

No. The quick start says that for local development you use `.on_disk("/tmp/users")` instead of the S3 object store, and the examples directory includes an `01_basic` example that defines a schema, inserts and queries in 30 lines.

Which version of Tonbo should I depend on?

Read it from the manifest before you copy the README, because they differ. The Cargo manifest declares version 0.4.0-a2, the README install line uses `[email protected]`, and the published release tags are 0.3.0 through 0.3.2 from early 2025, so the 0.4 line is still a pre-release.

Official sources

  1. License: Apache-2.0
  2. Project website
  3. README
  4. Releases
  5. tonbo-io/tonbo on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/tonbo-io-tonbo.svg)](https://hysenlabs.com/projects/tonbo-io-tonbo)

Was this useful?