stable

Your first service

Opt into the history service with withHistory() and read back a record's past versions.

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-put version 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.