Release notes
What changed in each version of NetlyDB.SDK, newest first: what is new, what was corrected, what behaves differently, and what to check before upgrading.
| Version | Published | Kind | In short |
|---|---|---|---|
| 1.2.0 | 31 October 2026 | Minor | Performance work, stricter recovery, data-loss corrections |
| 1.1.0 | 19 October 2026 | Minor | Clustering across machines, optional modules, safer defaults |
| 1.0.2 | 25 September 2026 | Servicing | Data-loss correction in replication snapshot bootstrap |
| 1.0.1 | 25 September 2026 | Servicing | Security correction in the Management UI file preview |
| 1.0.0 | 21 September 2026 | First release | The first certified release |
Every version so far opens stores written by every earlier version unchanged: no persisted format has changed since
1.0.0. Downgrading is not supported - keep a backup taken before upgrading, and roll back by restoring it. The assembly
version stays 1.0.0.0, so an application built against an earlier 1.x binds to a later one without
redirects.
1.2.0 - 31 October 2026
A minor release. It ships the performance and scale work, and the correctness work done since 1.1.0. Several
corrections change behaviour in states where 1.1.0 served data or ran operations it should have refused: read the
behaviour changes before upgrading. A 1.1.1 servicing release was prepared but never published; its
correction is part of 1.2.0.
Performance
- Faster full scans, indexed queries, reads by id, log replay on open, startup over a snapshot, index rebuilds and bulk loads; see Performance for the measured changes.
- Writes no longer wait for a snapshot. A snapshot copies the collection without holding writers; the longest write during a snapshot of 200,000 documents fell from about 400 ms to a few milliseconds.
- Asynchronous writes no longer hold a thread while they wait for documents reserved by another write. Before, waiting writers could exhaust the thread pool and stall the writer they were waiting for until the 30-second ordering window expired.
- Compared with 1.1.0 on the benchmark machine: 11 workloads meaningfully faster, 6 approximately unchanged, one not comparable, none slower. The release notes make no performance claim for other machines.
Data loss and durability corrected
- Recovery could open a collection at an older snapshot without acknowledged writes, and report success.
If the newest snapshot generation could not be used on reopen (damaged, missing or mismatched), recovery fell back to
an older generation and treated the shortened log as if it continued it. Now an older generation is accepted only
when the retained log still holds every write up to the state the store last published; otherwise the collection is
refused, the engine starts in
RecoveryRequired, nothing on disk is changed, and the failure names each generation and why it could not be used. A store that 1.1.0 would have opened at an older state is now refused: it has already lost those writes, so restore a backup or repair the newest generation's files. - A write reported as failed could still be stored. Under concurrent writes to a collection that was empty while its log held records, a write could be reported as safe to retry and still be committed. Recovery no longer touches writes the running pipeline owns, and the implicit reload that triggered it is removed.
- The first write after registering, importing or reopening a collection did not record the log's identity, so the next open had to write it and failed where the collection's metadata could not be written. The identity is now recorded before the first append.
Behaviour changes
- An engine that requires recovery no longer serves reads. Ordinary document and file reads, and resolving a collection, are admitted only in
ReadyandDegraded; in other states they throwNetlyDBEngineStateExceptionwith the new categoryEngineOperationCategory.Read. No collection is created while the engine is not writable. Collection names, mutation status, the recovery session and report, and the health probes stay available. Applications that read straight after startup should treat this exception as "not readable now". - A collection is not dropped while the engine refuses writes, and shutdown now waits for a drop in progress before it releases the store.
- Snapshot, checkpoint and replication-state entry points follow the engine's admission rules, including after this process has lost ownership of the store.
- A store that records a collection as dropped and still holds it requires recovery, instead of silently serving the collection and leaving it out of replication. Nothing is deleted: clear the recorded drop with
IClusterManager.ClearCollectionDrop, restart, then keep the collection or drop it again. GetCollection<T>()no longer reloads a registered collection. CallLoadSnapshot()to reload explicitly; it now waits for writes in progress, within the ordering window (30 seconds by default), and can throwTimeoutException.- A failure after a write reached the log is reported as
NetlyDBApplyExceptionwithIsDurable = true: the write is durable, so do not reissue it. - Replication follows the engine's lifecycle. A clustered node pauses replication while starting, recovering or requiring recovery, and reports its own transport impairment as
Degraded. A peer's change received while paused is refused withNetlyDBReplicationPausedExceptionand applied once the node is writable again. - Ownership is not released while an admitted operation is still running. If shutdown's drain times out, the store stays owned until the last operation finishes, so another process cannot open it while it is still being written.
Other fixes
- Independent concurrent writes to one document from one thread were refused as re-entrant. Re-entry is now judged per execution flow, across
await, so independent writes wait for each other. - A cancellation requested before a write's reservation is taken is always refused with
OperationCanceledException, and leaves nothing held.
New public API
- Recovery reconstruction details per collection - published, loaded and required positions, and every rejected snapshot generation with its reason - on
RecoverySession.ReconstructionsandRecoveryReport.Reconstructions. EngineOperationCategory.Read. Code that switches overNetlyDBEngineStateException.Categoryshould handle it.LicenseStatus.Unsupported, reported on a platform that cannot verify a license signature (none of the supported platforms). It runs as Community edition.
Compatibility
- No persisted store format changes. The recovery report file gains a
Reconstructionsmember and keeps its format version. - Package dependencies are unchanged from 1.1.0. The shared engine also carries code for the future browser runtime; nothing in this package enables it.
- The replication protocol is unchanged. Mixing 1.1.0 and 1.2.0 nodes in one cluster is not a tested configuration: upgrade every node together.
1.1.0 - 19 October 2026
A minor release: clustering across machines, optional modules that are truly optional, and safer defaults.
What's new
- Clustering across machines. A clustered node listens on the addresses its
SelfAddressresolves to, so nodes on different machines reach each other;ClusterBindAddressoverrides this. A node on a non-loopback address refuses to start without cluster TLS, unlessSecurity.AllowInsecureClusterTransportis set.EnableClusterTlsnow encrypts the control channel as well as replication. Snapshot bootstrap and clusters with a custom storage root now work. See Clustering & replication. - Optional integrations are opt-in. Starting NetlyDB no longer loads the REST API, MCP server, Management UI or Azure Blob storage provider unless you enable them. Enabling one without its packages fails at that call with
NetlyDBOptionalFeatureUnavailableException(NDB-LIFE-0064), naming the packages to add. See Packages. - Package presentation. The package carries a description, a README whose quick start is run against every release before it is published, a license notice and its release notes.
Improvements
- Security: in 1.0.x, an ASP.NET Core application that mapped its own controllers, and had the packages NetlyDB's integrations use, also served NetlyDB's entire HTTP API on its own port, without authentication. NetlyDB's assemblies no longer contribute controllers to your application.
- Package dependencies: the packages the engine needs at run time are declared directly, so an application no longer fails at first use on a missing assembly.
- gRPC listener: no longer serves generic document access, and when a cluster secret is configured every call must present it.
- Start and stop: stopping a host right after starting it no longer throws. A clustered node whose gRPC port is in use fails to start with an error naming the port. With the MCP server, start completes only once its endpoint is listening.
- Includes the corrections of 1.0.1 and 1.0.2.
Compatibility
- No persisted format changes; the replication protocol is unchanged.
- With
EnableClusterTls, 1.1.0 nodes also encrypt the control channel and cannot run beside 1.0.x nodes: upgrade every node of such a cluster together. - Applications that use the REST API, MCP server, Management UI or Azure Blob storage provider reference that integration's packages themselves.
1.0.2 - 25 September 2026
A servicing release of the 1.0 line: 1.0.1 plus one data-loss correction, and nothing else.
- An acknowledged write could be silently removed when a node bootstrapped a collection from a peer.
Clustered deployments only. When a node's copy of a collection was empty while a peer held documents, the node
replaced its contents from the peer's snapshot, and a local write in flight at that moment could be acknowledged and
then removed - on every node. The decision to replace the collection is now made only after every write in progress
has applied; when one has, the peer's snapshot is merged instead, and the node briefly reports
DestructiveRepairRefused(NDB-REPL-0031) andDegraded. - No public API, persisted format or protocol changes; 1.0.2 nodes interoperate with 1.0.0 and 1.0.1 nodes.
1.0.1 - 25 September 2026
A security servicing release of the 1.0 line: 1.0.0 plus one Management UI correction, and nothing else.
- Stored cross-site scripting in the Management UI file preview. In 1.0.0 a file in a file collection
could run script in the Management UI with the signed-in operator's session. Text and JSON previews now render as
escaped text; only common image, audio and video types are shown in the browser, and everything else is downloaded,
never opened. The file-stream endpoint sends
X-Content-Type-Options: nosniffand a restrictive content security policy. Every deployment that enables the Management UI and stores files from sources it does not fully trust should upgrade. - Resource bounds on previews. Text previews read at most 64 KiB, files over 1 MiB are not previewed, and image previews and thumbnails decode under explicit size and pixel limits. A malformed or oversized image fails closed instead of ending the operator's session.
- Behaviour change: Download original replaces Open original for files outside the image, audio and video types.
1.0.0 - 21 September 2026
The first certified release, after a dedicated engineering phase on correctness: an explicit engine lifecycle, exclusive store ownership, one durable mutation pipeline, atomically published snapshots and recovery that stops on ambiguity.
- Embedded engine for .NET 10 with typed, dynamic and named document collections, and file collections with queryable metadata.
- Durability through a checksummed write-ahead log and snapshot generations, resolvable mutation outcomes and deterministic recovery with a recovery report.
- Queries and search: LINQ and text queries, expression indexes, full-text and vector search.
- Optional modules: the Management UI, REST API and MCP server, and peer-to-peer replication between nodes on one machine.
- Security and operations: encryption at rest, authentication, licensing, diagnostic codes, health probes and metrics, and the offline CLI.
- Supported on Linux x64, Windows x64 and macOS arm64; Android arm64 is a build target only.