await, direct returnsThe in-memory backend supports a synchronous mirror of every CRUD method: createSync, readSync, updateSync, deleteSync, listSync, countSync. No Promises, no microtasks — useful for tight loops, tests, and synchronous event handlers where you can't await.
create, list, …) always returns a Promise, so it works on any backend.createSync, listSync, …) returns the value directly and only works when the data lives in memory — for IndexedDB and encrypted backends it throws.db.isMemoryBackend(); true means the sync methods are safe to call.Database and doesn't want to propagate async. The sync path avoids one microtask hop per call.await anyway — the sync/async perf gap disappears once you have I/O.
flowchart LR
A["db.create(...)"] --> P[Promise] --> V1[record]
S["db.createSync(...)"] --> V2[record]
S -. throws on
persistent backend .-> X[Error]
A -. works on
any backend .-> ALL[memory · IDB · encrypted]
style A fill:#fff3e0,stroke:#ef6c00
style S fill:#e0f2f1,stroke:#00897b
style X fill:#ffcdd2,stroke:#c62828
style ALL fill:#e8f5e9,stroke:#2e7d32
Seed 20 records. 20 createSync calls land in the users entity.listSync (all), listSync (filter age > 50), and listSync (sort age desc). Each returns the array immediately — no await in the handler code.Performance comparison. Runs 1000 sync creates vs 1000 async creates side by side and shows the ratio.| ID | Data | Actions |
|---|
Run all tests runs 11 steps and reports pass/fail:
isMemoryBackend() is truecreateSync returns id + _version=1readSync returns matching fieldsupdateSync bumps _version and mergesdeleteSync removes the rowlistSync returns all 20listSync with filter returns subsetlistSync with desc sort is monotoniccountSync without filter returns 20countSync with filter matches listSync length