Sled - the champagne of beta embedded databases

Last update: May 21, 2022
key value
buy a coffee for us to convert into databases
documentation
chat about databases with us

sled - it's all downhill from here!!!

An embedded database.

let tree = sled::open("/tmp/welcome-to-sled")?;

// insert and get, similar to std's BTreeMap
let old_value = tree.insert("key", "value")?;

assert_eq!(
  tree.get(&"key")?,
  Some(sled::IVec::from("value")),
);

// range queries
for kv_result in tree.range("key_1".."key_9") {}

// deletion
let old_value = tree.remove(&"key")?;

// atomic compare and swap
tree.compare_and_swap(
  "key",
  Some("current_value"),
  Some("new_value"),
)?;

// block until all operations are stable on disk
// (flush_async also available to get a Future)
tree.flush()?;

If you would like to work with structured data without paying expensive deserialization costs, check out the structured example!

features

  • API similar to a threadsafe BTreeMap<[u8], [u8]>
  • serializable (ACID) transactions for atomically reading and writing to multiple keys in multiple keyspaces.
  • fully atomic single-key operations, including compare and swap
  • zero-copy reads
  • write batches
  • subscribe to changes on key prefixes
  • multiple keyspaces
  • merge operators
  • forward and reverse iterators over ranges of items
  • a crash-safe monotonic ID generator capable of generating 75-125 million unique ID's per second
  • zstd compression (use the compression build feature, disabled by default)
  • cpu-scalable lock-free implementation
  • flash-optimized log-structured storage
  • uses modern b-tree techniques such as prefix encoding and suffix truncation for reducing the storage costs of long keys with shared prefixes. If keys are the same length and sequential then the system can avoid storing 99%+ of the key data in most cases, essentially acting like a learned index

expectations, gotchas, advice

  • Maybe one of the first things that seems weird is the IVec type. This is an inlinable Arced slice that makes some things more efficient.
  • Durability: sled automatically fsyncs every 500ms by default, which can be configured with the flush_every_ms configurable, or you may call flush / flush_async manually after operations.
  • Transactions are optimistic - do not interact with external state or perform IO from within a transaction closure unless it is idempotent.
  • Internal tree node optimizations: sled performs prefix encoding on long keys with similar prefixes that are grouped together in a range, as well as suffix truncation to further reduce the indexing costs of long keys. Nodes will skip potentially expensive length and offset pointers if keys or values are all the same length (tracked separately, don't worry about making keys the same length as values), so it may improve space usage slightly if you use fixed-length keys or values. This also makes it easier to use structured access as well.
  • sled does not support multiple open instances for the time being. Please keep sled open for the duration of your process's lifespan. It's totally safe and often quite convenient to use a global lazy_static sled instance, modulo the normal global variable trade-offs. Every operation is threadsafe, and most are implemented under the hood with lock-free algorithms that avoid blocking in hot paths.

performance

  • LSM tree-like write performance with traditional B+ tree-like read performance
  • over a billion operations in under a minute at 95% read 5% writes on 16 cores on a small dataset
  • measure your own workloads rather than relying on some marketing for contrived workloads

a note on lexicographic ordering and endianness

If you want to store numerical keys in a way that will play nicely with sled's iterators and ordered operations, please remember to store your numerical items in big-endian form. Little endian (the default of many things) will often appear to be doing the right thing until you start working with more than 256 items (more than 1 byte), causing lexicographic ordering of the serialized bytes to diverge from the lexicographic ordering of their deserialized numerical form.

  • Rust integral types have built-in to_be_bytes and from_be_bytes methods.
  • bincode can be configured to store integral types in big-endian form.

interaction with async

If your dataset resides entirely in cache (achievable at startup by setting the cache to a large enough value and performing a full iteration) then all reads and writes are non-blocking and async-friendly, without needing to use Futures or an async runtime.

To asynchronously suspend your async task on the durability of writes, we support the flush_async method, which returns a Future that your async tasks can await the completion of if they require high durability guarantees and you are willing to pay the latency costs of fsync. Note that sled automatically tries to sync all data to disk several times per second in the background without blocking user threads.

We support async subscription to events that happen on key prefixes, because the Subscriber struct implements Future<Output=Option<Event>>:

let sled = sled::open("my_db").unwrap();

let mut sub = sled.watch_prefix("");

sled.insert(b"a", b"a").unwrap();

extreme::run(async move {
    while let Some(event) = (&mut sub).await {
        println!("got event {:?}", event);
    }
});

minimum supported Rust version (MSRV)

We support Rust 1.48.0 and up.

architecture

lock-free tree on a lock-free pagecache on a lock-free log. the pagecache scatters partial page fragments across the log, rather than rewriting entire pages at a time as B+ trees for spinning disks historically have. on page reads, we concurrently scatter-gather reads across the log to materialize the page from its fragments. check out the architectural outlook for a more detailed overview of where we're at and where we see things going!

philosophy

  1. don't make the user think. the interface should be obvious.
  2. don't surprise users with performance traps.
  3. don't wake up operators. bring reliability techniques from academia into real-world practice.
  4. don't use so much electricity. our data structures should play to modern hardware's strengths.

known issues, warnings

  • if reliability is your primary constraint, use SQLite. sled is beta.
  • if storage price performance is your primary constraint, use RocksDB. sled uses too much space sometimes.
  • if you have a multi-process workload that rarely writes, use LMDB. sled is architected for use with long-running, highly-concurrent workloads such as stateful services or higher-level databases.
  • quite young, should be considered unstable for the time being.
  • the on-disk format is going to change in ways that require manual migrations before the 1.0.0 release!

priorities

  • rework the transaction API to eliminate surprises and limitations
  • reduce space and memory usage
  • the 1.0.0 release date is imminent! just putting the final touches on, while performing intensive testing
  • combine merge operators with subscribers in a way that plays nicely with transactions
  • typed trees for low-friction serialization
  • replication support for both strongly and eventually consistent systems
  • continue to improve testing and make certain bug classes impossible through construction
  • continue to optimize the hell out of everything
  • continue to improve documentation and examples
  • continue to reduce compilation latency

fund feature development

Like what we're doing? Help us out via GitHub Sponsors!

GitHub

https://github.com/spacejam/sled
Comments
  • 1. 32-bit ARM compatibility

    • [x] add test to make sure that the system never wraps by writing to an offset > 2^32
    • [x] add additional concurrency verification tooling, as ARM has a weaker memory model than x86_64 (which makes it a great test platform in general)
    Reviewed by spacejam at 2017-09-21 15:55
  • 2. Transactions are deadlocking at insert_inner

    Transactions are deadlocking inside of commit and never returning in my application. LLDB shows the thread as stuck on this line:

    while self.tree.insert_inner(k, v_opt.clone(), &mut guard)?.is_err()
    {
    }
    

    Source things: https://github.com/spacejam/sled/blob/master/src/transaction.rs#L364

    1. expected result: I expect TransactionTree::commit to always return a result.
    2. actual result: TransactionTree::commit intermittently blocks until I kill the application.
    3. sled version: 0.34.2 + some small error handling experiments: https://github.com/D1plo1d/sled/tree/53d0e30a749f27fb808101730f1794a5f85b6216
    4. rustc version: rustc 1.44.1 (c7087fe00 2020-06-17)
    5. operating system: Ubuntu 20.04
    6. minimal code sample that helps to reproduce the issue: Intermittent issue. TBH I could use a hand figuring out how to reliably reproduce my issue.
    7. logs, panic messages, stack traces: Not sure what would be helpful here (please let me know!). I added a couple trace! macros to commit and observed that the commit started but never finished.
    Reviewed by D1plo1d at 2020-08-22 20:44
  • 3. Cannot shutdown sled from Windows Service

    1. sled version 0.28.0
    2. rustc version 1.39.0
    3. operating system Windows 10 Enterprise 1809 Build 17763.864
    4. logs

    When I try to join my main thread after receiving the stop signal, I have 2 sled threads that are not terminating.

    The Db and Trees are stored using RwLock:

    pub struct Table {
        pub arc_tree_lock: RwLock<Option<Arc<Tree>>>,
        name: String,
        key: String,
        key2_opt: Option<String>,
    }
    
    pub struct MyDb {
        pub my_db: Arc<RwLock<Option<Db>>>,
        db_name: String,
    
    

    When I get the Windows service stop, for each Tree I call flush() and then I set the option to None to de-reference the Tree after taking the lock.

    When done, I set my_db to None to de-reference the DB.

    However, I have 2 threads still waiting that prevent the final join from completing, it was 3 including the log flusher, but after the code to flush then set option to None, at least the log flusher seems to have cleaned up.

    The 2 are sled-io with the following stack trace (after break all):

     	[External Code]	
     	[Inline Frame] my.exe!!std::sys::windows::c::SleepConditionVariableSRW() Line 70	Unknown
     	[Inline Frame] my.exe!!std::sys::windows::condvar::Condvar::wait() Line 22	Unknown
     	[Inline Frame] my.exe!!std::sys_common::condvar::Condvar::wait() Line 41	Unknown
     	[Inline Frame] my.exe!!std::sync::condvar::Condvar::wait() Line 204	Unknown
     	my.exe!std::thread::park() Line 911	Unknown
     	my.exe!!crossbeam_channel::context::Context::wait_until(core::option::Option<std::time::Instant> self) Line 175	Unknown
     	my.exe!!crossbeam_channel::flavors::zero::{{impl}}::recv::{{closure}}<alloc::boxed::Box<FnOnce<()>>>(crossbeam_channel::flavors::zero::{{impl}}::recv::closure-1 cx, crossbeam_channel::context::Context *) Line 304	Unknown
     	my.exe!!crossbeam_channel::context::{{impl}}::with::{{closure}}<closure-1,core::result::Result<alloc::boxed::Box<FnOnce<()>>, crossbeam_channel::err::RecvTimeoutError>>(crossbeam_channel::context::{{impl}}::with::closure-0 * cx, crossbeam_channel::context::Context *) Line 51	Unknown
     	my.exe!!crossbeam_channel::context::{{impl}}::with::{{closure}}<closure-1,core::result::Result<alloc::boxed::Box<FnOnce<()>>, crossbeam_channel::err::RecvTimeoutError>>(crossbeam_channel::context::{{impl}}::with::closure-1 cell, core::cell::Cell<core::option::Option<crossbeam_channel::context::Context>> *) Line 58	Unknown
     	my.exe!!std::thread::local::LocalKey<core::cell::Cell<core::option::Option<crossbeam_channel::context::Context>>>::try_with<core::cell::Cell<core::option::Option<crossbeam_channel::context::Context>>,closure-1,core::result::Result<alloc::boxed::Box<FnOnce<()>>, crossbeam_channel::err::RecvTimeoutError>>(crossbeam_channel::context::{{impl}}::with::closure-1 self) Line 262	Unknown
    >	my.exe!!crossbeam_channel::context::Context::with<closure-1,core::result::Result<alloc::boxed::Box<FnOnce<()>>, crossbeam_channel::err::RecvTimeoutError>>(crossbeam_channel::flavors::zero::{{impl}}::recv::closure-1 f) Line 53	Unknown
     	my.exe!!crossbeam_channel::flavors::zero::Channel<alloc::boxed::Box<FnOnce<()>>>::recv<alloc::boxed::Box<FnOnce<()>>>(core::option::Option<std::time::Instant> self) Line 293	Unknown
     	my.exe!!crossbeam_channel::channel::Receiver<alloc::boxed::Box<FnOnce<()>>>::recv<alloc::boxed::Box<FnOnce<()>>>() Line 718	Unknown
     	my.exe!!crossbeam_channel::channel::{{impl}}::next<alloc::boxed::Box<FnOnce<()>>>(crossbeam_channel::channel::Iter<alloc::boxed::Box<FnOnce<()>>> * self) Line 1105	Unknown
     	my.exe!!pagecache::threadpool::spawn::init_pool::{{closure}}(pagecache::threadpool::spawn::init_pool::closure-0) Line 54	Unknown
     	my.exe!!std::sys_common::backtrace::__rust_begin_short_backtrace<closure-0,()>(pagecache::threadpool::spawn::init_pool::closure-0 f) Line 127	Unknown
     	my.exe!!std::thread::{{impl}}::spawn_unchecked::{{closure}}::{{closure}}<closure-0,()>(std::thread::{{impl}}::spawn_unchecked::{{closure}}::closure-0) Line 471	Unknown
     	my.exe!!std::panic::{{impl}}::call_once<(),closure-0>(std::panic::AssertUnwindSafe<closure-0> self) Line 316	Unknown
     	my.exe!!std::panicking::try::do_call<std::panic::AssertUnwindSafe<closure-0>,()>(unsigned char * data) Line 292	Unknown
     	my.exe!!panic_unwind::__rust_maybe_catch_panic() Line 80	Unknown
     	my.exe!!std::panicking::try<(),std::panic::AssertUnwindSafe<closure-0>>(std::panic::AssertUnwindSafe<closure-0> f) Line 271	Unknown
     	my.exe!!std::panic::catch_unwind<std::panic::AssertUnwindSafe<closure-0>,()>(std::panic::AssertUnwindSafe<closure-0> f) Line 394	Unknown
     	my.exe!!std::thread::{{impl}}::spawn_unchecked::{{closure}}<closure-0,()>(std::thread::{{impl}}::spawn_unchecked::closure-0) Line 469	Unknown
     	my.exe!!core::ops::function::FnOnce::call_once<closure-0,()>(std::thread::{{impl}}::spawn_unchecked::closure-0 *) Line 227	Unknown
     	my.exe!!alloc::boxed::{{impl}}::call_once<(),FnOnce<()>>() Line 922	Unknown
     	[Inline Frame] my.exe!!alloc::boxed::{{impl}}::call_once() Line 922	Unknown
     	[Inline Frame] my.exe!!std::sys_common::thread::start_thread() Line 13	Unknown
     	my.exe!e!std::sys::windows::thread::{{impl}}::new::thread_start() Line 47	Unknown
     	[External Code]	
    
    
    Reviewed by crusty-dave at 2019-12-11 03:38
  • 4. Compilation for 32-bit architectures on nightly

    Discussion points:

    • [x] Is a global nightly feature good in this case? Should I give it a better name?
    • [x] I didn't run the tests on an ARM 32-bit; would you want me to test that?
    • [x] pagecache::Lsn is now of type i64 when the nightly feature is enabled.

    Let me know if you want me to change stuff! :-)

    Issue #145 for reference.

    Reviewed by rubdos at 2018-03-19 09:19
  • 5. Miri support

    This PR will add enough conditional compilation to support running tests with miri. So far, I have disabled use of the process's PID, turned off the body of try_lock(), and ignored the quickcheck tests, since they would take far too long to run. Miri is slow as tar, so using it would only be useful for spot-checking for unsoundness, not a CI job or anything.

    Miri requires additional shims for mkdir and rmdir before this will work, I have changes in progress for that as well.

    The first issue I've discovered thus far is that crossbeam-epoch has an unsound use of std::mem::uninitialized, creating a std::Mem::ManuallyDrop<T>. There is a PR at crossbeam-rs/crossbeam#458 that will fix this soon.

    Relevant commands:

    • Run a test: cargo +nightly miri test --features=testing -- -Zmiri-disable-isolation -- bug_22
    • Install miri from source: cargo +nightly install --path . --force --locked --offline

    Edit - updated commands:

    • Install miri from source (can use my merged-for-sled branch now): ./rustup-toolchain one time, then ./miri install
    • Run a test: cargo +miri miri test --features=testing -- -Zmiri-disable-isolation -Zmiri-ignore-leaks -- bug_22
    • Expanding macros, as seen by miri: RUSTFLAGS="--cfg miri" cargo +nightly expand --lib --tests serialization::qc

    More commands:

    • Default test suite: cargo +miri miri test --features=testing -- -Zmiri-disable-isolation -Zmiri-ignore-leaks -- (set ulimit -v first or this may eat all your swap space)
    • Default test suite, with racing stripes: cargo +miri miri test --features=testing -- -Zmiri-disable-isolation -Zmiri-ignore-leaks -Zmiri-disable-stacked-borrows -Zmiri-disable-validation -- (takes ~1hr on my computer)
    • Try running a longer-running test: cargo +miri miri test --features=testing -- -Zmiri-disable-isolation -Zmiri-ignore-leaks -- --ignored tree_bug_01
    Reviewed by divergentdave at 2020-01-24 13:47
  • 6. Tree::transaction API prevents error forwarding

    The function passed to Tree::transaction must currently return a Result<_, TransactionError>.

    This prevents users from forwarding business logic errors that occur during a transaction.

    I can see two solutions:

    • make the error generic, so it is under the control of the user. diesel does it this way

    • Add a TransactionError::Custom(Box<dyn std::error::Error) variant that can be used.

    Reviewed by theduke at 2019-09-07 15:51
  • 7. Use SHA3-256 for checksum

    As of release 0.31.0, sled is using the CRC32 checksum for the checksum value. This is quite weak. Would you consider upgrading the SHA3 family of functions? I'd suggest either (SHA3-256)[https://docs.rs/sha3/0.8.2/sha3/struct.Sha3_256.html] or (SHA3-512)[https://docs.rs/sha3/0.8.2/sha3/struct.Sha3_512.html].

    Reviewed by ckaran at 2020-02-14 19:40
  • 8. Rewrite the Data split method

    I tested and assumed that the ptrs are already sorted and that prefix encoded keys are sorted the same that non encoded ones (is that named "ordering transitivity" ?).

    I will rebase on master once #592 is merged, if it is 😄

    So in this rewrite I no longer need to construct a decoded sorted Vec but only need to decode the middle key (split) and create a new Vec of half the size of ptrs re-encoded using the previously extracted middle key (split).

    I also rewrite the prefix_decode and prefix_encode functions removing the unsafe code that doesn't seems to be needed and introduced a new prefix_reencode function that decode and encode using the the old and new prefix.

    This update reduced the usage percentage of the Data::split method from 46.2% to 25.47% and make my program takes from 25mins (including the #592 patch) to near 16mins.

    flamegraphs-before-after-data-split-patch.zip

    Reviewed by Kerollmops at 2019-03-23 11:25
  • 9. Sled database is not really closed after dropping `sled::Db`.

    Example code snippet (non-standalone):

            let db: sled::Db = sled::open(&opts.database_path)?;
            db.insert(b"qqq2", b"www3")?;
            db.flush()?;
            drop(db);
    
    
            let db: sled::Db = sled::open(&opts.database_path)?;
            drop(db);
    
    1. expected result: always works. No extra threads or file descriptors or other remnants remain after dropping all sled::Db instances.
    2. actual result: sometimes fails to close the file descriptor on drop, then fails flock on the next open.
    3. sled version: 0.34.6
    4. rustc version: rustc 1.49.0-nightly (8dae8cdcc 2020-10-12)
    5. operating system: Linux
    Reviewed by vi at 2021-01-04 17:06
  • 10. Question: Is Sled multi-process safe?

    I have access to a cluster system, but the nodes on the cluster can only synchronize through the filesystem. flock does work on the system, so I've been using it to ensure that any shared files aren't corrupted, and I could continue to do the same when using sled, but if sled is already multi-process safe, then there's no need for all this code (and it would likely slow sled down a lot). So, is sled multi-process safe?

    Reviewed by ckaran at 2020-08-25 13:13
  • 11. MIPS support

    Hi there,

    I've recently tried to compile a project that depends on sled to OpenWRT mips device using cross.

     cross build --target mips-unknown-linux-musl
    

    This led me to type errors similar to the ones found on async-std for 32bit devices.

    I've tried to locally change the types from AtomicU64 to AtomicUsize as they did there, and there were many more errors to fix...

    I'm curious if there is interest on having the project working on MIPS devices, and it I could give it a try to get it compiling. Cheers.

    Reviewed by bltavares at 2020-05-19 01:44
  • 12. Deadlock under high load

    I have an application making hundreds of get calls and dozens of insert calls a second over 8 concurrent threads. Sled consistently deadlocks after several minutes of this. I wasn't able to trigger a deadlock without insert calls, but get calls themselves did deadlock.

    • Sled version 0.34.7.
    • rustc version 1.59.0.
    • Linux.
    Reviewed by JustinLovinger at 2022-05-13 16:16
  • 13. Update zstd requirement from 0.10.0 to 0.11.2

    Updates the requirements on zstd to permit the latest version.

    Commits

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    Reviewed by dependabot[bot] at 2022-05-12 10:14
  • 14. Is sled supposed to use memory comparable to database size itself?

    I get crashes on trying to open a big Sled database on small VPS.

    Does using 500 MB of RSS after opening gigabyte database indicate a bug in Sled or is within design expectations?

    cache_capacity is set to 1024 * 1024.

    Reviewed by vi at 2022-04-30 00:40
  • 15. Transactions example from docs doesn't seem to compile, requires annotations

    I'm writing migrations (which is why I posted this feature request for tree renames) but I can't get transaction to compile when working on multiple Trees.

    Start a new sled project and try this code, practically copied from the Transaction docs:

    fn main() {
        use sled::Transactional;
        let config = sled::Config::new().temporary(true);
        let db = config.open().unwrap();
    
        let unprocessed = db.open_tree(b"unprocessed items").unwrap();
        let processed = db.open_tree(b"processed items").unwrap();
    
        // An update somehow gets into the tree, which we
        // later trigger the atomic processing of.
        unprocessed.insert(b"k3", b"ligers").unwrap();
    
        // Atomically process the new item and move it
        // between `Tree`s.
        (&unprocessed, &processed)
            .transaction(|(unprocessed, processed)| {
                let unprocessed_item = unprocessed.remove(b"k3")?.unwrap();
                let mut processed_item = b"yappin' ".to_vec();
                processed_item.extend_from_slice(&unprocessed_item);
                processed.insert(b"k3", processed_item)?;
                Ok(())
            }).unwrap();
    
        assert_eq!(unprocessed.get(b"k3").unwrap(), None);
        assert_eq!(&processed.get(b"k3").unwrap().unwrap(), b"yappin' ligers");
    }
    

    Get the following compilation error where transaction(|(unprocessed, processed) is:

    type annotations needed
    cannot infer type for type parameter `E`rustc[E0282](https://doc.rust-lang.org/error-index.html#E0282)
    [main.rs(16, 21): ]()consider specifying the type arguments in the method call: `::<F, A>`
    error: type annotations needed
    label: cannot infer type for type parameter `E``
    

    I'm not really sure what is missing here.

    Reviewed by joepio at 2022-04-13 14:10
  • 16. Add `rename` method to `Tree`

    Use Case:

    I was wondering if it's possible to rename a Tree. I'm writing code that performs schema migrations, and it seems safer to create a temporary tree to put everything in, and replace that normal one with the new one after doing the migration. However, this warrants a Tree rename function, or something similar.

    Proposed Change:

    Add the rename method on Tree, which takes a new name.

    Who Benefits From The Change(s)?

    People performing schema migration in Sled?

    Alternative Approaches

    • Move all KV combo's over again to the old store. Can't say I like that.
    • Other ideas also welcome!
    Reviewed by joepio at 2022-04-13 11:42
Gh-sql - Query GitHub Projects (beta) with SQL
Gh-sql - Query GitHub Projects (beta) with SQL

gh-sql: Query GitHub Projects (beta) with SQL Installation gh extension install KOBA789/gh-sql Features SELECT items DELETE items UPDATE item fields

May 12, 2022
Engula empowers engineers to build reliable and cost-effective databases.
Engula empowers engineers to build reliable and cost-effective databases.

Engula is a storage engine that empowers engineers to build reliable and cost-effective databases with less effort and more confidence. Engula is in t

May 23, 2022
Provides a Rust-based SQLite extension for using Hypercore as the VFS for your databases.

SQLite and Hypercore A Rust library providing SQLite with an virtual file system to enable Hypercore as a means of storage. Contributing The primary r

May 5, 2022
Replibyte - a powerful tool to seed your databases
Replibyte - a powerful tool to seed your databases

Seed Your Development Database With Real Data ⚡️ Replibyte is a powerful tool to seed your databases with real data and other cool features ?? Feature

May 27, 2022
Simple, async embedded Rust

Cntrlr - Simple, asynchronous embedded Cntrlr is an all-in-one embedded platform for writing simple asynchronous applications on top of common hobbyis

Jun 3, 2021
RedisLess is a fast, lightweight, embedded and scalable in-memory Key/Value store library compatible with the Redis API.

RedisLess is a fast, lightweight, embedded and scalable in-memory Key/Value store library compatible with the Redis API.

May 16, 2022
Embedded graph database

CQLite An embedded graph database implemented in Rust. This is currently a pre-release. It has not been extensively tested with 'real-world work-loads

May 4, 2022
Embedded graph database

CQLite An embedded graph database implemented in Rust. This is currently a pre-release. It has not been extensively tested with 'real-world work-loads

May 15, 2022
Scalable and encrypted embedded database with 3-tier caching

Infinitree is a versioned, embedded database that uses uniform, encrypted blobs to store data.

May 18, 2022
Embedded Distributed Encrypted Database (Research).

EDED Embedded Distributed Encrypted Database. Research projects to support ESSE. WIP Distributed design features Adapt to personal distributed usecase

Jan 6, 2022
A simple embedded key-value store written in rust as a learning project

A simple embedded key-value store written in rust as a learning project

Feb 20, 2022
CLI tool to work with Sled key-value databases.

sledtool CLI tool to work with Sled key-value databases. $ sledtool --help Usage: sledtool <dbpath> <command> [<args>] CLI tool to work with Sled da

May 16, 2022
Solana Foundation stake bot used on the Solana Testnet and Mainnet-Beta

Effortlessly Manage Cluster Stakes The testnet and mainnet-beta clusters currently have a large population of validators that need to be staked by a c

May 18, 2022
Gh-sql - Query GitHub Projects (beta) with SQL
Gh-sql - Query GitHub Projects (beta) with SQL

gh-sql: Query GitHub Projects (beta) with SQL Installation gh extension install KOBA789/gh-sql Features SELECT items DELETE items UPDATE item fields

May 12, 2022
Santa Claus has to optimize the space for everyone present on the sled.

How to generate all sets of P packages into N bags Santa Claus has to optimize the space for everyone present on the sled Description Santa Claus got

Apr 26, 2022
Engula empowers engineers to build reliable and cost-effective databases.
Engula empowers engineers to build reliable and cost-effective databases.

Engula is a storage engine that empowers engineers to build reliable and cost-effective databases with less effort and more confidence. Engula is in t

May 23, 2022
Provides a Rust-based SQLite extension for using Hypercore as the VFS for your databases.

SQLite and Hypercore A Rust library providing SQLite with an virtual file system to enable Hypercore as a means of storage. Contributing The primary r

May 5, 2022
Query your Postgres databases directly using gRPC or transcoded JSON.

PostgRPC Query your Postgres databases directly using gRPC or transcoded JSON. Crates Postguard PostgRPC (release pending) postgres-services (release

Mar 2, 2022
A mini paste bin and url shortener written in rust without databases.

pb Build $ cargo build --release Environment Variables PB_DATA: /some/path (Default: ./pb_data) PB_SITE: Url of your site. (Default: http://localhost:

May 15, 2022
Replibyte - a powerful tool to seed your databases
Replibyte - a powerful tool to seed your databases

Seed Your Development Database With Real Data ⚡️ Replibyte is a powerful tool to seed your databases with real data and other cool features ?? Feature

May 27, 2022