#atomic #storage #crash-consistent

syncless

ordered, atomic storage without durability guarantees

4 releases

Uses new Rust 2024

0.2.0 Dec 27, 2025
0.1.2 Dec 20, 2025
0.1.1 Dec 20, 2025
0.1.0 Dec 20, 2025

#942 in Filesystem

MIT license

28KB
515 lines

syncless: Ordered, atomic storage without durability guarantees.

syncless provides crash-safe, append-style storage where:

  • individual writes are atomic
  • writes are observed in order
  • previously visible data is never corrupted
  • fsync is rarely used (only on creation, and when file gets too large)

Recent writes may be lost on OS crash or power failure.

When to use this

Use syncless when:

  • durability is not required
  • corruption is unacceptable
  • synchronous fsync is too expensive

Examples: browser history, bookmarks, caches, indexes.

When not to use this

Do not use syncless when you need:

  • durability guarantees
  • multi-writer isolation
  • cross-process coordination

Try sqlite3 for that.

Documentation

Full API documentation: https://docs.rs/syncless


lib.rs:

syncless: ordered, atomic storage without durability guarantees.

Many times you don't want to pay the cost of continuous fsyncs, and are ok with losing the latest updates if an OS crash/power outage were to happen and the user is unlucky - but it's not acceptable to corrupt older data. Think of cases like "browser bookmarks" or "history": synchronous requirements are overkill for these (and stressful on the entire system).

Once syncless has opened a file (except for hardware errors or bugs) writes are atomic and consistently ordered: if you see a write you will see all of it, and all prior writes.

Writes are not isolated (a single reader/writer is assumed) and not durable: data may remain buffered in memory and be lost on crash or power failure. However, crash recovery will never expose torn writes or corrupt earlier data.

Guarantees

  • Atomic visibility of individual writes
  • Ordered visibility of writes
  • Crash-safe recovery of previously visible data

Non-guarantees

  • Durability (recent writes may be lost)
  • Isolation (single writer assumed)
  • Multi-process coordination

Example: atomically storing a JSON file

This saves a JSON blob (perhaps your program's config?) using syncless so it either gets the old or new one, never a corrupted version. In practice you would probably keep the Store object around, as reloading it can be expensive if it has many changes.

use syncless::{open, Store, Writable, Error};

pub fn save_config(
    store: &mut Store<syncless::Writable>,
    json: &str,
) -> Result<(), Error> {
    store.write(0, json.as_bytes())
}

pub fn load_config(
    store: &mut Store<syncless::ReadOnly>
) -> Result<String, Error> {
    let mut buf = vec![0u8; store.size() as usize];

    store.read(0, &mut buf)?;
    let s = std::str::from_utf8(&buf)
        .map_err(|e| Error::CorruptRecord)?;
    Ok(s.to_owned())
}

Dependencies

~125KB