Skip to content

Write Modes

shelf supports two write modes that control when data is persisted to disk. Choose the mode that matches your durability and performance requirements.

In WriteBack mode, writes go to ETS (memory) only. Data is persisted to DETS (disk) when you explicitly call save(), or automatically when the table is closed.

import shelf/set
let assert Ok(table) = set.open(name: "sessions", path: "data/sessions.dets")
// Fast writes — ETS only
let assert Ok(Nil) = set.insert(table, "user:1", session_1)
let assert Ok(Nil) = set.insert(table, "user:2", session_2)
// Persist to disk when ready
let assert Ok(Nil) = set.save(table)

Best for: High-throughput writes where you can tolerate some data loss on crash.

Use reload() to discard unsaved ETS changes and restore from the last DETS snapshot:

let assert Ok(Nil) = set.insert(table, "temp", "data")
// Changed our mind — discard unsaved changes
let assert Ok(Nil) = set.reload(table)
// "temp" key no longer exists

In WriteThrough mode, every write persists to both ETS and DETS immediately. Reads are still served from ETS (fast).

import shelf
import shelf/set
let config =
shelf.config(name: "accounts", path: "data/accounts.dets")
|> shelf.write_mode(shelf.WriteThrough)
let assert Ok(table) = set.open_config(config)
// This writes to both ETS and DETS
let assert Ok(Nil) = set.insert(table, "acct:1", account)

Best for: Data that must survive crashes with no loss — financial records, user accounts, configuration.

DETS buffers writes internally for performance. After a WriteThrough write, the data is in DETS but may still be in the OS write buffer. Use sync() to force the DETS buffer to the filesystem:

let assert Ok(Nil) = set.insert(table, "critical", value)
let assert Ok(Nil) = set.sync(table)
// Data is now on disk
WriteBackWriteThrough
Write speedFast (ETS only)Slower (ETS + DETS)
Data loss on crashSince last save()None (after sync())
When to persistManual save() callAutomatic on every write
reload() useful?Yes — discards unsaved changesNot typically — ETS and DETS are in sync
Best forCaches, sessions, high-throughputAccounts, config, audit logs

Write mode is set at table creation via Config:

import shelf
// WriteBack (the default — no config needed)
let assert Ok(table) = set.open(name: "cache", path: "data/cache.dets")
// WriteThrough (use config)
let config =
shelf.config(name: "accounts", path: "data/accounts.dets")
|> shelf.write_mode(shelf.WriteThrough)
let assert Ok(table) = set.open_config(config)

Write mode applies to all table types — set, bag, and duplicate_bag all support both modes.