emdb 0.6.0

A lightweight, high-performance embedded database for Rust.
Documentation
<h1 align="center">
    <strong>emdb</strong>
    <br>
    <sup><sub>EMBEDDED DATABASE FOR RUST</sub></sup>
</h1>

<p align="center">
    <a href="https://crates.io/crates/emdb"><img alt="crates.io" src="https://img.shields.io/crates/v/emdb.svg"></a>
    <a href="https://docs.rs/emdb"><img alt="docs.rs" src="https://docs.rs/emdb/badge.svg"></a>
    <a href="https://github.com/jamesgober/emdb-rs/actions"><img alt="CI" src="https://github.com/jamesgober/emdb-rs/actions/workflows/ci.yml/badge.svg"></a>
    <a href="https://github.com/jamesgober/emdb-rs/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/badge/license-Apache--2.0-blue.svg"></a>
</p>

<p align="center">
    A lightweight, high-performance embedded database for Rust.
</p>

---

## Status

**v0.6.** Page-oriented storage format (4 KB pages, B-tree index, free-list,
WAL sidecar), automatic migration from v1/v2 log formats, optional
memory-mapped reads, closure-based transactions with atomic batch writes,
and a sharded in-memory primary index for fully parallel reads. The API
is still pre-1.0 and may change before 1.0.

Track progress and roadmap: <https://github.com/jamesgober/emdb-rs>

## Installation

```toml
[dependencies]
emdb = "0.6"
```

## Quick Start

```rust
use emdb::Emdb;

let db = Emdb::open_in_memory();
db.insert("name", "emdb")?;
assert_eq!(db.get("name")?, Some(b"emdb".to_vec()));
# Ok::<(), emdb::Error>(())
```

## Persistence

```rust
use emdb::{Emdb, FlushPolicy};

let path = std::env::temp_dir().join("app.emdb");

{
    let db = Emdb::builder()
        .path(path.clone())
        .flush_policy(FlushPolicy::EveryN(64))
        .build()?;

    db.insert("user:1", "james")?;
    db.flush()?;
}

let reopened = Emdb::open(&path)?;
assert_eq!(reopened.get("user:1")?, Some(b"james".to_vec()));
# let _cleanup = std::fs::remove_file(path);
# Ok::<(), emdb::Error>(())
```

Manual compaction:

```rust
use emdb::Emdb;

let path = std::env::temp_dir().join("compact.emdb");
let db = Emdb::open(&path)?;
db.insert("k", "v")?;
db.compact()?;
db.flush()?;
# let _cleanup = std::fs::remove_file(path);
# Ok::<(), emdb::Error>(())
```

## Transactions

Commit path:

```rust
use emdb::Emdb;

let db = Emdb::open_in_memory();
db.transaction(|tx| {
    tx.insert("user:1", "james")?;
    tx.insert("user:2", "alex")?;
    Ok(())
})?;

assert_eq!(db.get("user:1")?, Some(b"james".to_vec()));
assert_eq!(db.get("user:2")?, Some(b"alex".to_vec()));
# Ok::<(), emdb::Error>(())
```

Rollback path:

```rust
use emdb::{Emdb, Error};

let db = Emdb::open_in_memory();
let failed = db.transaction::<_, ()>(|tx| {
    tx.insert("temp", "value")?;
    Err(Error::TransactionAborted("rollback"))
});

assert!(failed.is_err());
assert_eq!(db.get("temp")?, None);
# Ok::<(), emdb::Error>(())
```

### Crash Safety

Transactions are written as `BatchBegin ... BatchEnd` records.
If a crash occurs before `BatchEnd`, the entire batch is discarded during
replay. If a crash occurs after `BatchEnd`, the entire batch is applied.

## Features

- `ttl` (default): per-record expiration and default TTL support.
- `nested`: dotted-prefix group operations and `Focus` handles.
- persistence (core): append-only file log, replay-on-open, flush policy,
  and compaction.
- transactions (core): closure-based atomic batches with read-your-writes
    and crash-safe replay.

## Concurrency

`Emdb` is `Send + Sync` and cheap to clone. Internally it uses a 32-shard
lock-striped primary index so reads on different keys never block each other,
plus a serialized backend mutex for the WAL and page file. In-memory
databases bypass the backend mutex entirely.

```rust
use std::sync::Arc;
use std::thread;

use emdb::Emdb;

let db = Arc::new(Emdb::open_in_memory());
db.insert("counter", "0")?;

let mut workers = Vec::new();
for i in 0_u32..4 {
    let db = Arc::clone(&db);
    workers.push(thread::spawn(move || {
        let _ = db.insert(format!("k{i}"), format!("v{i}"));
    }));
}

for worker in workers {
    let _ = worker.join();
}

assert!(db.len()? >= 4);
# Ok::<(), emdb::Error>(())
```

### TTL Example

```rust
# #[cfg(feature = "ttl")]
# {
use std::time::Duration;

use emdb::{Emdb, Ttl};

let db = Emdb::builder()
    .default_ttl(Duration::from_secs(30))
    .build()?;
db.insert_with_ttl("session", "token", Ttl::Default)?;
assert!(db.ttl("session")?.is_some());
# }
# Ok::<(), emdb::Error>(())
```

### Nested Example

```rust
# #[cfg(feature = "nested")]
# {
use emdb::Emdb;

let db = Emdb::open_in_memory();
let product = db.focus("product");
product.set("name", "phone")?;
product.set("price", "799")?;

assert_eq!(product.get("name")?, Some(b"phone".to_vec()));
assert_eq!(db.group("product")?.count(), 2);
# }
# Ok::<(), emdb::Error>(())
```

## Goals

- **Embedded-first** — runs in-process; no separate server, no network.
- **High performance** — zero-copy reads, allocation-free hot paths, cache-friendly layout.
- **Safe** — strict `clippy` profile, no `unwrap` in library code, all `unsafe` documented.
- **Small footprint** — minimal dependency graph, fast compile times.
- **Portable** — Linux, macOS, Windows (x86_64 and ARM64).

## Benchmarking

emdb ships with Criterion benchmarks, including an optional comparative suite.

- Core benches: [benches/kv.rs]benches/kv.rs, [benches/persistence.rs]benches/persistence.rs, [benches/transactions.rs]benches/transactions.rs, [benches/concurrency.rs]benches/concurrency.rs
- Comparative bench: [benches/comparative.rs]benches/comparative.rs

Quick start:

```powershell
cargo bench --bench comparative
```

Compare with embedded DBs (sled + redb):

```powershell
cargo bench --bench comparative --features bench-compare
```

Compare with RocksDB (optional):

```powershell
cargo bench --bench comparative --features bench-rocksdb
```

Compare with Redis (optional):

```powershell
$env:EMDB_REDIS_URL = "redis://127.0.0.1/"
cargo bench --bench comparative --features bench-redis
```

For full benchmark workflow, tuning, and reporting format, see [docs/BENCH.md](docs/BENCH.md).
The latest recorded baseline metrics are also tracked there.

## Non-Goals

- Client-server operation (use a dedicated DBMS for that).
- A full SQL dialect at this stage.
- Distributed replication at this stage.

## Related Projects

`emdb` is the Rust implementation. Implementations in other languages (Go, C, and others) are planned and will live under their own repositories.

## License

Licensed under the [Apache License, Version 2.0](./LICENSE).

Copyright &copy; 2026 James Gober.