[1.0.0-rc8] (May 28, 2026)
May 28, 2026 · View on GitHub
Bug Fixes
- Remove duplicate profiles from wasm build workflow
[1.0.0-rc7] (May 28, 2026)
CI
- Custom build profile for wasm crate when syncing with web repo
[1.0.0-rc6] (May 27, 2026)
Docs
- Added benchmarking docs
- Added transparency docs
[1.0.0-rc5] (May 21, 2026)
Performance
$ct/$containsadded to the MsgPack fast path -- substring-match predicates (e.g.{ "model": { "$ct": "Pro" } }) now evaluate directly on raw MsgPack bytes viaevaluate_predicate_msgpackinstead of falling back to fullrmp_serdedeserialization per document. The check is case-insensitive. Crucially,$ctnow also works on array fields (e.g.{ "tags": { "$ct": "gaming" } }wheretagsis a string array) — the evaluator iterates the MsgPack array elements and returnstrueif any element contains the needle.is_fast_path_opinfetch.rsincludes$ct/$contains, so mixed WHERE clauses also avoid full deserialization.- Parallel Phase 3 decode --
get_filtered,get_allnow usepar_iter()in Phase 3 (decoding the page-sized subset of documents) instead of a sequentialiter(). Forcount: 100with heavy documents this is free parallelism — the decode work is embarrassingly parallel and scales near-linearly with available cores. The wasm32 paths remain sequential (no rayon on wasm32). - Multi-condition WHERE clauses now use the MsgPack fast path — previously, any WHERE clause with more than one condition (e.g.
{ "price": { "$gte": 1500, "$lte": 2500 } }or{ "in_stock": true, "price": { "$lt": 1000 } }) fell through to fullrmp_serdedeserialization for every document becauseextract_single_field_predicaterequired exactly one field with exactly one operator. The newextract_fast_predicateshelper flattens the entire WHERE clause into a flat list of(field, op, value)triples and evaluates them all directly on raw MsgPack bytes viaevaluate_predicate_msgpack. All conditions are AND-ed together without ever callingrmp_serde::from_slice. This covers:- Multi-operator on the same field:
{ "price": { "$gte": 1500, "$lte": 2500 } }→ two raw-byte comparisons per doc - Multi-field predicates:
{ "in_stock": true, "price": { "$lt": 1000 } }→ two raw-byte comparisons per doc - Any combination of
$eq,$ne,$in,$nin,$gt,$gte,$lt,$lteacross any number of fields
- Multi-operator on the same field:
- Full deserialization fallback preserved — clauses containing logical operators (
$or,$and) or unknown/custom operators still fall back toevaluate_wherewith full deserialization, exactly as before. - Scalar fast-path extended to
$gt/$gte/$lt/$lte--evaluate_predicate_msgpacknow handles all four numeric range operators in addition to the existing$eq/$ne/$in/$nin, so even non-SIMD paths (wasm32, prefix-filtered queries) avoid fullrmp_serdedeserialization for numeric comparisons. - Three-phase scan eliminates deserialization memory spikes --
get_filtered(native path) now runs in three distinct phases: (1) parallel predicate scan collecting only matchingStringkeys — noValueallocation; (2) sort + page-slice on the key list; (3) MsgPack decode for the page-sized subset only. For$ne/$ninqueries matching 80%+ of a large collection, this avoids materialising hundreds of thousands of decodedserde_json::Valueobjects simultaneously, eliminating the x8–x10 RSS spike previously observed on those operators. - Full MsgPack fast-path for
$ne,$in,$nin, and nested-field predicates -- extended the raw-bytes predicate evaluator (evaluate_predicate_msgpack) to cover all four common operators with full dot-notation support (e.g.specs.cpu.brand). Previously only$eqon plain top-level strings had a fast path; all other operators fell through tormp_serde::from_sliceper document, causing rayon workers to materialise the entire collection in memory simultaneously. The new path touches ~16–32 bytes per document for the common case. get_allalso uses three-phase paging -- the unfiltered path mirrors the same (seq, key) collect → sort → page → decode pattern, so sorted full-collection scans no longer decode documents that are outside the requested page window.
Bug Fixes
- Duplicate documents across paginated sorted queries --
HeapItem::Ordpreviously broke ties by sort-value only, causing non-deterministic heap eviction when multiple documents share the same sort value. Ties are now broken bykey, making the bounded heap fully deterministic. Both the rayonpush_intoguard and the wasm32 sequential path use the sameHeapItem::cmp(value + key) comparator, so eviction decisions are consistent with heap ordering.
Improvements
- wasm32 scan paths now identical to native --
get_filteredandget_allon wasm32 now use the same three-phase (collect(seq, key)-> sort by_seq-> page -> decode) pattern as the native rayon path. Previously the wasm32 branches used a streaming early-stop loop that decoded documents before paging and appliedoffset/countinline, producing non-deterministic ordering and incorrect pagination. Both targets now sort by insertion order (_seq) and decode only the page-sized subset. - Default sort order changed from
_key(alphabetical) to_seq(insertion order) -- when nosortfield is provided,get_filteredandget_allnow sort results by the document's_seqcounter before applyingoffset/count. This matches the natural-order expectation of every major document database (MongoDB, CouchDB, Firestore) and avoids surprising alphabetical ordering when keys are user-supplied strings. A newread_msgpack_seqhelper extracts_seqdirectly from raw MsgPack bytes without full deserialization; docs without_seqsort last (u64::MAXfallback).
[1.0.0-rc4] (May 19, 2026)
Performance
- Zero-copy binary predicate evaluation -- swapped
serde_jsondeserialization inget_filteredwith a rawrmpbyte-scanner. This avoids deserializing the entire document into an allocatedserde_json::Valueduring full-table scans for simple queries, vastly reducing CPU overhead and memory allocation churn, yielding ~3x faster queries on large collections.
Bug Fixes
- Tenant scoping in GET queries -- pushed
_allowed_prefixesevaluation directly intofetch_documentsand the coreget_filtered/get_allclosures. Prefix gating is now evaluated beforelimitandoffsettruncation to prevent silent query results dropping. - Pagination stability -- changed
get_filteredandget_allto returnVec<(String, Value)>instead ofHashMap. Ordered sorting based onkeyis now maintained before truncation, preventing non-deterministic pagination scrambling. - OOM on simple queries -- modified
get_allto acceptoffsetandlimitparameters, enabling early loop exit and preventing massive full-collection heap allocations on simple queries. - Early prefix gating -- improved efficiency by evaluating simple conditions (e.g.
_allowed_prefixes) on raw document keys before performing deep JSON parsing and fullWHEREpredicate evaluation. - Parameter rename -- renamed the parameter
limittocountin the core engine's GET functionality signatures (get_filteredandget_all) to match the existing naming convention across the API. - WASM: OOM on OPFS compaction -- fixed
OpfsStoragefailing to implementcompact_from_maps. The compaction process previously aggregated all documents into a massive byte vector before writing to OPFS. It now serializes documents sequentially directly from the DashMap and writes in 64KB chunks, preventing OOM crashes in the Web Worker when compacting large datasets. - WASM: OPFS storage format inconsistency -- OPFS backend (
wasm.rs) still used plain-text JSON with newline separators for logging, causing high disk usage and string encoding/decoding overhead in the browser. Aligned with native engines by switching to binary length-prefixed MessagePack (rmp_serde). The reader now streams the file in chunks instead of loading the entire log into aString, preventing Out of Memory (OOM) crashes in the browser worker on large datasets. - WASM:
time not implemented on this platformpanic -- replacedstd::time::SystemTimewithweb_time::SystemTimeinengine/operations/ttl.rsandengine/storage/disk/snapshot.rs. Both files were using the standard library time API which panics unconditionally onwasm32targets.web_timewas already a dependency ofmoltendb-core. - TTL expiry: re-inserted documents incorrectly received
_v: 2instead of_v: 1-- TTL expiry used lazy eviction (documents hidden on read but never removed from theDashMap). When the same keys were re-inserted after expiry,insert.rsfound the stale documents in memory and incremented their_vcounter. Fixed indb.insert()(engine/mod.rs): before callingoperations::insert, the engine now checks whether the target collection has expired and, if so, physically evicts it viaoperations::delete_collection(). - TTL eviction is now durable across restarts -- the previous fix cleared expired documents from memory but left the old
INSERTentries in the WAL. A process restart before compaction would replay those entries and restore the stale documents, causing the_vcounter bug to reappear. The eviction now callsoperations::delete_collection()which writes aTX_BEGIN → DROP → TX_COMMITsequence to the WAL before removing the collection from memory, so the eviction survives WAL replay. - TTL expiry now survives restarts --
ttl_expirywas a purely in-memory map that was never persisted. After a reload, the map was empty soprocess_getno longer hid expired documents — they became fully visible again. Fixed by writing aTTL_EXPIRYWAL entry each time an expiry timestamp is set, and restoring it during WAL replay inapply_entry. If the expiry has already passed at replay time, the collection is evicted from state immediately so stale documents never surface after a reload.
[1.0.0-rc3] (May 12, 2026)
Breaking Changes
_vis now fully engine-managed on/set-- clients can no longer supply_vas an optimistic-lock guard on insert. The engine always sets_v = 1for new documents and increments it on every overwrite. Any document containing a_-prefixed field on/setor/updateis now rejected with400 Bad Requestwithout exception.
Features
-
Bulk delete with
wherefilters --/deletenow accepts a"where"clause using the same filter operators as/get($eq,$ne,$gt,$gte,$lt,$lte,$contains,$in,$nin,$or,$and). The response includes a"deleted"count. Implemented via a newDb::delete_filtered()engine method (mirroringDb::get_filtered()) that uses a parallel rayon scan on native targets to collect matching keys before deleting them in a single transaction. -
Reserved
_-prefix field enforcement -- the handler layer now rejects any insert (/set) or update (/update) document that contains a field whose name starts with_, returning400 Bad Requestwith a descriptive error. This applies universally to every collection, with or without a JSON Schema registered, atO(1)cost per document. -
countdefaults to 100, max 1000 --/getand/delete(bulkwheremode) now default to returning/deleting at most 100 documents whencountis not supplied. Supplying a value greater than 1000 returns a400 Bad Requesterror. This prevents accidental full-collection scans on large datasets.
Features
POST /statsandGET /statsendpoints -- returns document counts per collection.POST /statswith{ "collection": "name" }returns stats for a single collection; omittingcollection(or usingGET /stats) returns counts for all collections plus atotal. TTL-aware: expired collections reportcount: 0andexpired: truewith theirexpiresAttimestamp. Both methods are available on the HTTP server and the WASM module (action: "stats").
Features (continued)
- TTL eviction (collection-level) -- collections can now expire automatically via a TTL registered on
POST /schemaor inline onPOST /setwith a"ttl"field (seconds). The expiry clock resets tonow + ttl_secsat the end of every insert batch -- so the clock starts when the last write commits, not when the schema was registered. On expiry the entire collection is dropped in one O(1) call._expiresAtis a virtual field -- never stored inside documents, computed from the collection TTL map and injected into every response. The background sweep task uses an event-driven min-heap with one entry per collection (not per document), sleeping until the next collection expiry. Zero CPU when idle. /schemaacceptsttlwithout requiringschema--POST /schemanow accepts"ttl"independently of"schema", allowing collection-level TTL defaults to be set on collections that have no JSON Schema validation.maxSizecapped collections -- collections can now be capped to a maximum document count viaPOST /schemawith"maxSize": Nor inline onPOST /set. After each insert batch, if the collection exceedsmaxSize, the oldest documents (lowest_seq) are evicted -- keeping exactlymaxSizedocuments at all times.maxSizeis reported inPOST /statsandGET /statsresponses._seq,_createdAt,_modifiedAt,_expiresAtare now opt-in -- these fields are no longer returned by default. They must be explicitly requested via afieldsprojection (e.g."fields": ["brand", "_createdAt"])._keyand_vremain always-present protocol primitives that cannot be suppressed.
Documentation
- Updated root
README.mdandmoltendb-core/README.mdwith a Reserved fields table documenting_key,_v,_createdAt,_modifiedAt, and_expiresAt, the_-prefix enforcement rule, and the always-returned guarantee for all five fields. Added TTL documentation covering collection-level TTL via/schema, the virtual_expiresAtfield, and the background sweep strategy. - Expanded TTL documentation in both READMEs with a sliding-window expiry design decision callout -- explicitly documenting that the TTL clock resets on every insert (not every access), that
/updatedoes not reset the clock, and that collection-level TTL is intentionally designed for ephemeral caches and analytics buffers rather than per-document expiry use cases (OTPs, reset tokens, session invalidation). Added a manual per-document expiry pattern usingPOST /deletewith awhereclause as the recommended alternative for security-sensitive expiry. - Expanded
tests/requests_9_ttl.httpwith new examples: §7 demonstrating that/updatedoes not reset the TTL clock, §8 showingwherequeries on TTL collections, and §10a/§10b showing the manual per-document expiry pattern for use cases not suited to collection-level TTL.
[1.0.0-rc2] (May 12, 2026)
Breaking Changes
- Encrypted WAL inner payload switched from JSON to MessagePack -- existing encrypted
.logfiles written byv1.0.0-rc1or earlier are not readable by this version. Delete or migrate your encrypted WAL before upgrading.
Performance
Arc<str>collection-key interning -- changed the outerDashMapkey fromStringtoArc<str>. During bulk insert and WAL replay, all documents in the same collection share a singleArc<str>pointer instead of allocating a newStringper document. Saves ~30 B per doc (~30 MB at 1M docs) and reduces allocator pressure during startup.- MessagePack in-memory storage -- switched the hot document map from
serde_json::ValuetoBox<[u8]>(MessagePack bytes). Reduces steady-state RSS for 1M docs from ~4 GB to ~500 MB (~8Ă— lower). Decoding toValuehappens lazily on read; write paths encode viarmp_serde. Full analysis inMEMORY_ANALYSIS.md. - Parallel read paths (rayon) --
get_filtered,get_all, andscan_top_nnow userayonpar_iteracross DashMap shards on native targets. MsgPack decode (the dominant cost) runs across all CPU cores. Sequential fallback retained forwasm32. - Bounded per-worker heaps in
scan_top_n-- rewrote sort-only paginated queries with rayonfold+reduceso each worker keeps its own small heap (size ≤cap). Eliminates the 1M-element intermediateVecthat caused ~7s latency on sort-only queries; peak intermediate memory drops from O(N) to O(workers × cap).
Removed (Backward Compatibility)
- Dropped JSON-lines WAL fallback --
log.rsno longer accepts the legacy JSON-lines log format. The WAL is exclusively MessagePack length-prefixed. Databases written beforev1.0.0-rc1must be migrated or discarded. - Dropped legacy snapshot format references --
MOLTSNG2(JSON body) andMOLTSNAP(uncompressed) snapshot formats were already rejected at load time; all remaining references and comments have been removed. OnlyMOLTSNG3(MsgPack + gzip) is supported.
Bug Fixes
- Eliminated memory spike during WAL replay and bulk insert -- changed
apply_entryto takeLogEntryby value so theserde_json::Valuetree inside each entry is dropped immediately after MsgPack encoding. Previously both theLogEntry(~2.4 KB Value tree) and the newBox<[u8]>(~120 B) coexisted in RAM for every entry, causing ~2Ă— peak memory during boot replay and stress inserts. - Fixed
compactmethod incorrectly placed insideimpl StorageBackend for OpfsStorage(not a trait member) -- moved to a separateimpl OpfsStorageblock inwasm.rs. - Fixed unused-variable warnings (
state,hook) in the defaultcompact_from_mapsimpl under#[cfg(not(feature = "schema"))]. - Fixed log file not being cleared after compaction on the encrypted storage path --
swap_lognow renames the.tmpfile directly on the calling thread when there is no async writer (the case whenEncryptedStoragedelegates compaction to its inner storage). - Implemented
compact_from_mapsonEncryptedStorageso the encrypted path now writes snapshots on compaction, reducing boot time from O(full WAL) to O(delta entries) -- matching the non-encrypted path behaviour.
[1.0.0-rc1] (May 9, 2026)
Breaking Changes
- Removed cold log / tiered storage --
my_database.cold.log,TieredStoragehot/cold promotion,MmapLogReader, andHOT_TIER_MAX_BYTESare gone. The--storage-mode tieredCLI flag is removed. All data now lives in a single log file + snapshot.TieredStorageis kept as a thin newtype overAsyncDiskStoragefor compatibility but does no tiering. - Removed
--hot-threshold/MOLTENDB_HOT_THRESHOLD-- the hot/cold eviction threshold no longer exists. All documents are loaded into RAM on startup.evict_collectionand theevict.rsmodule are removed. - Removed auto-indexing --
indexing.rs, theindexesfield onDb,track_query, and all INDEX log entries are removed. Queries always use full-collection scans. Indexes will be rebuilt from scratch in a future release. - Removed auto-compaction -- compaction no longer triggers automatically on write count or log size thresholds. Call
POST /snapshotexplicitly to compact. This eliminates surprise I/O spikes during bulk writes and gives full control over when the log is reset.
Performance
- Rewrote
process_get.rs-- simplified from ~500 lines to ~230 lines; removed incorrect pre-sort fast path, extractedshape_dochelper, unified sort/truncate/skip pipeline. - Added bounded heap fast path for
sort + countqueries with no joins or key filters -- onlyoffset + countdocuments ever live in RAM regardless of collection size, eliminating the memory-doubling spike previously observed on large collections (e.g. top-10 cheapest from 1M docs). - Fixed snapshot
countinflation (e.g. 979 000 instead of 100 000) caused by a race wherestream_log_intoreplayed the old pre-truncation log on top of the already-loaded snapshot. Compaction now synchronously waits for the background file swap to complete before returning via a typedWriterMsg::Compactenum + condvar.
Bug Fixes
- Fixed duplicate lines in the cold collection log --
promote_hot_to_coldwas called with the full database state (cold + hot combined) instead of only hot-tier entries. Moot after cold log removal but documented for history.
Refactor
- Removed
write_compacted_logfromdisk/log.rs-- only used by the old cold-log promotion path. - Removed re-exports of
write_compacted_logandwrite_snapshotfromdisk/mod.rs. - Deleted stale
my_database.cold.logfrom project root. - Removed stale auto-compaction references from README storage mode descriptions and the "Snapshots, Compaction & Data Safety" section.
[1.0.0-rc0] (May 7, 2026)
⚠️ WARNING: This version was nuked and never made it to the public release.
Reliability
- Implemented
AtomicBoolcircuit breaker inAsyncDiskStorageto eliminate silent data loss on background disk I/O failure -- when the background flush thread encounters a fatalwriteln!orflusherror it sets a sharedArc<AtomicBool>flag and stops accepting further writes; the core engine checks this flag at the top of everyinsert,update, anddeletecall and returnsDbError::StorageFaultimmediately if it is set, preventing the in-memory state from diverging from what is persisted on disk - Mapped
DbError::StorageFaulttoHTTP 503 Service Unavailableinprocess_set.rs-- clients now receive an explicit error response instead of a false200 OKwhen the storage layer is in a faulted state
Performance
- Removed intermediate
Vec<LogEntry>from snapshot loading path -- entries are now streamed directly into the in-memoryDashMapas they are read from disk, halving peak startup RAM usage for large snapshots (previously~2Ă—snapshot file size, now~1Ă—) - Snapshot files are now gzip-compressed using
flate2(pure Rust, WASM-compatible); typical JSON snapshots compress 3Ă—-8Ă—, significantly reducing disk usage and improving startup I/O on large datasets; magic header updated toMOLTSNG2for forward/backward compatibility -- oldMOLTSNAPsnapshots are gracefully ignored and state is rebuilt from the WAL - Added lazy
Db::get_filtered()operation that filters documents while iterating the collectionDashMap, only cloning matches; replaces the priorget_all-> filter pattern inprocess_getfor queries with WHERE but no joins. Reduces peak memory and time on sparse WHERE queries from O(total) to O(matches) -- e.g. a query returning 84 matches from 1M docs no longer clones the other 999 916 documents - Added bounded top-N streaming via
Db::scan_top_n()-- forsort + count(and optionaloffset) queries with no joins, documents are streamed directly into a max-heap of capacityoffset + countwith a peek-before-clone guard so docs that cannot beat the current worst candidate are never cloned. Peak memory is now O(offset + count) instead of O(matching_docs); eliminates the memory-doubling spike previously observed on §6 stress queries and brings response times under 1s on 1M-doc collections
Reliability
- Replaced
.unwrap()on disk I/O in the async storage background flush thread (async_storage.rs) withmatch/if let Errblocks that log errors viatracing::error!and return early -- prevents silent panics on disk-full or lost file handle conditions - Replaced
.lock().unwrap()on the WASM handle mutex inwasm.rs(6 call sites) with.lock().expect("db handle mutex poisoned")-- provides a clear, descriptive panic message if the mutex is ever poisoned by a prior panic
Refactor
- Grouped the 8 parameters of
insert()intoInsertParams<'a>struct (insert.rs) to resolve Clippy's "too many arguments" warning; re-exported fromoperations/mod.rs; all call sites updated - Grouped the 8 parameters of
update()intoUpdateParams<'a>struct (update.rs) for the same reason; re-exported fromoperations/mod.rs; all call sites updated
Code Quality
- Fixed all ~44 Clippy warnings in
moltendb-core: collapsed nestedifstatements, replaced redundant closures with direct constructor references (DbError::Serialization), removed unnecessaryOk(…?)inencrypted.rs, replacedor_insert_withwithor_default, replaced manual% 2 == 0checks with.is_multiple_of(), replaced manual suffix stripping with.strip_suffix() - Fixed all Clippy warnings in
moltendb-server,moltendb-auth, andmoltendb-wasm:or_insert_with, redundant cast, collapsibleif, unnecessaryas_ref/deref/borrow, and doc comment indentation issues - Added
#![deny(warnings)]to all four crates (moltendb-core/src/lib.rs,moltendb-auth/src/lib.rs,moltendb-wasm/src/lib.rs,moltendb-server/src/main.rs) -- future warnings are now hard compile errors
Documentation
- Updated all README files to reflect
1.0.0-rcrelease candidate status: replaced⚠️ Beta Softwarenotice with🚀 Release Candidate (v1.0.0-rc), addedstatus-1.0.0-rcbadge to all six Rust crate READMEs, corrected test count badges (88 passingroot,59 passingserver), and updated## Current limitationsheading inmoltendb-auth/README.mdfromv0.10.3tov1.0.0-rc
[0.10.3] (May 6, 2026)
Bug Fixes
- Fixed stale document state after log replay: documents were not correctly removed from in-memory state during startup replay when a
DELETEentry was encountered for a previously cold (disk-pointer) document
[0.10.2] (May 4, 2026)
Refactor
- Extracted
Db::open()(native) andDb::open_wasm()(WASM) fromengine/mod.rsinto dedicated filesengine/open.rsandengine/open_wasm.rs;engine/mod.rsnow only declares and delegates - Removed duplicate single-key
getmethod; renamedget_batchtoget-- callers now passVec<String>and receiveHashMap<String, Value>; all call sites and tests updated - Removed duplicate single-key
deletemethod; renameddelete_batchtodelete-- callers now passVec<String>; all call sites and tests updated - Renamed
insert_batchtoinsertacross the entire codebase for consistency with the newget/deletenaming - Moved
compact,evict_collection, andrecover_toimplementations fromengine/mod.rsinto dedicated filesoperations/compact.rs,operations/evict.rs, andoperations/recover.rs;engine/mod.rsis now a thin delegation layer
[0.10.1] (May 4, 2026)
Yanked due to a build issue.
[0.10.0] (May 1, 2026)
Features
- WebSocket JWT scope filtering -- each connected client only receives change events for collections their token's scopes grant
readaccess to; admin tokens (*:*:*) receive all events - WebSocket revocation enforcement at connection time -- revoked tokens are rejected immediately with a structured error (
{"error":"token_revoked", "detail":"..."}) before the connection is accepted - WebSocket revocation re-check on open connections -- a background ticker checks every 30 seconds whether the authenticated token has been revoked since the connection was opened; if so, the client receives a
token_revokederror and the connection is closed - Distinct WebSocket auth error codes -- each failure mode now returns a specific
errorcode:invalid_message,invalid_action,missing_token,invalid_token,token_revoked - Broadcast lag observability --
RecvError::Laggedevents are now logged as warnings instead of silently dropping the connection - Configurable bind host -- new
--hostCLI flag andMOLTENDB_HOSTenv var (default0.0.0.0); supports any IPv4/IPv6 address, enabling Docker and multi-interface deployments without recompilation - In-memory mode -- new
--in-memoryCLI flag andMOLTENDB_IN_MEMORYenv var; bypasses the WAL and all disk I/O entirely, turning MoltenDB into a pure RAM cache (Redis-like); compaction and revocation-file persistence are automatically skipped; a startup warning is emitted to make the ephemeral nature explicit - WASM in-memory mode --
WorkerDb.create()now accepts anin_memoryboolean as its ninth parameter; whentrue, OPFS is never opened and all data lives only in the browser's RAM -- useful for ephemeral session caches or testing without touching persistent storage
[0.9.0] (Apr 30, 2026)
Features
- configurable max keys per request for core and wasm engines (
max_keys_per_requestinDbConfig,--max-keys-per-requestCLI flag /MOLTENDB_MAX_KEYS_PER_REQUESTenv var,maxKeysPerRequestparam inMoltenDb.create()) - dev mode:
--dev-modeflag /MOLTENDB_DEV_MODEenv var -- runs the server over plain HTTP/WS instead of HTTPS/WSS, ignoring--certand--key(for local development only) - telemetry endpoints:
GET /system/health(public liveness check) andGET /system/metrics(admin-only snapshot of uptime, process memory, host RAM/disk, and database internals --hot_keys_count,hot_tier_threshold,wal_size_bytes,storage_mode)
0.8.0 (Apr 30, 2026)
Bug Fixes
- wasm error (44478a9)
Features
0.7.0 (Apr 28, 2026)
Bug Fixes
- changelog merge conflict (9f8a3fc)
Features
- post backup hook (99f95e7)
0.6.3 (Apr 28, 2026)
Features
- post backup hook (e3b0f55)
0.6.2 (Apr 27, 2026)
Bug Fixes
- add transactions to update (0c4681d)
- fix disk log issues (7b9c7a0)
- load snapshot in memory (a7b6242)
- persist delete functionality across restart (d21f56c)
- wasm compilation issues (cf7f2fd)
Features
- add timestamp metadata (65b7363)
- expose snapshot endpoint (f8a9b09)
- point in time recovery (619239d)
- schema validation (85757a2)
- versioned snapshot and backup management (0a46217)
- WAL transaction markers (51f7ecd)
0.4.0 (Apr 23, 2026)
Bug Fixes
- wasm module build (ddcae13)