`@noy-db/to-*` — Storage destinations
Where your ciphertext lives. Pick one backend per vault — or several, via
routeStore— and swap it later without touching your app code.
The to- prefix reads as "data goes to a backend." Every to-*
package implements the same 6-method NoydbStore contract
and only ever sees encrypted envelopes — never plaintext, and never a
query (queries run inside the hub, after decryption). A few essential
stores ship alongside noy-db; the extended stores — cloud object stores, SQL
databases, remote filesystems, personal drives, and Cloudflare adapters —
are published from the companion
noy-db-to repo under the same
@noy-db npm names, installed exactly like a core store. Which repo
publishes each one, and the current counts, are in the generated
store capabilities matrix —
its Scope column, not this paragraph, is the authority.
Catalog
Local
| Package | Description |
|---|---|
memory | Fuller in-memory store. Tests, REPL, ephemeral caches. casAtomic: true, txAtomic: true. |
file | Local disk / USB stick. One JSON file per record, inspectable with any editor. |
browser-idb | The recommended browser store for PWAs. IndexedDB quota is typically 50–80% of available disk; CAS is atomic. |
browser-local | localStorage for small vaults under the 5 MB cap, synchronous access. Optional key obfuscation. |
Cloud object & KV
| Package | Description |
|---|---|
aws-s3 | S3 object per record. Atomic CAS via conditional writes. loadAll() is O(N) requests. |
aws-dynamo | DynamoDB single-table (pk = vault, sk = {collection}#{id}), so loadAll() is a single Query. |
cloudflare-r2 | Zero egress fees. S3-API-compatible: a thin factory around aws-s3 pointed at the R2 endpoint. |
cloudflare-d1 | Edge SQLite inside Cloudflare Workers via the D1Database binding. |
Cloud-sync drives
| Package | Description |
|---|---|
drive | Google Drive bundle store. Whole vault as one .noydb bundle, opaque ULID filename, in the hidden appDataFolder. |
icloud | iCloud Drive bundle store (Node on macOS). Detects .icloud eviction stubs; raises PodVersionConflictError on conflicts. |
drive and icloud are bundle stores (NoydbPodStore): wrap them with
wrapPodStore() from @noy-db/hub to get the standard six-method
NoydbStore surface.
SQL
| Package | Description |
|---|---|
postgres | Encrypted-envelope KV in a single table with a jsonb column. Any duck-typed query(sql, params) client. |
mysql | Encrypted-envelope KV with a JSON column, for MySQL 8+ / MariaDB. |
sqlite | Single-file SQLite for 10K+ records. Duck-typed Database interface (better-sqlite3, node:sqlite, bun:sqlite). |
turso | Hosted libSQL with multi-region replication. Same table/DDL as sqlite — a factory swap. |
supabase | Thin factory over postgres for the Postgres connection you already have. Never talks to Supabase REST/Realtime. |
Remote filesystems
| Package | Description |
|---|---|
ssh | SFTP over SSH, keys only (no passwords). Any Linux/macOS server with sshd. |
webdav | Nextcloud / ownCloud / Apache mod_dav, or any RFC 4918 server. Pure fetch()-based, zero dependencies. |
smb | SMB/CIFS (NTLM or Kerberos). Windows file servers, NAS devices, corporate shared drives. |
nfs | File store for a pre-mounted NFS path, with pre-flight mount diagnostics (nolock, stale attribute caching). |
rest | Any HTTP endpoint running an @noy-db/in-rest relay. The server holds ciphertext it cannot open. |
Diagnostics & wrappers
| Package | Description |
|---|---|
probe | Diagnostic companion. Not a backend — benchmarks any store and reports its suitability for primary / sync-peer / backup / archive. |
meter | Pass-through metrics wrapper. Wraps any store and records op latency, error rate, and CAS conflicts. |
→ Source and changelogs: github.com/noy-db/to
Concepts
| Page | Description |
|---|---|
choosing a store | How to pick a to-* store per platform, and the one real gap in the matrix. |
store-locator descriptors | A credentialless, JSON-serializable second construction path alongside to<Kind>() — build from data, resolve back to a live store. |
Compare
casAtomic is the load-bearing capability: whether put(expectedVersion)
fails atomically on a version mismatch, or is only an advisory check.
| Store | Atomic CAS | Shape | Best for |
|---|---|---|---|
memory | ✓ | record | tests, REPL, ephemeral caches |
file | ✗ | record | USB stick, local-first apps |
browser-idb | ✓ | record | PWAs, browser apps |
browser-local | ✗ | record | tiny vaults under 5 MB |
aws-s3 | ✓ | record + bundle | S3 object storage, blobs |
aws-dynamo | ✓ | record | single-table DynamoDB, low latency |
cloudflare-r2 | ✓ | record | zero-egress object storage |
cloudflare-d1 | ✓ | record | edge SQLite in Workers |
drive | n/a | bundle | Google Drive backup |
icloud | n/a | bundle | iCloud Drive backup (macOS) |
postgres | ✓ | record | Postgres-backed apps |
mysql | ✓ | record | MySQL 8+ / MariaDB apps |
sqlite | ✓ | record | 10K+ records, single file |
turso | ✓ | record | hosted libSQL, multi-region |
supabase | ✓ | record | existing Supabase Postgres project |
ssh | ✗ | record | SFTP servers, key-only auth |
webdav | ✗ | record | Nextcloud / ownCloud servers |
smb | ✗ | record | Windows file servers, NAS |
nfs | ✗ | record | pre-mounted NFS paths |
rest | ✓ | record | an in-rest relay over HTTP |
probe | n/a | diagnostic | benchmarking a store before committing |
meter | n/a | wrapper | production latency / error metrics |
Stores without atomic CAS are still safe as single-writer primaries or as
backup / archive targets — pair them with a CAS-capable primary (e.g.
postgres, aws-dynamo) when multiple writers are involved.