What this package is like to depend on
Last release 6 days ago
17 Aug 2026
Release timing varies
gaps range from 8 days to 5 months
Most releases are documented
notes for 62 of 72 stable releases
2 versions withdrawn
withdrawn after publishing
8 years old
75 releases · first in 2018
8 releases in the last 12 months
see the full history below
Release timeline
75 releases · Sep 2018 to Aug 2026Releases
latest 60 of 75-
4.2.017 Aug 2026Release notes
Open source →New features
- Add an experimental cursor API, behind the
experimental_cursorfeature flag:
Table::lower_bound_mut()andTable::upper_bound_mut()return aCursorMutpointing at a gap
between entries, modeled on the standard library'sBTreeMapcursors. Inserting sorted data
through itsinsert_before()method can be around 3x faster than callinginsert()with the
same data;insert_after()inserts through the gap in descending order at the same speed.
ReadableTable::lower_bound()andReadableTable::upper_bound()return a read-onlyCursor.
The feature is unstable and may change incompatibly, or be removed, in any release. - Add
ReadOnlyTable::get_owned(),ReadOnlyTable::range_owned(),
ReadOnlyMultimapTable::get_owned(), andReadOnlyMultimapTable::range_owned(), which
return the newOwnedAccessGuard,OwnedRange,OwnedMultimapValue, and
OwnedMultimapRangetypes. These keep the read transaction alive until they are dropped,
including the guards yielded by the iterators, which may outlive the iterator that produced
them. - Add
Table::entry()and the associatedEntry,OccupiedEntry, andVacantEntry
types, mirroringstd::collections::BTreeMap::entry. Supportsor_insert,
or_insert_with,or_insert_with_key,and_modify, and the usualOccupiedEntry
/VacantEntryaccessors. - Add
ExtractIf::close()to explicitly finalize an extract iterator without removing unread
entries.
Optimizations
- Improve write performance:
Durability::Nonecommits are about 2x faster, and writes that do not
split a page are about 15% faster for single-keyDurability::Nonecommits and about 6% faster
for batched writes. - Improve write performance when tables of a single
WriteTransactionare modified concurrently
from multiple threads. Writes to separate tables previously serialized on internal locks and
could be slower than writing from a single thread; they now scale with the number of threads.
Up to about 4x faster. - Optimize
Table::pop_first()andTable::pop_last()to be about 2x faster. - Optimize inserting in ascending key order. A table loaded in key order occupies about half as
much space, and loads faster. - Optimize
Table::retain(),Table::retain_in(),Table::extract_if(), and
Table::extract_from_if(). Benchmarks on large tables show a 30-100x speedup for retaining and
an 18-65x speedup for extracting, depending on the fraction of entries affected. Iterating an
extract iterator from both ends no longer degrades removal batching. - Avoid unnecessary write amplification when removing a value that is not present from a multimap
table. Such a removal is now a no-op.
Minor improvements
Table::retain(),Table::retain_in(),Table::extract_if(), andTable::extract_from_if()
now poison the write transaction if their predicate panics or an internal error prevents
removals from being applied, causingWriteTransaction::commit()to return
CommitError::TransactionPoisoned. After an extract iterator returns an error, later calls keep
returning an error instead of continuing.- Enable file space reclamation during non-durable transactions performed while a savepoint exists.
- Reuse pages freed by a durable write transaction in the next write transaction when no live read
transaction or savepoint still needs them. Previously, pages were not reused for one additional
transaction. compact()now returnsCompactionError::PersistentSavepointExistsor
CompactionError::EphemeralSavepointExistsinstead of the misleading
CompactionError::TransactionInProgresswhen a savepoint blocks compaction.StorageBackend::close()is now called when opening a database fails and when an I/O error occurs
while dropping aDatabase, allowing backends to release their resources on both paths.
Bug fixes
- Return
StorageError::Corruptedinstead of panicking when opening or repairing a database with a
corrupted persistent savepoint record or malformed freed-page record. - Return
StorageError::Corruptedinstead of aborting the process when branch pages form a cycle or
arbitrarily long chain, or when a corrupted page number could cause a multi-terabyte allocation. - Fix
WriteTransaction::stats()returning garbage statistics, or panicking when debug assertions
are enabled, when called while a table is open and modified in the same transaction. - Fix a deadlock when a
Databasewas dropped while aWriteTransactionwas live. A live
WriteTransactionnow keeps the database open: the transaction remains usable after the
Databaseis dropped, and the database closes when the transaction commits, aborts, or is
dropped. - Fix a panic, including one raised while dropping a
Database, aftercheck_integrity()returned
an error. Such a database now refuses to begin a write transaction or to re-run the check,
returningStorageError::Corrupted, and is no longer recorded as cleanly shut down. - Harden against errors and panics raised part way through
WriteTransaction::commit(): the
database now refuses further write transactions until it is closed and reopened (which
repairs it), instead of risking corruption from continued use after the failed commit. - Fix a case where
check_integrity()failed to repair the database when the table length was
corrupted. Such a file previously passed the check and then panicked, including from
Database::drop. - Fix a potential deadlock when removing a value from a multimap table causes its value-set to
shrink from a subtree back to inline storage, while another table of the same write transaction
is used concurrently from a different thread. - Fix crashes while growing or resizing the database file that could leave it permanently
unopenable or reported as corrupted on subsequent opens, even though every committed transaction
was intact and fully recoverable. - Fix cases where the database file could grow instead of reusing freed space, and where
compact()could grow the file or stop before fully shrinking it. - Fix
Table::get_mut()andEntry::and_modify()to enforce the maximum value size limit.
Previously these paths could bypass the limit thatTable::insert()and theentry()accessors
enforce. - Fix a panic in
insert()when a single leaf page accumulated 65536 entries via in-place
appends, e.g. by inserting a large value and then many small values in ascending key order
within the same transaction. - Fix
check_integrity()incorrectly reporting a healthy database as corrupted (and panicking
in debug builds) after a persistent savepoint was deleted or restored, or when an ephemeral
Savepointwas dropped from another thread while the same write transaction was committing. - Fix a leak of database space when an ephemeral
Savepointwas created from one thread while the
same write transaction was first accessing a table from another thread, and that savepoint was
later restored. The leaked space was only reclaimed by a full repair. - Fix a panic when opening a database file that was externally extended to an invalid size; such
files are now rejected withStorageError::Corrupted. - Fix a hang on Windows when opening a truncated or corrupt database file. Reads past the end of the
file now return an error instead of looping forever. - Fix
check_integrity()so that it now returnsDatabaseError::TransactionInProgresswhen an
ephemeralSavepointis still alive. Previously the check could invalidate the pages such a
savepoint referenced while leaving it marked valid, so restoring it afterward could corrupt the
database. - Fix
Database::check_integrity()silently discarding transactions committed with
Durability::Nonethat had not yet been made durable by a later commit; a passing check now
preserves them (making them durable) instead of rolling them back. - Fix a bug that could silently roll back or corrupt durably committed transactions if a crash
occurred while recovering from an earlier crash. Triggering it required two crashes -- one
interrupting a commit and another during the subsequent repair on the next open -- and it did
not affect transactions committed with two-phase commit. - Fix new composite types (
Option,Vec, tuples, and arrays) of a user-defined type sharing a
type identity with the same composite of a built-in type when the two happened to have the same
name. A table using such a composite of a user type can no longer be silently opened under the
built-in composite (and vice versa); the mismatch is now reported asTableError::TableTypeMismatch.
Existing databases created by older versions remain readable. If an older database already used
such a colliding composite name, its stored type identity remains ambiguous and may still open
under either spelling.
Release notes
Open source →New features
- Add an experimental cursor API, behind the
experimental_cursorfeature flag:Table::lower_bound_mut()andTable::upper_bound_mut()return aCursorMutpointing at a gap between entries, modeled on the standard library'sBTreeMapcursors. Inserting sorted data through itsinsert_before()method can be around 3x faster than callinginsert()with the same data;insert_after()inserts through the gap in descending order at the same speed.ReadableTable::lower_bound()andReadableTable::upper_bound()return a read-onlyCursor. The feature is unstable and may change incompatibly, or be removed, in any release. - Add
ReadOnlyTable::get_owned(),ReadOnlyTable::range_owned(),ReadOnlyMultimapTable::get_owned(), andReadOnlyMultimapTable::range_owned(), which return the newOwnedAccessGuard,OwnedRange,OwnedMultimapValue, andOwnedMultimapRangetypes. These keep the read transaction alive until they are dropped, including the guards yielded by the iterators, which may outlive the iterator that produced them. - Add
Table::entry()and the associatedEntry,OccupiedEntry, andVacantEntrytypes, mirroringstd::collections::BTreeMap::entry. Supportsor_insert,or_insert_with,or_insert_with_key,and_modify, and the usualOccupiedEntry/VacantEntryaccessors. - Add
ExtractIf::close()to explicitly finalize an extract iterator without removing unread entries.
Optimizations
- Improve write performance:
Durability::Nonecommits are about 2x faster, and writes that do not split a page are about 15% faster for single-keyDurability::Nonecommits and about 6% faster for batched writes. - Improve write performance when tables of a single
WriteTransactionare modified concurrently from multiple threads. Writes to separate tables previously serialized on internal locks and could be slower than writing from a single thread; they now scale with the number of threads. Up to about 4x faster. - Optimize
Table::pop_first()andTable::pop_last()to be about 2x faster. - Optimize inserting in ascending key order. A table loaded in key order occupies about half as much space, and loads faster.
- Optimize
Table::retain(),Table::retain_in(),Table::extract_if(), andTable::extract_from_if(). Benchmarks on large tables show a 30-100x speedup for retaining and an 18-65x speedup for extracting, depending on the fraction of entries affected. Iterating an extract iterator from both ends no longer degrades removal batching. - Avoid unnecessary write amplification when removing a value that is not present from a multimap table. Such a removal is now a no-op.
Minor improvements
Table::retain(),Table::retain_in(),Table::extract_if(), andTable::extract_from_if()now poison the write transaction if their predicate panics or an internal error prevents removals from being applied, causingWriteTransaction::commit()to returnCommitError::TransactionPoisoned. After an extract iterator returns an error, later calls keep returning an error instead of continuing.- Enable file space reclamation during non-durable transactions performed while a savepoint exists.
- Reuse pages freed by a durable write transaction in the next write transaction when no live read transaction or savepoint still needs them. Previously, pages were not reused for one additional transaction.
compact()now returnsCompactionError::PersistentSavepointExistsorCompactionError::EphemeralSavepointExistsinstead of the misleadingCompactionError::TransactionInProgresswhen a savepoint blocks compaction.StorageBackend::close()is now called when opening a database fails and when an I/O error occurs while dropping aDatabase, allowing backends to release their resources on both paths.
Bug fixes
- Return
StorageError::Corruptedinstead of panicking when opening or repairing a database with a corrupted persistent savepoint record or malformed freed-page record. - Return
StorageError::Corruptedinstead of aborting the process when branch pages form a cycle or arbitrarily long chain, or when a corrupted page number could cause a multi-terabyte allocation. - Fix
WriteTransaction::stats()returning garbage statistics, or panicking when debug assertions are enabled, when called while a table is open and modified in the same transaction. - Fix a deadlock when a
Databasewas dropped while aWriteTransactionwas live. A liveWriteTransactionnow keeps the database open: the transaction remains usable after theDatabaseis dropped, and the database closes when the transaction commits, aborts, or is dropped. - Fix a panic, including one raised while dropping a
Database, aftercheck_integrity()returned an error. Such a database now refuses to begin a write transaction or to re-run the check, returningStorageError::Corrupted, and is no longer recorded as cleanly shut down. - Harden against errors and panics raised part way through
WriteTransaction::commit(): the database now refuses further write transactions until it is closed and reopened (which repairs it), instead of risking corruption from continued use after the failed commit. - Fix a case where
check_integrity()failed to repair the database when the table length was corrupted. Such a file previously passed the check and then panicked, including fromDatabase::drop. - Fix a potential deadlock when removing a value from a multimap table causes its value-set to shrink from a subtree back to inline storage, while another table of the same write transaction is used concurrently from a different thread.
- Fix crashes while growing or resizing the database file that could leave it permanently unopenable or reported as corrupted on subsequent opens, even though every committed transaction was intact and fully recoverable.
- Fix cases where the database file could grow instead of reusing freed space, and where
compact()could grow the file or stop before fully shrinking it. - Fix
Table::get_mut()andEntry::and_modify()to enforce the maximum value size limit. Previously these paths could bypass the limit thatTable::insert()and theentry()accessors enforce. - Fix a panic in
insert()when a single leaf page accumulated 65536 entries via in-place appends, e.g. by inserting a large value and then many small values in ascending key order within the same transaction. - Fix
check_integrity()incorrectly reporting a healthy database as corrupted (and panicking in debug builds) after a persistent savepoint was deleted or restored, or when an ephemeralSavepointwas dropped from another thread while the same write transaction was committing. - Fix a leak of database space when an ephemeral
Savepointwas created from one thread while the same write transaction was first accessing a table from another thread, and that savepoint was later restored. The leaked space was only reclaimed by a full repair. - Fix a panic when opening a database file that was externally extended to an invalid size; such
files are now rejected with
StorageError::Corrupted. - Fix a hang on Windows when opening a truncated or corrupt database file. Reads past the end of the file now return an error instead of looping forever.
- Fix
check_integrity()so that it now returnsDatabaseError::TransactionInProgresswhen an ephemeralSavepointis still alive. Previously the check could invalidate the pages such a savepoint referenced while leaving it marked valid, so restoring it afterward could corrupt the database. - Fix
Database::check_integrity()silently discarding transactions committed withDurability::Nonethat had not yet been made durable by a later commit; a passing check now preserves them (making them durable) instead of rolling them back. - Fix a bug that could silently roll back or corrupt durably committed transactions if a crash occurred while recovering from an earlier crash. Triggering it required two crashes -- one interrupting a commit and another during the subsequent repair on the next open -- and it did not affect transactions committed with two-phase commit.
- Fix new composite types (
Option,Vec, tuples, and arrays) of a user-defined type sharing a type identity with the same composite of a built-in type when the two happened to have the same name. A table using such a composite of a user type can no longer be silently opened under the built-in composite (and vice versa); the mismatch is now reported asTableError::TableTypeMismatch. Existing databases created by older versions remain readable. If an older database already used such a colliding composite name, its stored type identity remains ambiguous and may still open under either spelling.
- Add an experimental cursor API, behind the
-
4.1.019 Apr 2026Release notes
Open source →This release contains a large number of bug fixes discovered by AI coding agents
- Fix a bug where
MultimapValue::len()andis_empty()returned stale counts after
consuming entries vianext_back(). - Fix a bug where
restore_savepoint()used in a non-Immediatedurability transaction and when
there are persistent savepoints newer than the one being restored, could fail
withSavepointError::InvalidSavepoint, but the savepoint would actually be partially applied.
The call now fails up front withSavepointError::ImmediateDurabilityRequired. - Fix a bug in
restore_savepoint()where modifications made earlier in the transaction might
not be reverted. - Fix a bug where renaming a table that was already modified in the same transaction could cause
the database to become corrupted. - Fix a bug where calling
restore_savepoint()after modifying a table in the same
transaction could cause the table to become corrupted in a future transaction. - Fix a panic when
delete_table()was called on a table that had been modified in the same
transaction. - Fix a panic in
restore_savepoint()when passed aSavepointfrom a differentDatabase.
SavepointError::InvalidSavepointis now returned instead. - Fix a bug where a transaction that created a persistent savepoint and was then
aborted could cause the database file to grow excessively, until theDatabasewas dropped. - Fix a panic in
check_integrity()when called while another transaction is still alive.
DatabaseError::TransactionInProgressis now returned instead. - Fix a bug where aborting a transaction that called
restore_savepoint()with a savepoint
when a newer savepoint existed could cause database space to be leaked. - Fix a bug where aborting a transaction that called
restore_savepoint()would leave more
recent savepoints invalid. - Improve performance when reading concurrently from multiple threads. Around 15% speedup on some benchmarks.
- Optimize cache usage, and general write performance. Around 1.5x speedup on some benchmarks.
- Optimize memory usage.
- Other performance optimizations.
Release notes
Open source →This release contains a large number of bug fixes discovered by AI coding agents
- Fix a bug where
MultimapValue::len()andis_empty()returned stale counts after consuming entries vianext_back(). - Fix a bug where
restore_savepoint()used in a non-Immediatedurability transaction and when there are persistent savepoints newer than the one being restored, could fail withSavepointError::InvalidSavepoint, but the savepoint would actually be partially applied. The call now fails up front withSavepointError::ImmediateDurabilityRequired. - Fix a bug in
restore_savepoint()where modifications made earlier in the transaction might not be reverted. - Fix a bug where renaming a table that was already modified in the same transaction could cause the database to become corrupted.
- Fix a bug where calling
restore_savepoint()after modifying a table in the same transaction could cause the table to become corrupted in a future transaction. - Fix a panic when
delete_table()was called on a table that had been modified in the same transaction. - Fix a panic in
restore_savepoint()when passed aSavepointfrom a differentDatabase.SavepointError::InvalidSavepointis now returned instead. - Fix a bug where a transaction that created a persistent savepoint and was then
aborted could cause the database file to grow excessively, until the
Databasewas dropped. - Fix a panic in
check_integrity()when called while another transaction is still alive.DatabaseError::TransactionInProgressis now returned instead. - Fix a bug where aborting a transaction that called
restore_savepoint()with a savepoint when a newer savepoint existed could cause database space to be leaked. - Fix a bug where aborting a transaction that called
restore_savepoint()would leave more recent savepoints invalid. - Improve performance when reading concurrently from multiple threads. Around 15% speedup on some benchmarks.
- Optimize cache usage, and general write performance. Around 1.5x speedup on some benchmarks.
- Optimize memory usage.
- Other performance optimizations.
- Fix a bug where
-
4.0.002 Apr 2026Release notes
Open source →- Implement
DroponAccessGuardMutandAccessGuardMutInPlace, which requires that these be dropped
before theTablethey borrow from.
This fixes a critical bug where the accessor could outlive theTable, and be dropped after the
transaction had already committed. This could cause data loss due to the data in the accessor
being written out after the transaction had already completed. - Remove
Legacytype. To migrate off theLegacytype, use theLegacytype in the 3.x release
and copy the data to a table with plain tuples, before upgrading to the 4.x release.
Release notes
Open source →- Implement
DroponAccessGuardMutandAccessGuardMutInPlace, which requires that these be dropped before theTablethey borrow from. This fixes a critical bug where the accessor could outlive theTable, and be dropped after the transaction had already committed. This could cause data loss due to the data in the accessor being written out after the transaction had already completed. - Remove
Legacytype. To migrate off theLegacytype, use theLegacytype in the 3.x release and copy the data to a table with plain tuples, before upgrading to the 4.x release.
- Implement
-
3.1.302 Apr 2026Release notes
Open source →- Fix a data loss bug which can occur when the guard returned from
Table::get_mut()is dropped
after the transaction has been committed. - Add a warning to
Table::insert_reserve()indicating that it can cause data loss and recommending
to upgrade to the 4.0.0 release.
Release notes
Open source →- Fix a data loss bug which can occur when the guard returned from
Table::get_mut()is dropped after the transaction has been committed. - Add a warning to
Table::insert_reserve()indicating that it can cause data loss and recommending to upgrade to the 4.0.0 release.
- Fix a data loss bug which can occur when the guard returned from
-
3.1.201 Apr 2026 -
3.1.108 Mar 2026Release notes
Open source →- Fix panic which could occur when inserting into a table with fixed size keys when
debug_assertionsare enabled - Add additional information to the stats returned by
cache_stats()
Release notes
Open source →- Fix panic which could occur when inserting into a table with fixed size keys when
debug_assertionsare enabled - Add additional information to the stats returned by
cache_stats()
- Fix panic which could occur when inserting into a table with fixed size keys when
-
3.1.025 Sep 2025Release notes
Open source →- Implement
std::error::ErrorforSetDurabilityError - Fix compilation error on various non-tier-1 platforms, such as wasm32-unknown
Release notes
Open source →- Implement
std::error::ErrorforSetDurabilityError - Fix compilation error on various non-tier-1 platforms, such as wasm32-unknown
- Implement
-
3.0.217 Sep 2025Release notes
Open source →- Fix performance issue where a transaction with a large number of writes would cause
WriteTransaction::abort()and committing non-durable transactions to become slow
Release notes
Open source →- Fix performance issue where a transaction with a large number of writes would cause
WriteTransaction::abort()and committing non-durable transactions to become slow.
- Fix performance issue where a transaction with a large number of writes would cause
-
3.0.123 Aug 2025Release notes
Open source →- Fix correctness issue with
range(),extract_from_if(), andretain_in(). If a RangeBounds
withstart>endwas passed as an argument andstartandendkeys were stored in different
internal pages in the database (i.e. a sufficient condition is that more than 4KiB of key-value
pairs were between the two keys) then these methods would perform as if the argument had been
start.. - Fix performance regression, from redb 2.x, where
Durability::Nonecommits could become linearly
slower during a series of transactions.
Release notes
Open source →- Fix correctness issue with
range(),extract_from_if(), andretain_in(). If a RangeBounds withstart>endwas passed as an argument andstartandendkeys were stored in different internal pages in the database (i.e. a sufficient condition is that more than 4KiB of key-value pairs were between the two keys) then these methods would perform as if the argument had beenstart.. - Fix performance regression, from redb 2.x, where
Durability::Nonecommits could become linearly slower during a series of transactions.
- Fix correctness issue with
-
3.0.009 Aug 2025Release notes
Open source →Removes support for file format v2.
Use
Database::upgrade(), in redb 2.6, to migrate to the v3 file format.General storage optimizations
The v3 file format has been further optimized to reduce the size of the database. Databases with only a few small keys will see the largest benefit, and the minimum size of a database file has decreased from ~2.5MiB to ~50KiB. To achieve the smallest file size call
Database::compact()before dropping theDatabase.Additionally, performance is ~15% better in bulk load benchmarks. This was achieved by implementing a custom hash function for various in-memory
HashSets andHashMaps, and by optimizing the usage of buffers held inArcs to reduce the number of atomic instructions executed.Optimize storage of tuple types
Storage of variable width tuple types with arity greater than 1 is more efficient. The new format elides the length of any fixed width fields and uses varint encoding for the lengths of all variable width fields.
Note that this encoding is not compatible with the serialization of variable width tuples used in prior versions. To load tuple data created prior to version 3.0, wrap them in the
Legacytype. For example,TableDefinition<u64, (&str, u32)>becomesTableDefinition<u64, Legacy<(&str, u32)>>. Fixed width tuples, such as(u32, u64)are backwards compatible.Derive for Key and Value traits
KeyandValuecan be derived using theredb-derivecrate. Note that it does not support schema migration. The recommended pattern to migrate schema is to create a new table, and then perform a migration from the old table to the new table.Read-only multi-process support
Multiple processes may open the same database file for reading by using the new
ReadOnlyDatabasetype. On platforms which support file locks, this acquires a shared lock on the database file.Enable garbage collection in Durability::None transactions
Non-durable transactions will now free pages when possible (pages allocated in a preceding non-durable transaction which are no longer referenced). This resolves an issue where a long sequence of non-durable transactions led to significant growth in the size of the database file. This change increases the RAM required for a sequence of non-durable transactions, such that RAM proportional to the net change in the database is now used. However, it will never use more than about 0.2% of the database file size.
Other changes
- Add
ReadOnlyDatabase - Add
Builder::open_read_only() - Add
StorageBackend::close() - Add
Table::get_mut() - Add
chrono_v0_4feature flag which enables serialization of theNaiveDate,NaiveTime,NaiveDatetime,DateTime<FixedOffset>, andFixedOffsettypes in thechronocrate - Add
uuidfeature flag which enables serialization of theUuidtype in theuuidcrate - Change
StorageBackend::read()to accept a&mut [u8]output argument instead of returning aVec<u8> - Change
Table::insert_reserve()to takeusizeinstead ofu32as the argument type - Change
TypeName::name()to be public - Change
ReadTransactionStillInUseto contain aBox - Change
set_durability()to return aResult - Move
Database::cache_stats()andDatabase::begin_read()toReadableDatabasetrait - Rename
AccessGuardMuttoAccessGuardMutInPlace. Note that a newAccessGuardMutstruct has been added; it serves a different purpose - Remove
Durability::Paranoid - Fix a rare case where
check_integrity()returnedOk(false)even though no repair was required, when called on a database that was not shutdown cleanly and was automatically repaired when opened - Disallow access to the database from read transactions after the
Databaseas been dropped. Access will now returnDatabaseClosed
- Add
-
2.6.323 Aug 2025Release notes
Open source →- Fix correctness issue with
range(),extract_from_if(), andretain_in(). If a RangeBounds
withstart>endwas passed as an argument andstartandendkeys were stored in different
internal pages in the database (i.e. a sufficient condition is that more than 4KiB of key-value
pairs were between the two keys) then these methods would perform as if the argument had been
start..
Release notes
Open source →- Fix correctness issue with
range(),extract_from_if(), andretain_in(). If a RangeBounds withstart>endwas passed as an argument andstartandendkeys were stored in different internal pages in the database (i.e. a sufficient condition is that more than 4KiB of key-value pairs were between the two keys) then these methods would perform as if the argument had beenstart..
- Fix correctness issue with
-
2.6.203 Aug 2025Release notes
Open source →- Forward compatibility improvement which makes the file format more flexible to support a potential future optimization
-
2.6.125 Jul 2025Release notes
Open source →- Fix a forward compatibility issue which caused a crash when opening databases created with redb 3.x. Note that opening 3.x databases with redb 2.x is not generally supported and only works in certain situations.
-
2.6.022 May 2025Release notes
Open source →Add support for the v3 file format.
This file format improves savepoints. Savepoints in the v3 format have constant, and small, overhead. Creating and restoring them is also much faster. The v3 file format also supports savepoints on large databases (v2 has a limit around 32TB). This release creates v2 databases by default. Use
Builder::create_with_file_format_v3()andDatabase::upgrade(), respectively, to enable and migrate to v3.The upcoming 3.0 release will only support the v3 file format.
- Add
Builder::create_with_file_format_v3() - Add
Database::upgrade()
- Add
-
2.5.022 Apr 2025Release notes
Open source →- Add
rename_table()andrename_multimap_table() - Add
KeyandValueimplementations for the unary tuple type (i.e.(T,)) - Fix an issue which could cause a panic when concurrently performing read and write transactions,
when
debug_assertionswere enabled - Optimize
retain()andretain_in()to use less space in the database file - Improve handling of some internal errors to return
LockPoisonedinstead of panicking
- Add
-
2.4.030 Dec 2024Release notes
Open source →- Add
Database::cache_stats() - Fix
open()andcreate()to returnInvalidDatawhen they are called on a database file that is not a valid redb database - Significantly speed up
restore_savepoint(). The time is takes now scales with the change delta since the savepoint was captured, rather than the size of the database file DatabaseStats::fragmented_bytes()is now more accurate
- Add
-
2.3.011 Dec 2024Release notes
Open source →- Add
WriteTransaction::set_two_phase_commit() - Add
WriteTransaction::set_quick_repair()which enables a faster repair mechanism at the cost of slower transaction commits Durability::Paranoidis now deprecated. Useset_two_phase_commit(true)instead- Fix various bugs when repairing the database after an unclean shutdown. These could result in panics, leaked space in the database file, or database corruption
- Add
-
2.2.027 Oct 2024Release notes
Open source →- Implement
TableHandleforReadOnlyTable - Fix bug in write cache, which caused pages to be evicted randomly. Pages are now evicted based on how recently they have been accessed
- Implement
-
2.1.411 Oct 2024Release notes
Open source →- Optimize
first()andlast()to be almost 2x faster - Improve in-memory cache algorithm to resolve edge cases where certain pages could become uncacheable under cache pressure
- Fix bug in read cache where the read cache could become disabled. This was likely to occur in multithreaded workloads when the read cache was smaller than the database file. This bug lead to 5-10x performance degradations for some workloads
- Optimize
-
2.1.314 Sep 2024Release notes
Open source →- Significant performance optimizations to
compact() - Fix some additional cases where
compact()did not fully compact the database - Fix a panic that could occur in
commit()orabort()after an IO error.StorageError::PreviousIois now returned - Fix a potential panic that could occur when repairing the database after a crash
- Significant performance optimizations to
-
2.1.226 Aug 2024Release notes
Open source →Major fixes:
- Fix leak of database space that could occur when calling
restore_savepoint() - Fix leak of database space when calling
delete_multimap_table() - Fix database corruption which could occur when restoring a savepoint. This edge case is rare, and could only occur if the database was less than approximately 4TiB when the savepoint was created, and greater than 4TiB when the savepoint was restored
- Fix edge case where a transient I/O error that occurred during transaction commit, but then did
not reoccur when the
Databasewas dropped, could cause database corruption
Important: If your application has called
restore_savepoint(),delete_multimap_table(), or you suspect it may have experienced a transient I/O error during transaction commit. It is recommended that you runcheck_integrity()after upgrading to this version. This will both detect corruption and clean up any leaked space.Other changes and fixes:
- Optimize page freeing to reduce the size of the database file
- Fix several cases where
check_integrity()would returnOk(false)instead ofOk(true) - Fix some cases where
compact()did not fully compact the database - Make the metadata overhead returned by
WriteTransaction::stats()more accurate - Return
StorageError::ValueTooLargewhen a key-value pair exceeds a total of 3.75GiB. Previously, a panic would occur for key-value pairs that were approximately 4GiB. - Downgrade several
info!log messages todebug! - Improve documentation
- Fix leak of database space that could occur when calling
-
2.1.109 Jun 2024Release notes
Open source →- Fix panic that occurred when calling
compact()when a read transaction was in progress - Fix
ReadTransaction::close()to returnOkwhen it succeeds - Performance optimizations
- Fix panic that occurred when calling
-
2.1.020 Apr 2024Release notes
Open source →- Implement
KeyandValueforString - Allow users to implement
ReadableTableMetadata,ReadableTable, andReadableMultimapTable
- Implement
-
2.0.022 Mar 2024Release notes
Open source →Major file format change
2.0.0 uses a new file format that optimizes
len()to be constant time. This means that it is not backwards compatible with 1.x. To upgrade, consider using a pattern like that shown in the upgrade_v1_to_v2 test.Other changes
check_integrity()now returns aDatabaseErrorinstead of aStorageError- Table metadata methods have moved to a new
ReadableTableMetadatatrait - Rename
RedbKeytoKey - Rename
RedbValuetoValue - Remove lifetimes from read-only tables
- Remove lifetime from
WriteTransactionandReadTransaction - Remove
drain()anddrain_filter()fromTable. Useretain,retain_in,extract_iforextract_from_ifinstead - impl
CloneforRange - Add support for
[T;N]as aValueorKeyas appropriate for the typeT - Add
len()andis_empty()toMultimapValue - Add
retain()andretain_in()toTable - Add
extract_if()andextract_from_if()toTable - Add
range()returning aRangewith the'staticlifetime to read-only tables - Add
get()returning a range with the'staticlifetime to read-only tables - Add
close()method toReadTransaction
-
2.0.0-beta018 Mar 2024 pre-releaseNothing published for this version
-
1.5.223 Aug 2025Release notes
Open source →- Fix correctness issue with
range(),drain(), anddrain_filter(). If a RangeBounds withstart>endwas passed as an argument andstartandendkeys were stored in different internal pages in the database (i.e. a sufficient condition is that more than 4KiB of key-value pairs were between the two keys) then these methods would perform as if the argument had beenstart..
- Fix correctness issue with
-
1.5.117 Mar 2024Release notes
Open source →- Fix
check_integrity()so that it returnsOk(true)when no repairs were preformed. Previously, it returnedOk(false)
- Fix
-
1.5.015 Jan 2024Release notes
Open source →- Export
TableStatstype - Export
MutInPlaceValuewhich allows custom types to supportinsert_reserve() - Add untyped table API which allows metadata, such as table stats, to be retrieved for at table without knowing its type at compile time
- Fix compilation on uncommon platforms (those other than Unix and Windows)
- Export
-
1.4.021 Nov 2023Release notes
Open source →- Add
Builder::set_repair_callback()which can be used to set a callback function that will be invoked if the database needs repair while opening it. - Add support for custom storage backends. This is done by implementing the
StorageBackendtrait and using theBuilder::create_with_backendfunction. This allows the database to be stored in a location other than the filesystem - Implement
RedbKeyandRedbValueforchar - Implement
RedbKeyandRedbValueforbool - Implement
TableHandleforTable - Implement
MultimapTableHandleforMultimapTable - Fix panic that could occur when inserting a large number of fixed width values into a table within a single transaction
- Fix panic when calling
delete_table()on a table that is already open - Improve performance for fixed width types
- Support additional platforms
- Add
-
1.3.022 Oct 2023Release notes
Open source →- Implement
RedbKeyforOption<T> - Implement
RedbValueforVec<T> - Implement
Debugfor tables - Add
ReadableTable::first()andlast()which retrieve the first and last key-value pairs, respectively` - Reduce lock contention for mixed read-write workloads
- Documentation improvements
- Implement
-
1.2.024 Sep 2023Release notes
Open source →- Add
Builder::create_file()which does the same thing ascreate()but takes aFileinstead of a path - Add
stats()to tables which provides informational statistics on the table's storage - Fix
WriteTransaction::stats()to correctly count the storage used by multi-map tables - Fix panics that could occur when operating on savepoints concurrently from multiple threads
on the same
WriteTransaction - Implement
SendforWriteTransaction - Change MSRV to 1.66
- Performance optimizations
- Add
-
1.1.021 Aug 2023Release notes
Open source →- Fix panic when calling
compact()on certain databases - Fix panic when calling
compact()when an ephemeralSavepointexisted - Improve performance of
compact() - Relax lifetime requirements on arguments to
insert()
- Fix panic when calling
-
1.0.516 Jul 2023Release notes
Open source →- Fix a rare panic when recovering a database file after a crash
- Minor performance improvement to write heavy workloads
-
1.0.401 Jul 2023Release notes
Open source →- Fix serious data corruption issue when calling
drain()ordrain_filter()on aTablethat had uncommitted data
- Fix serious data corruption issue when calling
-
1.0.330 Jun 2023 -
1.0.229 Jun 2023Release notes
Open source →- Fix panic when recovering some databases after a forceful shutdown
- Fix panic when recovering databases with multimaps that have fixed width values after a forceful shutdown
-
1.0.126 Jun 2023Release notes
Open source →- Fix panic that could occur after an IO error when reopening a database
- Fix panic that could occur after an IO error when opening a table
- Improve error message when opening a table twice to include a more meaningful line number
- Performance improvements
-
1.0.016 Jun 2023Release notes
Open source →Announcement
redb has reached its first stable release! The file format is now gauranteed to be backward compatible, and the API is stable. I've run pretty extensive fuzz testing, but please report any bugs you encounter.
The following features are complete:
- MVCC with a single
WriteTransactionand multipleReadTransactions - Zero-copy reads
- ACID semantics, including non-durable transactions which only sacrifice Durability
- Savepoints which allow the state of the database to be captured and restored later
Changes from 0.22.0:
- Stabilize file format
- Improve performance of
restore_savepoint()
- MVCC with a single
-
0.22.012 Jun 2023Release notes
Open source →- Fix panic while repairing a database file after crash
- Fix rare panic in
restore_savepoint()
-
0.21.009 Jun 2023Release notes
Open source →- Improve cache heuristic. This asymptotically improves performance on large databases. Benchmarks show 30% to 5x+
- Fix rare crash that could occur under certain conditions when inserting values > 2GiB
- Fix crash when growing database beyond 4TiB
- Fix panic when repairing a database containing a multimap table with fixed width values
- Performance optimizations
- File format simplifications
-
0.20.030 May 2023Release notes
Open source →- Export
TransactionErrorandCommitError. These were unintentionally private - Implement
std::error::Errorfor all error enums
- Export
-
0.19.030 May 2023Release notes
Open source →- Remove
Clonebound from range argument type ondrain()anddrain_filter() - File format changes to improve future extensibility
- Remove
-
0.18.028 May 2023Release notes
Open source →- Improve errors to be more granular.
Errorhas been split into multiple differentenums, which can all be implicitly converted back toErrorfor convenience - Rename
savepoint()toephemeral_savepoint() - Add support for persistent savepoints. These persist across database restarts and must be explicitly released
- Optimize
restore_savepoint()to be ~30x faster - Add experimental support for WASI. This requires nightly
- Implement
RedbKeyfor() - Fix some rare crash and data corruption bugs
- Improve errors to be more granular.
-
0.17.009 May 2023Release notes
Open source →- Enforce a limit of 3GiB on keys & values
- Fix database corruption bug that could occur if a
Durability::Nonecommit was made, followed by a durable commit and the durable commit crashed or encountered an I/O error duringcommit() - Fix panic when re-openning a database file, when the process that last had it open had crashed
- Fix several bugs where an I/O error during
commit()could cause a panic instead of returning anErr - Change
lengthargument toinsert_reserve()tou32 - Change
Table::len()to returnu64 - Change width of most fields in
DatabaseStatstou64 - Remove
Ktype parameter fromAccessGuardMut - Add
Database::compact()which compacts the database file - Performance optimizations
-
0.16.029 Apr 2023Release notes
Open source →- Combine
Builder::set_read_cache_size()andBuilder::set_write_cache_size()into a single,Builder::set_cache_size()setting - Relax lifetime constraints on read methods on tables
- Optimizations to
Savepoint
- Combine
-
0.15.009 Apr 2023Release notes
Open source →- Add
Database::check_integrity()to explicitly run repair process (it is still always run if needed on db open) - Change
list_tables()to return aTableHandle - Change
delete_table()to take aTableHandle - Make
insert_reserve()API signature type safe - Change all iterators to return
Resultand propagate I/O errors - Replace
WriteStrategywithDurability::Paranoid - Remove
Builder::set_initial_size() - Enable db file shrinking on Windows
- Performance optimizations
- Add
-
0.14.026 Mar 2023Release notes
Open source →- Remove
Builder::create_mmapped()andBuilder::open_mmapped(). The mmap backend has been removed because it was infeasible to prove that it was sound. This makes the redb API entirely safe, and the remainingFilebased backed is within a factor of ~2x on all workloads that I've benchmarked - Make
TableimplementSend. It is now possible to insert into multipleTables concurrently - Expose
AccessGuardMut,DrainandDrainFilterin the public API - Rename
RangeItertoRange - Rename
MultimapRangeItertoMultimapRange - Rename
MultimapValueItertoMultimapValue - Performance optimizations
- Remove
-
0.13.005 Feb 2023Release notes
Open source →- Fix a major data corruption issue that was introduced in version 0.12.0. It caused databases
greater than ~4GB to become irrecoverably corrupted due to an integer overflow in
PageNumber::address_rangethat was introduced by commitb2c44a824d1ba69f526a1a75c56ae8484bae7248 - Add
drain_filter()toTable - Make key and value type bounds more clear for tables
- Fix a major data corruption issue that was introduced in version 0.12.0. It caused databases
greater than ~4GB to become irrecoverably corrupted due to an integer overflow in
-
0.12.122 Jan 2023 withdrawnRelease notes
Open source →- Fix
open()on platforms with OS page size != 4KiB - Relax lifetime requirements on argument to
range()anddrain()
- Fix
-
0.12.022 Jan 2023 withdrawnRelease notes
Open source →- Add
pop_first()andpop_last()toTable - Add
drain()toTable - Add support for
Option<T>as a value type - Add support for user defined key and value types. Users must implement
RedbKeyand/orRedbValue - Change
get(),insert(),remove()...etc to take arguments of typeimpl Borrow<SelfType> - Return
Error::UpgradeRequiredwhen opening a file with an outdated file format - Improve support for 32bit platforms
- Performance optimizations
- Add
-
0.11.026 Dec 2022Release notes
Open source →- Remove
[u8]andstrtype support. Use&[u8]and&strinstead. - Change
get(),range()and several other methods to returnAccessGuard. - Rename
AccessGuard::to_value()tovalue() - Add a non-mmap based backend which is now the default. This makes
Database::create()andDatabase::open()safe, but has worse performance in some cases. The mmap backend is available viacreate_mmapped()/open_mmapped(). There is no difference in the file format, so applications can switch from one backend to the other. - Better handling of fsync failures
- Remove
-
0.10.024 Nov 2022Release notes
Open source →- Remove maximum database size argument from
create(). Databases are now unbounded in size - Reduce address space usage on Windows
- Remove
set_dynamic_growth() - Add
set_initial_size()toBuilder - Optimize cleanup of deleted pages. This resolves a performance issue where openning a Database or performing a small transaction, could be slow if the last committed transaction deleted a large number of pages
- Remove
set_page_size(). 4kB pages are always used now - Add
iter()method toTableandMultimapTable - Fix various lifetime issues with type that had a lifetime, such as
&strand(&[u8], u64)
- Remove maximum database size argument from
-
0.9.005 Nov 2022Release notes
Open source →- Add support for dynamic file growth on Windows
- Add support for tuple types as keys and values
- Remove
Builder::set_region_size - Save lifetime from
Savepoint - Fix crash when using
create()to open an existing database created withWriteStrategy::TwoPhase - Fix rare crash when writing a mix of small and very large values into the same table
- Performance optimizations
-
0.8.019 Oct 2022Release notes
Open source →- Performance improvements for database files that are too large to fit in RAM
- Fix deadlock in concurrent calls to
savepoint()andrestore_savepoint() - Fix crash if
restore_savepoint()failed - Move
savepoint()andrestore_savepoint()methods toWriteTransaction - Implement
Iteratorfor the types returned fromrange()andremove_all()
-
0.7.026 Sep 2022Release notes
Open source →- Add support for Windows
- Add
Database::set_write_strategywhich allows theWriteStrategyof the database to be changed after creation - Make
Database::begin_writeblock, instead of panic'ing, if there is another write already in progress - Add
Database::savepointandDatabase::restore_savepointwhich can be used to snapshot and rollback the database - Rename
DatabaseBuildertoBuilder - Performance optimizations for large databases
-
0.6.111 Sep 2022Release notes
Open source →- Fix crash when
Database::open()was called on a database that had been created withWriteStrategy::TwoPhase - Change default region size on 32bit platforms to 4GiB
- Fix crash when
-
0.6.011 Sep 2022Release notes
Open source →- Return
Errinstead of panic'ing when opening a database file with an incompatible file format version - Many optimizations to the file format, and progress toward stabilizing it
- Fix race between read & write transactions, which could cause reads to return corrupted data
- Better document the different
WriteStrategys - Fix panic when recovering a database that was uncleanly shutdown, which had been created with
WriteStrategy::Checksum(which is the default) - Fix panic when using
insert_reserve()in certain cases
- Return
-
0.5.007 Aug 2022Release notes
Open source →- Optimize
MultimapTablestorage format to useO(k * log(n_k) + v * log(n_v / n_k))space instead ofO(k * log(n_k + n_v) + v * log(n_k + n_v))space, where k is the size of the stored keys, v is the size of the stored values, n_k is the number of stored keys, n_v is the number of stored values - Fix compilation errors for 32bit x86 targets
- Add support for the unit type,
(), as a value - Return an error when attempting to open the same database file for writing in multiple locations, concurrently
- More robust handling of fsync failures
- Change
MultimapTable::rangeto return an iterator of key-value-collection pairs, instead of key-value pairs - Automatically abort
WriteTransactionon drop
- Optimize
-
0.4.027 Jul 2022Release notes
Open source →- Add single phase with checksum commit strategy. This is now the default and reduces commit latency by ~2x. For more details,
see the design doc and
blog post. The previous behavior is available
via
WriteStrategy::Throughput, and can have better performance when writing a large number of bytes per transaction.
- Add single phase with checksum commit strategy. This is now the default and reduces commit latency by ~2x. For more details,
see the design doc and
blog post. The previous behavior is available
via
-
0.3.121 Jul 2022Release notes
Open source →- Fix a bug where re-opening a
Tableduring aWriteTransactionlead to stale results being read
- Fix a bug where re-opening a