Zurück zum Ranking

fjall-rs/fjall

Rustfjall-rs.github.io

🗻 Log-structured, embeddable key-value storage engine written in Rust

databaselsmlsm-treelsmtrustrust-langstorage-engineembedded-databaseembedded-kvkvkv-databasekv-storage
Sterne-Wachstum
Sterne
2.2k
Forks
107
Wochenwachstum
Issues
26
1k2k
Dez. 2023Okt. 2024Sept. 2025Juli 2026
Artefaktecrates.iocargo add fjall
README

CI docs.rs Crates.io MSRV dependency status

Discord Bluesky

Fjall (Nordic: "Mountain") is a log-structured, embeddable key-value storage engine written in Rust. It features:

  • A thread-safe BTreeMap-like API
  • 100% safe & stable Rust
  • LSM-tree-based storage similar to RocksDB
  • Range & prefix searching with forward and reverse iteration
  • Multiple keyspaces (a.k.a. column families) with cross-keyspace atomic semantics
  • Built-in compression (default = LZ4)
  • Serializable transactions (optional)
  • Key-value separation for large blob use cases (optional)
  • Custom compaction filters to run custom logic during compactions (optional)
  • Automatic background maintenance

It is not:

  • A standalone database server
  • A relational or wide-column database: it has no built-in notion of columns or query language

Sponsors

Orbitinghail

Basic usage

cargo add fjall
use fjall::{Database, KeyspaceCreateOptions, PersistMode};

fn main() -> fjall::Result<()> {
    // A database may contain multiple keyspaces
    // You should probably only use a single database for your application
    let db = Database::builder(path).open()?;
    // TxDatabase::builder for transactional semantics

    // Each keyspace is its own physical LSM-tree, and thus isolated from other keyspaces
    let items = db.keyspace("my_items", KeyspaceCreateOptions::default)?;

    // Write some data
    items.insert("a", "hello")?;

    // And retrieve it
    let bytes = items.get("a")?;

    // Or remove it again
    items.remove("a")?;

    // Search by prefix
    for kv in items.prefix("prefix") {
        // ...
    }

    // Search by range
    for kv in items.range("a"..="z") {
        // ...
    }

    // Iterators implement DoubleEndedIterator, so you can search backwards, too!
    for kv in items.prefix("prefix").rev() {
        // ...
    }

    // Sync the journal to disk to make sure data is definitely durable
    // When the database is dropped, it will try to persist with `PersistMode::SyncAll` automatically
    db.persist(PersistMode::SyncAll)
}

[!TIP] Like any typical key-value store, keys are stored in lexicographic order. If you are storing integer keys (e.g. timeseries data), you should use the big endian form to have predictable ordering.

Durability

To support different kinds of workloads, Fjall is agnostic about the type of durability your application needs. After writing data (insert, remove or committing a write batch/transaction), you can choose to call Database::persist which takes a PersistMode parameter. By default, any operation will flush to OS buffers, but not to disk. This matches RocksDB's default durability. Also, when dropped, the database will try to persist the journal to disk synchronously.

Multithreading, Async and Multiprocess

[!WARNING] A single database may not be loaded in parallel from separate processes.

Fjall is internally synchronized for multi-threaded access, so you can clone around the Database and Keyspaces as needed, without needing to lock yourself.

For an async example, see the tokio example.

Memory usage

Generally, memory for loaded data, indexes etc. is managed on a per-block basis, and capped by the block cache capacity. Note that this also applies to returned values: When you hold a Slice, it keeps the backing buffer alive (which may be a block). If you know that you are going to keep a value around for a long time, you may want to copy it out into a new Vec<u8>, Box<[u8]>, Arc<[u8]> or new Slice (using Slice::new).

[!NOTE] It is recommended to configure the block cache capacity to be ~20-25% of the available memory - or more if the data set fits fully into memory.

Additionally, orthogonally to the block cache, each Keyspace has its own write buffer ("Memtable") which is the unit of data flushed back into the "proper" index structure.

Error handling

Fjall returns an error enum, however these variants are mostly used for debugging and tracing purposes, so your application is not expected to handle specific errors.

It's best to let the application crash and restart, which is the safest way to recover from transient I/O errors.

Transactional modes

The backing store (lsm-tree) is a MVCC key-value store, allowing repeatable snapshot reads. However this isolation level can not do read-modify-write operations without the chance of lost updates. Also, WriteBatch does not allow reading the intermediary state back as you would expect from a proper transaction. For that reason, if you need transactional semantics, you need to use one of the transactional database implementation (OptimisticTxDatabase or SingleWriterTxDatabase).

TL;DR: Fjall supports both transactional and non-transactional workloads. Chances are you want to use a transactional database, unless you know your workload does not need serializable transaction semantics.

Single writer

Opens a transactional database for single-writer (serialized) transactions. Single writer means only a single write transaction can run at a time. This is trivially serializable because it literally serializes write transactions.

Optimistic

Opens a transactional database for multi-writer, serializable transactions. Conflict checking is done using optimistic concurrency control, meaning transactions can conflict and may have to be rerun.

Feature flags

lz4

Allows using LZ4 compression, powered by lz4_flex.

Enabled by default.

bytes_1

Uses bytes 1.x as the underlying Slice type. Otherwise, byteview is used instead.

Disabled by default.

Stable disk format

Future breaking changes will result in a major version bump and a migration path.

For the underlying LSM-tree implementation, see: https://crates.io/crates/lsm-tree.

Examples

See here for practical examples.

Contributing

How can you help?

License

All source code is licensed under MIT OR Apache-2.0.

All contributions are to be licensed as MIT OR Apache-2.0.

Ähnliche Repositories
supabase/supabase

The Postgres development platform. Supabase gives you a dedicated Postgres database to build your web, mobile, and AI applications.

TypeScriptnpmApache License 2.0firebasesupabase
supabase.com
106.8k13.2k
netdata/netdata

The fastest path to AI-powered full stack observability, even for lean teams.

GoGo ModulesGNU General Public License v3.0monitoringdocker
netdata.cloud
79.8k6.5k
redis/redis

For developers, who are building real-time data-driven applications, Redis is the preferred, fastest, and most feature-rich cache, data structure server, and document and vector query engine.

COtherdatabasekey-value
redis.io
75.6k24.7k
Asabeneh/30-Days-Of-Python

The 30 Days of Python programming challenge is a step-by-step guide to learn the Python programming language in 30 days. This challenge may take more than 100 days. Follow your own pace. These videos may help too: https://www.youtube.com/channel/UC7PNRuno1rzYPb1xLa4yktw

PythonPyPI30-days-of-pythonpython
68.8k12.8k
meilisearch/meilisearch

A lightning-fast search engine API bringing AI-powered hybrid search to your sites and applications.

Rustcrates.ioOthersearch-enginetypo-tolerance
meilisearch.com
58.7k2.6k
etcd-io/etcd

Distributed reliable key-value store for the most critical data of a distributed system

GoGo ModulesApache License 2.0etcdraft
etcd.io
52k10.4k
dbeaver/dbeaver

Free universal database tool and SQL client

JavaMavenApache License 2.0sqldatabase
dbeaver.io
51.1k4.3k
ClickHouse/ClickHouse

ClickHouse® is a real-time analytics database management system

C++Apache License 2.0dbmsolap
clickhouse.com
48.8k8.7k
metabase/metabase

The easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:

ClojureOtheranalyticsbusinessintelligence
metabase.com
48.3k6.7k
prisma/prisma

Next-generation ORM for Node.js & TypeScript | PostgreSQL, MySQL, MariaDB, SQL Server, SQLite, MongoDB and CockroachDB

TypeScriptnpmApache License 2.0prismaorm
prisma.io
47.4k2.4k
LeCoupa/awesome-cheatsheets

👩‍💻👨‍💻 Awesome cheatsheets for popular programming languages, frameworks and development tools. They include everything you should know in one single file.

JavaScriptnpmMIT Licensecheatsheetsjavascript
lecoupa.github.io/awesome-cheatsheets/
46.2k6.7k
pingcap/tidb

TiDB is built for agentic workloads that grow unpredictably, with ACID guarantees and native support for transactions, analytics, and vector search. No data silos. No noisy neighbors. No infrastructure ceiling.

GoGo ModulesApache License 2.0distributed-databasedistributed-transactions
tidb.io
40.3k6.2k