vorot93/libmdbx-rs

Rust bindings for MDBX

C

101

570 commits

updated Sep 24, 2026

See the code

README

libmdbx-rs

Idiomatic, safe Rust bindings for libmdbx, an embedded key-value store.

The crate wraps the vendored C library (mdbx-sys) behind a Send + Sync transaction API. An optional typed ORM lives under libmdbx::orm.

Documentation · Repository

The crate is pre-1.0: breaking changes are called out in CHANGELOG.md.

Build requirements

Building compiles the vendored libmdbx C sources and generates FFI bindings:

  • A C compiler (any toolchain supported by the cc crate).
  • libclang for bindgen (on Windows, point LIBCLANG_PATH at your LLVM installation).

Rust: latest stable (edition 2024).

Usage

The unnamed table needs no extra options:

use libmdbx::{Database, NoWriteMap, WriteFlags};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let path = std::env::temp_dir().join("libmdbx-demo");
    let db = Database::<NoWriteMap>::open(&path)?;

    let txn = db.begin_rw_txn()?;
    let table = txn.create_table(None, Default::default())?;
    txn.put(&table, b"cat", b"meow", WriteFlags::UPSERT)?;
    txn.commit()?;

    let txn = db.begin_ro_txn()?;
    let table = txn.open_table(None)?;
    let value = txn.get::<Vec<u8>>(&table, b"cat")?.unwrap();
    assert_eq!(value, b"meow");

    Ok(())
}

Named tables need slots reserved at open (max_tables defaults to 0). Without that, open_table / create_table fail with Error::DbsFull:

use libmdbx::{Database, DatabaseOptions, NoWriteMap};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let db = Database::<NoWriteMap>::open_with_options(
        "mydb",
        DatabaseOptions {
            max_tables: Some(4),
            ..Default::default()
        },
    )?;
    let txn = db.begin_rw_txn()?;
    txn.create_table(Some("pets"), Default::default())?;
    txn.commit()?;
    Ok(())
}

Walk a table with [Cursor]. Reads in a read-only transaction can be zero-copy (Cow<[u8]>); read-write transactions always copy, because libmdbx may relocate pages on a later write.

Database is generic over the write path:

  • [NoWriteMap] — modified pages are buffered and written through file I/O.
  • [WriteMap] — writes go through the memory map (typically faster). The ORM defaults to this.

Logging

libmdbx's own diagnostics are forwarded to the log crate under the libmdbx target (they are never printed to stderr). Install any log backend to see them, e.g. with RUST_LOG=libmdbx=info for env_logger.

ORM

Enable the orm feature and see libmdbx::orm. Declare tables with table! / dupsort!, assemble a DatabaseChart, and use typed get / upsert / cursors. cbor adds serde-via-CBOR table objects.

Features

FeatureDescription
ormTyped table mapping (libmdbx::orm).
cborAny serde type as an ORM key/value via CBOR (cbor_table_object!, ciborium). Implies orm.
bytesbytes::Bytes as a decoded value for core reads (copied), and as an ORM key/value.
lifetimed-bytesZero-copy lifetime-carrying Bytes<'tx> handles for core transaction reads.

FFI crate

mdbx-sys is the raw bindgen crate. This workspace pins it exactly (=) so the wrapper and FFI crate always match.

License

Apache License 2.0. See LICENSE.

mdbx

Contributors

vorot93

268 commits

danburkert

107 commits

mykmelez

98 commits

victorporof

48 commits

vorot93/libmdbx-rs

Rust bindings for MDBX

C

101

570 commits

updated Sep 24, 2026

See the code

README

libmdbx-rs

Idiomatic, safe Rust bindings for libmdbx, an embedded key-value store.

The crate wraps the vendored C library (mdbx-sys) behind a Send + Sync transaction API. An optional typed ORM lives under libmdbx::orm.

Documentation · Repository

The crate is pre-1.0: breaking changes are called out in CHANGELOG.md.

Build requirements

Building compiles the vendored libmdbx C sources and generates FFI bindings:

  • A C compiler (any toolchain supported by the cc crate).
  • libclang for bindgen (on Windows, point LIBCLANG_PATH at your LLVM installation).

Rust: latest stable (edition 2024).

Usage

The unnamed table needs no extra options:

use libmdbx::{Database, NoWriteMap, WriteFlags};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let path = std::env::temp_dir().join("libmdbx-demo");
    let db = Database::<NoWriteMap>::open(&path)?;

    let txn = db.begin_rw_txn()?;
    let table = txn.create_table(None, Default::default())?;
    txn.put(&table, b"cat", b"meow", WriteFlags::UPSERT)?;
    txn.commit()?;

    let txn = db.begin_ro_txn()?;
    let table = txn.open_table(None)?;
    let value = txn.get::<Vec<u8>>(&table, b"cat")?.unwrap();
    assert_eq!(value, b"meow");

    Ok(())
}

Named tables need slots reserved at open (max_tables defaults to 0). Without that, open_table / create_table fail with Error::DbsFull:

use libmdbx::{Database, DatabaseOptions, NoWriteMap};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let db = Database::<NoWriteMap>::open_with_options(
        "mydb",
        DatabaseOptions {
            max_tables: Some(4),
            ..Default::default()
        },
    )?;
    let txn = db.begin_rw_txn()?;
    txn.create_table(Some("pets"), Default::default())?;
    txn.commit()?;
    Ok(())
}

Walk a table with [Cursor]. Reads in a read-only transaction can be zero-copy (Cow<[u8]>); read-write transactions always copy, because libmdbx may relocate pages on a later write.

Database is generic over the write path:

  • [NoWriteMap] — modified pages are buffered and written through file I/O.
  • [WriteMap] — writes go through the memory map (typically faster). The ORM defaults to this.

Logging

libmdbx's own diagnostics are forwarded to the log crate under the libmdbx target (they are never printed to stderr). Install any log backend to see them, e.g. with RUST_LOG=libmdbx=info for env_logger.

ORM

Enable the orm feature and see libmdbx::orm. Declare tables with table! / dupsort!, assemble a DatabaseChart, and use typed get / upsert / cursors. cbor adds serde-via-CBOR table objects.

Features

FeatureDescription
ormTyped table mapping (libmdbx::orm).
cborAny serde type as an ORM key/value via CBOR (cbor_table_object!, ciborium). Implies orm.
bytesbytes::Bytes as a decoded value for core reads (copied), and as an ORM key/value.
lifetimed-bytesZero-copy lifetime-carrying Bytes<'tx> handles for core transaction reads.

FFI crate

mdbx-sys is the raw bindgen crate. This workspace pins it exactly (=) so the wrapper and FFI crate always match.

License

Apache License 2.0. See LICENSE.

mdbx

Contributors

vorot93

268 commits

danburkert

107 commits

mykmelez

98 commits

victorporof

48 commits

Languages

C

69.1%

C++

21.4%

Rust

9.5%