DoraDB is an attempt to build a modern and fast storage engine in Rust from scratch. It is work in progress.
Build a modern and fast storage engine.
The storage engine is designed as a hybrid engine managing both in-memory row store and on-disk column store, with full transactional support across all data.
The snippets below assume an async function returning doradb_storage::Result<()>.
DoraDB is runtime agnostic, so you can run these futures on whichever async runtime your application already uses.
For a complete runnable version, see quick_start.rs or run cargo run --example quick_start.
Create a table with a schema and indexes, then drop it from an idle session.
use doradb_storage::{
ColumnAttributes, ColumnSpec, Engine, EngineConfig, IndexAttributes, IndexKey, IndexSpec,
TableSpec, ValKind,
};
let engine = Engine::bootstrap(
EngineConfig::default().storage_root("target/doradb-quick-start"),
)
.await?;
let mut session = engine.new_session()?;
let table_id = session
.create_table(
TableSpec::new(vec![
ColumnSpec::new("id", ValKind::I32, ColumnAttributes::empty()),
ColumnSpec::new("name", ValKind::VarByte, ColumnAttributes::empty()),
]),
vec![
IndexSpec::new(vec![IndexKey::new(0)], IndexAttributes::UK),
IndexSpec::new(vec![IndexKey::new(1)], IndexAttributes::empty()),
],
)
.await?;
session.drop_table(table_id).await?;
session.close().await?;
engine.shutdown()?;Insert, update, and delete rows by executing statements inside a transaction.
use doradb_storage::{SelectKey, UpdateCol, Val};
let mut trx = session.begin_trx()?;
trx.exec(async |stmt| {
stmt.table_insert_mvcc(table_id, vec![Val::from(1i32), Val::from("alice")])
.await?;
Ok(())
})
.await?;
let key = SelectKey::new(0, vec![Val::from(1i32)]);
trx.exec(async |stmt| {
stmt.table_update_unique_mvcc(
table_id,
&key,
vec![UpdateCol {
idx: 1,
val: Val::from("ada"),
}],
)
.await?;
Ok(())
})
.await?;
trx.exec(async |stmt| {
stmt.table_delete_unique_mvcc(table_id, &key, false).await?;
Ok(())
})
.await?;
trx.commit().await?;Scan rows, read one unique-key row, and scan matching rows through a secondary index.
use doradb_storage::{SelectKey, Val};
let mut trx = session.begin_trx()?;
let mut rows = Vec::new();
trx.exec(async |stmt| {
stmt.table_scan_mvcc(table_id, &[0, 1], |vals| {
rows.push(vals);
true
})
.await?;
Ok(())
})
.await?;
let id_key = SelectKey::new(0, vec![Val::from(1i32)]);
let _row = trx
.exec(async |stmt| {
stmt.table_lookup_unique_mvcc(table_id, &id_key, &[0, 1])
.await
})
.await?;
let name_key = SelectKey::new(1, vec![Val::from("ada")]);
let _matching_rows = trx
.exec(async |stmt| {
stmt.table_index_scan_mvcc(table_id, &name_key, &[0, 1])
.await
})
.await?
.unwrap_rows();
trx.rollback().await?;- Storage Architecture
- Transaction System
- Index Design
- Block Index
- Secondary Index
- Checkpoint
- Data Checkpoint
- Deletion Checkpoint
- Recovery
- Table File
- Buffer Pool
- Garbage Collect
Above documents describe the core design of this engine. Most parts are update-to-date. Some ideas are different from traditional database system. I'm glad to have discussions if someone is interested in details.
- buffer: Buffer pool implementation with async direct IO.
- catalog: Catalog of storage engine.
- compression: Compression algorithms for column store.
- file: Storage of table data, index and delete bitmap. The file is page based and organized as CoW B+Tree, to enable simple recovery and fast access.
- index: Block index and B+Tree index.
- io: Async direct IO system with compile-time-selected
libaioandio_uringbackends, by defaultio_uring. - latch: Async latch primitives including Mutex, RWLock and HybridLatch(enhanced RWLock with optimistic mode).
- lock: Metadata lock and table-level lock.
- log: Redo log record encoding, append, and initialization.
- lwc: Lightweight columnar format for on-disk warm data.
- recovery: Startup recovery coordination, redo stream replay, and recovered row state.
- row: In-memory row store and operations.
- table: Table of data, composite of block index, secondary index, buffer pool and table file. Support operations like index lookup, index scan, table scan, insert, delete, update, etc.
- trx: Transaction system, including transaction lifecycle, redo log integration, undo log, purge, and garbage collection.
Current development is heavily driven by document starting from Jan 2026, and implemneted by code agent.
Every task assigned to agent has one associated task document located in docs/tasks.
Larger features/refactors require RFC document inside docs/rfcs.
Deferred tasks are put in docs/backlogs.
This project is licensed under either of
- Apache License, Version 2.0, (LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or https://opensource.org/licenses/MIT)
at your option.