Your first service
The vault and collection you used on the previous page are the always-on kernel — every install ships them. Everything past that is opt-in: a service is a tree-shakeable module behind a with*() strategy factory, and its code only enters your bundle once you pass that factory to createNoydb().
history is a good first one to try: it keeps a full audit trail of every write to a collection — a snapshot of each record's prior state, plus a tamper-evident log — the ledger — of who changed what and when. Opt in with withHistory():
import { createNoydb } from '@noy-db/hub'
import { withHistory } from '@noy-db/hub/history'
type Invoice = { id: string; amount: number; customer: string }
const db = await createNoydb({
user: 'me',
secret: 'correct horse battery staple',
historyStrategy: withHistory(),
})
const vault = await db.openVault('acme')
const invoices = vault.collection<Invoice>('invoices')
await invoices.put('inv-1', { id: 'inv-1', amount: 8500, customer: 'ABC Trading' })
await invoices.put('inv-1', { id: 'inv-1', amount: 9000, customer: 'ABC Trading' })
const versions = await invoices.history('inv-1')
[
{ "version": 1, "timestamp": "2026-07-08T10:01:00.000Z", "userId": "me", "record": { "id": "inv-1", "amount": 8500, "customer": "ABC Trading" } }
]
history() returns only prior versions, newest first — the current live version (amount: 9000) isn't in the list; read it with invoices.get('inv-1') as usual. That's why one put before it produced zero history entries and this second put produced exactly one: each put snapshots the version it's about to overwrite.
That snapshot-plus-ledger write is what every other history capability reads from:
invoices.getVersion('inv-1', 1)— load one past version's content directly.invoices.diff('inv-1', 1)— field-level diff between version 1 and the current record.invoices.revert('inv-1', 1)— re-putversion 1's content as a brand-new version.vault.at('2026-07-08T10:01:30Z')— a read-only view of the whole vault as it stood at that instant.
Without historyStrategy, history(), getVersion(), and diff() throw pointing back to @noy-db/hub/history, and none of that code reaches your bundle. See history for the full API — including the ledger, retention, and point-in-time reads in depth.
Next
See the ciphertext → — persist the vault to disk and verify with your own eyes what the store holds.