> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ditto.live/llms.txt
> Use this file to discover all available pages before exploring further.

# Flutter Release Notes

<Callout icon="circle-info" color="#3B82F6" iconType="regular">
  This content is for SDK V4. For the latest version, see the [V5 documentation](/sdk/latest).
</Callout>

<Update label="4.14.6" description="Release Date: Jul 02, 2026">
  ## 4.14.6 Flutter Specific Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: `AttachmentToken.toJson()` returned `downloadedBytes` and `totalBytes` swapped on round-trip. (#SPO-888)

  ## 4.14.6 Common Changes

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: a new timeout for WebSocket connect that is adjustable by system parameter transport\_websocket\_connect\_timeout. (#21866)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: A bug in internal subscription bookkeeping caused long-connected Document Sync sessions to become disabled due to spurious capacity errors. (#SPO-1011)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: a crash caused by an unhandled SIGPIPE signal on iOS and other Unix-based platforms. (#SPO-1037)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: The replication\_session\_request\_timeout\_secs and blob\_session\_request\_timeout\_secs system parameters are no longer functional; the timeouts have been removed. They are accepted for backwards compatibility but have no effect. (#SPO-869)
</Update>

<Update label="4.14.5" description="Release Date: Jul 02, 2026">
  SDK version `4.14.5` is known to have a regression. Use `4.14.6` instead.
</Update>

<Update label="4.14.4" description="Release Date: May 08, 2026">
  ## 4.14.4 Flutter Specific Changes

  <Icon icon="triangle-exclamation" iconType="solid" horizontal /> **Deprecated**: `SmallPeerInfo.syncScope` in favor of the Sync Scopes feature, settable via DQL ALTER SYSTEM. (#21193)

  <Icon icon="triangle-exclamation" iconType="solid" horizontal /> **Deprecated**: `AuthenticationHandler` will be removed in SDK 5.0. See SDK 5.0 migration guide for authentication changes. (#SDKS-3012)

  <Icon icon="triangle-exclamation" iconType="solid" horizontal /> **Deprecated**: `DocumentID` will be removed in SDK 5.0. Use DQL queries instead. (#SDKS-3012)

  <Icon icon="triangle-exclamation" iconType="solid" horizontal /> **Deprecated**: `Identity`, `OnlinePlaygroundIdentity`, `OnlineWithAuthenticationIdentity`, `OfflinePlaygroundIdentity`, `SharedKeyIdentity`, and `ManualIdentity` in favor of `DittoConfig` and `DittoConfigBuilder` for identity configuration in SDK 5.0. (#SDKS-3012)

  <Icon icon="triangle-exclamation" iconType="solid" horizontal /> **Deprecated**: `SiteID` will be removed in SDK 5.0. (#SDKS-3012)

  <Icon icon="triangle-exclamation" iconType="solid" horizontal /> **Deprecated**: `Ditto.debugFillProperties` will be removed in SDK 5.0. (#SDKS-3012)

  <Icon icon="triangle-exclamation" iconType="solid" horizontal /> **Deprecated**: `Ditto.startSync()`, `Ditto.stopSync()`, and `Ditto.isSyncActive` will be removed in SDK 5.0. Use `ditto.sync.start()`, `ditto.sync.stop()`, and `ditto.sync.isActive` instead. (#SDKS-3012)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Transport config Duration serialization to use milliseconds instead of microseconds, fixing the retry cooldown bug where values were \~1000x too large. Also fixed `LanConfig.isMdnsEnabled` default to `true` and `HttpListenConfig.websocketSync` default to `false`. (#SDKS-3649)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: History tracking is now correctly disabled by default. Previously, the Flutter SDK unintentionally enabled history tracking, causing the `__history` local-only collection to grow without bound. Apps that used a previous version of the Flutter SDK should execute `EVICT FROM __history` during app initialization to purge accumulated history data. (#SPO-650)

  ## 4.14.4 Common Changes

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: Increase the default limit of subscriptions queries displayed in \_\_small\_peer\_info from 16 to 32. (#21085)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: A race condition where `fetchAttachment` could permanently fail to find locally-created attachments due to stale in-memory cache entries. (#21146)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: Write transaction diagnostic logs now include the blocking transaction's current operation, elapsed time, and queue depth. (#CORE-1449)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: High latency when write transactions trigger evictions. (#CORE-1453)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: More information is logged at debug level around peer GC and eviction progress including what remote peers are being deleted. (#CORE-1455)

  **Performance**: Reduced redundant replication GC work during rapid eviction bursts by debouncing and coalescing compatible GC tasks. (#CORE-1466)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: Evictions are now logged with extra detail by SP and surfaced in the system:request\_history virtual collection. (#DS-1026)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: small\_peer\_info subscription queries now include arguments. (#DS-1027)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: system:system\_info subscription queries now include arguments; query location moved from key to value.query. (#DS-1027)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: Garbage collection for document sync sessions now imposes limits on the number of disconnected sessions that will be retained, even if the TTL is not exceeded. (#DS-1065)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: v4 peers not reporting the SDK version of v5 peers in the presence viewer. (#SDKS-3090)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Transport watchdog no longer logs spurious "Address already in use" errors when restarting TCP/HTTP servers. The watchdog now waits for previous server tasks to fully exit and release their sockets before attempting to rebind ports, preventing EADDRINUSE races when servers are invalidated during e.g. app backgrounding. (#SPO-127)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Attachment garbage collection now removes empty shard directories, preventing inode leaks. (#SPO-158)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: Publish sync scopes in small peer info document. (#SPO-276)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: Ditto shutdown logging promoted to info level. (#SPO-626)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Bug which meant a Ditto starting log failed to be logged. (#SPO-626)
</Update>

<Update label="4.14.3" description="Release Date: Feb 19, 2026">
  ## 4.14.3 Flutter Specific Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: WebSocket URL configuration not working on WASM due to JSON key mismatch. (#SDKS-2679)

  ## 4.14.3 Common Changes

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: The new `transport_tcp_connect_timeout` system parameter which shortcuts long platform-based TCP connection timeouts. (#20782)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Inconsistent internal hashing of Document IDs could cause failure to sync documents. (#DS-944)
</Update>

<Update label="4.14.2" description="Release Date: Feb 05, 2026">
  ## 4.14.2 Flutter Specific Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: crashes when force-closing apps that use a connection request handler. (#SDKS-2673)

  ## 4.14.2 Common Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: A deadlock could occur where a device would fail to establish new P2P connections until restarted. (#20810)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: On-disk logs now make better use of available disk space by resuming writing to incomplete files. (#CORE-561)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: premature connection cleanup causing duplicate connections. (#NETW-1021)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: Channel open retries and watchdog to tear down VirtualConnections that never open a channel, preventing resource exhaustion from stalled peers. (#NETW-1098)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: queries in the legacy language might fail to surface documents with settable counters. (#QE-512)
</Update>

<Update label="4.14.1" description="Release Date: Jan 08, 2026">
  ## 4.14.1 Flutter Specific Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Connection request handler callback is now invoked correctly when peer connections are established. (#SDKS-2080)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: A race condition in `StoreObserver` that could throw when cancelling an observer while callbacks are still arriving. (#SDKS-2494)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: 16KB page alignment to the Flutter Android SDK. (#SDKS-2503)

  ## 4.14.1 Common Changes

  *No Specific Changes*
</Update>

<Update label="4.14.0" description="Release Date: Dec 18, 2025">
  # 4.14 - Major Data Sync Performance Improvements & DQL Settable Counter Type

  ## Major Data Sync Performance Improvements

  Ditto 4.14 delivers significant performance improvements for initial sync scenarios, achieved through intelligent batching of file system writes to minimize I/O overhead. Performance gains are visible across all document counts, with the most dramatic improvements at 100,000+ documents.

  ### Performance Impact

  Benchmarking shows substantial speed improvements during initial sync across the entire spectrum of document counts:

  #### Android (Kotlin) Performance - Results

  <img src="https://mintlify.s3.us-west-1.amazonaws.com/ditto-248bc0d1/images/v4/kotlin-initial-data-sync-4-13-vs-4-14.png" alt="Kotlin Initial Data Sync 4.13 vs 4.14" />

  | Document Count | 4.13.1  | 4.14.0  | Speed Improvement |
  | -------------- | ------- | ------- | ----------------- |
  | 100            | 5.73s   | 3.37s   | **1.7x faster**   |
  | 500            | 6.72s   | 3.62s   | **1.9x faster**   |
  | 1,000          | 7.14s   | 4.49s   | **1.6x faster**   |
  | 5,000          | 10.00s  | 6.04s   | **1.7x faster**   |
  | 10,000         | 12.98s  | 8.36s   | **1.6x faster**   |
  | 50,000         | 38.48s  | 22.23s  | **1.7x faster**   |
  | 100,000        | 82.02s  | 38.86s  | **2.1x faster**   |
  | 500,000        | 489.05s | 154.55s | **3.2x faster**   |
  | 1,000,000      | 789.35s | 328.98s | **2.4x faster**   |

  #### iOS (Swift) Performance - Results

  <img src="https://mintlify.s3.us-west-1.amazonaws.com/ditto-248bc0d1/images/v4/swift-initial-data-sync-4-13-vs-4-14.png" alt="Swift Initial Data Sync 4.13 vs 4.14" />

  | Document Count | 4.13.1  | 4.14.0  | Speed Improvement |
  | -------------- | ------- | ------- | ----------------- |
  | 100            | 2.81s   | 2.84s   | \~1x              |
  | 500            | 3.11s   | 3.09s   | \~1x              |
  | 1,000          | 3.26s   | 3.34s   | \~1x              |
  | 5,000          | 4.19s   | 3.88s   | \~1x              |
  | 10,000         | 5.03s   | 4.79s   | \~1x              |
  | 50,000         | 12.28s  | 8.74s   | **1.4x faster**   |
  | 100,000        | 22.14s  | 13.50s  | **1.6x faster**   |
  | 500,000        | 105.47s | 56.88s  | **1.9x faster**   |
  | 1,000,000      | 216.47s | 116.60s | **1.9x faster**   |

  **Key findings:**

  * **Android shows improvements at nearly all document counts**, ranging from 1.6x to 3.2x faster
  * **iOS shows the greatest improvements at 50,000+ documents**, reaching up to 1.9x faster
  * Performance benefits scale with document count, with the most dramatic improvements at 100,000+ documents

  ### What Changed

  Previous versions of Ditto wrote document updates to disk more frequently, resulting in significant I/O overhead when processing large volumes of documents during initial sync. Version 4.14 introduces intelligent write batching that:

  * **Reduces file system operations**: Groups multiple document writes into batched operations
  * **Optimizes I/O patterns**: Minimizes expensive disk seeks and flushes
  * **Maintains data integrity**: Ensures consistency guarantees while improving throughput
  * **Scales with document count**: Performance benefits increase with larger datasets

  ### When This Helps

  This optimization is particularly beneficial for:

  * Initial sync of large datasets (50,000+ documents)
  * Onboarding new devices to existing mesh networks with substantial data
  * Bulk data imports and migrations
  * Scenarios where mobile devices sync large catalogs or inventory systems

  ### Testing Methodology

  Performance benchmarks were conducted using a standardized dataset:

  * Document size: \< 1 KB (representing typical production data patterns)
  * All documents in a single collection
  * Test start: when `startSync()` is called
  * Test completion: when observer with `COUNT` statement fires with expected document count
  * Document count controlled via subscription to subset of size N
  * 15 runs per configuration with median values reported
  * Application and database reset between runs
  * Test configurations: 100, 500, 1K, 5K, 10K, 50K, 100K, 500K, 1M documents
  * Test devices: Samsung Galaxy S22 (Android) and iPhone 15 (iOS), both physical devices

  <Note>
    These results provide a general baseline. Actual performance will vary based on your specific data patterns, document sizes, network conditions, and device characteristics. We recommend validating performance against your own use cases.
  </Note>

  ## DQL Settable Counter Type

  Ditto 4.14 introduces `COUNTER`, a new CRDT type that extends the capabilities of the legacy `PN_COUNTER` with the ability to explicitly set counter values. While maintaining the same conflict-free increment and decrement operations, settable counters add a powerful `RESTART` operation that uses last-write-wins semantics.

  ### What's New

  The `COUNTER` type provides three operations:

  * **INCREMENT BY**: Add or subtract integer values from the counter (same as PN\_COUNTER)
  * **RESTART WITH**: Explicitly set the counter to a specific integer value using last-write-wins semantics
  * **RESTART**: Reset the counter to zero

  This makes counters ideal for scenarios requiring both distributed counting and periodic resets, such as:

  * Inventory counts that need recalibration when receiving shipments
  * Like/vote counts with administrative reset capabilities
  * Session or usage metrics that require initialization to specific values

  ### Usage

  Increment a counter:

  ```sql theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
  UPDATE COLLECTION products (stock_count COUNTER)
  APPLY stock_count INCREMENT BY 5
  WHERE _id = '123'
  ```

  Set counter to a specific value:

  ```sql theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
  UPDATE COLLECTION products (stock_count COUNTER)
  APPLY stock_count RESTART WITH 100
  WHERE _id = '123'
  ```

  Reset counter to zero:

  ```sql theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
  UPDATE COLLECTION products (stock_count COUNTER)
  APPLY stock_count RESTART
  WHERE _id = '123'
  ```

  ### Migration from PN\_COUNTER

  The `PN_COUNTER` type remains available for backward compatibility but is now considered legacy. For new implementations, use `COUNTER` to take advantage of the set and reset capabilities.

  If you have existing applications using `PN_COUNTER` and want to migrate to `COUNTER`, please contact our customer support team for guidance, as migrating between CRDT types requires careful planning.

  ## Additional Improvements

  ### Reliability & Error Handling

  * **Enhanced error recovery**: Additional recovery mechanisms for document deserialization errors, reducing potential crashes and data loss scenarios
  * **Improved diagnostics**: More detailed logging when peers receive data that cannot be deserialized due to hash mismatches, making issues easier to troubleshoot

  ### Bug Fixes & Stability

  * **Fixed**: DQL SELECT queries on indexed collections could deadlock when executed in an explicit transaction
  * **Fixed**: Index path query plans now consistently preserve document IDs across runs
  * **Documentation**: Corrected on-disk logger retention documentation (actual retention is 15 days, not 3 days)

  ## 4.14.0 Full Change Log

  <AccordionGroup>
    <Accordion title="Common Changes">
      **Performance**: Improved the underlying representation of Ditto documents for better performance. (feat(crdt): Improve in-memory format for CRDT documents, introduce feature flag for rkyv-encoded documents #17509)

      **Performance**: Document synchronization between peers now batches updates more efficiently, reducing processing time for large document sets. (Batching pt 4: Sync engine batches document diffs and document metadata #19273)

      <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: More information is logged when a Ditto peer receives data that it cannot deserialize due to a hash mismatch. (#CORE-897)

      <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: We now make an additional attempt to recover from some kinds of document deserialization errors, which may reduce errors or crashes due to deserialization. (#CORE-916)

      <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: Document sync protocol now supports rkyv-encoded diffs, for more efficient initial synchronization. (#DS-531)

      <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: DQL SELECT queries on indexed collections could deadlock if executed in an explicit transaction. (#DS-648)

      <Icon icon="plus" iconType="solid" horizontal /> **Added**: COUNTER data type and APPLY clause syntax in UPDATE statements for settable COUNTER field modifications. (#QE-426)

      <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Make sure that index path query plan preserve document ids across runs. (#QE-429)

      <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Documentation for on-disk logger incorrectly stated logs are retained for 3 days; actual retention is 15 days. (#SDKS-1726)
    </Accordion>
  </AccordionGroup>
</Update>

<Update label="4.13.4" description="Release Date: May 08, 2026">
  ## 4.13.4 Flutter Specific Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: crashes when force-closing apps that use a connection request handler. (#SDKS-2673)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Transport config Duration serialization to use milliseconds instead of microseconds, fixing the retry cooldown bug where values were \~1000x too large. Also fixed `LanConfig.isMdnsEnabled` default to `true` and `HttpListenConfig.websocketSync` default to `false`. (#SDKS-3468)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: History tracking is now correctly disabled by default. Previously, the Flutter SDK unintentionally enabled history tracking, causing the `__history` local-only collection to grow without bound. Apps that used a previous version of the Flutter SDK should execute `EVICT FROM __history` during app initialization to purge accumulated history data. (#SPO-650)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: `AttachmentToken.toJson()` returned `downloadedBytes` and `totalBytes` swapped on round-trip. (#SPO-887)

  ## 4.13.4 Common Changes

  **Performance**: Disk usage monitor now runs on a dedicated thread, reducing blocking operations that might impact performance. (#20191)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: A deadlock could occur where a device would fail to establish new P2P connections until restarted. (#20810)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: Increase the default limit of subscriptions queries displayed in \_\_small\_peer\_info from 16 to 32. (#21085)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: A race condition where `fetchAttachment` could permanently fail to find locally-created attachments due to stale in-memory cache entries. (#21146)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: The thread ID is now included in small peer console logs. (#CORE-1201)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: Query engine operator execution logs now identify which operator is being executed. (#CORE-1266)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: The number of tokio worker and/or blocking threads can now be configured by setting the `DITTO_TOKIO_WORKER_THREADS` and `DITTO_TOKIO_BLOCKING_THREADS` environment variables. (#CORE-1273)

  **Performance**: Store observer no longer re-queries unrelated collections when writes occur. (#CORE-1389)

  **Performance**: Observers using a single ID equality builder query now shortcut all query execution and get the document directly in constant time. (#CORE-1433)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: Write transaction diagnostic logs now include the blocking transaction's current operation, elapsed time, and queue depth. (#CORE-1449)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: High latency when write transactions trigger evictions. (#CORE-1453)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: More information is logged at debug level around peer GC and eviction progress including what remote peers are being deleted. (#CORE-1455)

  **Performance**: Reduced redundant replication GC work during rapid eviction bursts by debouncing and coalescing compatible GC tasks. (#CORE-1466)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: More information is logged when a Ditto peer receives data that it cannot deserialize due to a hash mismatch. (#CORE-897)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: We now make an additional attempt to recover from some kinds of document deserialization errors, which may reduce errors or crashes due to deserialization. (#CORE-916)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: Evictions are now logged with extra detail by SP and surfaced in the system:request\_history virtual collection. (#DS-1026)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: small\_peer\_info subscription queries now include arguments. (#DS-1027)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: system:system\_info subscription queries now include arguments; query location moved from key to value.query. (#DS-1027)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: Garbage collection for document sync sessions now imposes limits on the number of disconnected sessions that will be retained, even if the TTL is not exceeded. (#DS-1065)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: premature connection cleanup causing duplicate connections. (#NETW-1021)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: Channel open retries and watchdog to tear down VirtualConnections that never open a channel, preventing resource exhaustion from stalled peers. (#NETW-1098)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: Automatic generation of USE IDS clause from \_id equality predicates when possible. (#QE-313)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: Periodic dumping of the Query Engine system:request\_history cache to the Ditto log for debugging purposes. (#QE-583)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: Diff scans are now enabled by default for observer queries that contain `ORDER BY` clauses. (#QE-729)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: v4 peers not reporting the SDK version of v5 peers in the presence viewer. (#SDKS-3089)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: Publish sync scopes in small peer info document. (#SPO-276)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: Ditto shutdown logging promoted to info level. (#SPO-626)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Bug which meant a Ditto starting log failed to be logged. (#SPO-626)
</Update>

<Update label="4.13.3" description="Release Date: Jan 26, 2026">
  ## 4.13.3 Common Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Connection manager now correctly cleans up orphaned connecting state when tasks are cancelled during shutdown (e.g., during auth refresh), preventing "Already connecting" errors on reconnection. (#20377)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: queries in the legacy language might fail to surface documents with settable counters. (#QE-512)
</Update>

<Update label="4.13.2" description="Release Date: Dec 23, 2025">
  ## 4.13.2 Flutter Specific Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Connection request handler callback is now invoked correctly when peer connections are established. (#SDKS-2080)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: 16KB page alignment to the Flutter Android SDK. (#SDKS-2484)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: A race condition in `StoreObserver` that could throw when cancelling an observer while callbacks are still arriving. (#SDKS-2494)

  ## 4.13.2 Common Changes

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: On-disk logs now make better use of available disk space by resuming writing to incomplete files. (#CORE-561)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: DQL queries using indexes could yield wrong results upon document deletion. (#DS-851)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: When another peer crashes, Ditto will stop attempting to connect to it in under 15 seconds. Previously, connection attempts would occur for up to 75 minutes at 5 second intervals. (#NETW-856)
</Update>

<Update label="4.13.1" description="Release Date: Nov 26, 2025">
  ## 4.13.1 Common Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: DQL SELECT queries on indexed collections could deadlock if executed in an explicit transaction. (#DS-648)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Documentation for on-disk logger incorrectly stated logs are retained for 3 days; actual retention is 15 days. (#SDKS-1726)
</Update>

<Update label="4.13.0" description="Release Date: Nov 10, 2025">
  ## 4.13 Flutter Improvements - Support for Windows

  Ditto 4.13 brings full support for Windows desktop applications in Flutter, expanding the range of platforms where you can deploy Ditto-powered apps.

  ### What's New

  The Flutter SDK now includes native Windows support, allowing you to build desktop applications that leverage Ditto's sync capabilities on Windows platforms.

  ### Getting Started

  Windows support works seamlessly with your existing Flutter Ditto integration. Simply target Windows as a build platform and Ditto will work as expected with all the features you're already using on other platforms, including:

  * Local data persistence
  * Peer-to-peer sync over LAN
  * Cloud sync via the Big Peer
  * DQL queries and observers
  * Attachments

  No code changes are required to add Windows support to your existing Flutter applications—just build for the Windows platform.

  ## 4.13 - DQL Index Enhancements, Observability & Performance

  ## DQL INDEX Support for Union & Intersect Scans

  Ditto 4.13 introduces advanced index utilization for complex query predicates, enabling significant performance improvements for local queries and observer registrations.

  ### What's Available

  The query optimizer can now leverage indexes when evaluating queries with `OR`, `IN`, and `AND` operators through union and intersect scans:

  * **Union Scans**: When using `OR` or `IN` operators, the query engine can now use multiple indexes simultaneously, combining results from each index scan. For example, a query like `WHERE status = 'active' OR priority = 'high'` can use separate indexes on both `status` and `priority` fields.

  * **Intersect Scans**: For queries with multiple `AND` conditions, the engine can use multiple indexes and intersect their results, efficiently narrowing down matches. For example, `WHERE category = 'urgent' AND assignee = 'user123'` can leverage indexes on both fields.

  ### Performance Impact

  These optimizations can dramatically reduce query execution time for complex predicates, especially on large datasets. Instead of scanning entire collections, Ditto now uses indexes to quickly locate relevant documents.

  **Query Selectivity Matters**

  The performance improvement from these index optimizations is inversely related to the selectivity of your query—that is, the percentage of documents returned:

  * **Highly selective queries** (returning a small percentage of documents) see the most dramatic improvements. For example, a query that returns only 10% of a collection can be approximately 90% faster, as the index allows skipping the other 90% of documents entirely.
  * **Less selective queries** (returning a large percentage of documents) benefit less from indexes, since most documents still need to be examined.

  This relationship holds true for both union and intersect scans. Indexes work best when they can efficiently eliminate large portions of the collection from consideration.

  ### Usage Example

  Here's how union scans work in practice. First, create indexes on the fields you'll query:

  ```sql theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
  CREATE INDEX movies_runtime ON movies (runtime)
  CREATE INDEX movies_year ON movies (_id.year)
  ```

  Now run a query with an `OR` condition and use `EXPLAIN` to see the query plan:

  ```sql theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
  EXPLAIN SELECT * FROM movies WHERE runtime > 200 OR _id.year = 2000
  ```

  The query plan shows a `unionScan` operator that leverages both indexes:

  ```json title="EXPLAIN Result" expandable theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
  {
    "plan": {
      "#operator": "sequence",
      "children": [
        {
          "#operator": "unionScan",
          "children": [
            {
              "#operator": "indexScan",
              "collection": "movies",
              "datasource": "default",
              "desc": {
                "index": "movies_runtime",
                "spans": [
                  {
                    "index_key": {
                      "direction": "asc",
                      "include_missing": true,
                      "key": ["runtime"]
                    },
                    "range": {
                      "low": {
                        "included": false,
                        "value": 200
                      }
                    }
                  }
                ]
              }
            },
            {
              "#operator": "indexScan",
              "collection": "movies",
              "datasource": "default",
              "desc": {
                "index": "movies_year",
                "spans": [
                  {
                    "index_key": {
                      "direction": "asc",
                      "include_missing": true,
                      "key": ["_id", "year"]
                    },
                    "range": {
                      "high": {
                        "included": true,
                        "value": 2000
                      },
                      "low": {
                        "included": true,
                        "value": 2000
                      }
                    }
                  }
                ]
              }
            }
          ]
        },
        {
          "#operator": "fetch",
          "collection": "movies",
          "datasource": "default"
        },
        {
          "#operator": "filter",
          "condition": "((`runtime` > 200) OR (`_id`.`year` = 2000))"
        }
      ]
    }
  }
  ```

  The `unionScan` operator combines results from both `indexScan` operations—one scanning the `movies_runtime` index for documents with `runtime > 200`, and another scanning the `movies_year` index for documents where `_id.year = 2000`. This is significantly faster than scanning the entire collection.

  ### Scope & Limitations

  **This optimization applies to:**

  * Local DQL queries (`store.execute(...)`)
  * Observer registrations (`store.registerObserver(...)`)

  **This does NOT apply to:**

  * Sync subscriptions (which use a different evaluation mechanism)

  Sync subscriptions continue to work as before and are not affected by these local query optimizations.

  ## Data Sync Performance Improvements

  Ditto 4.13 includes significant optimizations for peer-to-peer sync reconnection scenarios, particularly when peers have accumulated changes while disconnected.

  ### Intelligent Session Resync

  When two previously synced peers reconnect after a period of disconnection, Ditto now intelligently detects when a full session resync (summary re-exchange) is more efficient than sending incremental updates. This avoids transmitting large, redundant diff-bearing updates that can slow down the sync process.

  **Key improvements:**

  * **Backlog-based detection**: The sync engine now tracks the size of pending changes (diff backlog) and automatically triggers session resync when the backlog exceeds a configurable threshold
  * **Faster reconnection**: By requesting a fresh session basis instead of sending accumulated diffs, peers can resynchronize more efficiently when they've been apart for extended periods
  * **Reduced redundant data transfer**: Eliminates unnecessary transmission of large update files containing redundant document changes
  * **Configurable threshold**: A new system parameter allows tuning when session resync should be triggered based on your application's sync patterns

  **When this helps:**

  This optimization is particularly beneficial in scenarios where:

  * Mobile devices reconnect after extended offline periods
  * Network interruptions cause peers to accumulate substantial local changes
  * Peers with large datasets reconnect after diverging significantly

  The result is faster sync completion times and reduced bandwidth usage during reconnection, especially noticeable when the document store has accumulated many changes during disconnection.

  ## New System Collection: `system:system_info`

  Ditto 4.13 introduces a new read-only system collection `system:system_info` that provides diagnostic and observability data about your Ditto instance. This collection logs key-value pairs with timestamps, allowing you to query runtime information, configuration, and performance metrics.

  ### What's Available

  The `system:system_info` collection tracks various categories of information:

  <AccordionGroup>
    <Accordion title="SDK Metadata">
      SDK version, commit hash, language, and platform

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "ditto_sdk_version",
        "namespace": "core",
        "timestamp": 1762469332,
        "value": "4.13.0-rc.2"
      }
      ```

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "ditto_sdk_commit",
        "namespace": "core",
        "timestamp": 1762469332,
        "value": "ca86b11de2"
      }
      ```

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "ditto_sdk_language",
        "namespace": "core",
        "timestamp": 1762469332,
        "value": "JavaScript"
      }
      ```

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "ditto_sdk_platform",
        "namespace": "core",
        "timestamp": 1762469332,
        "value": "macOS"
      }
      ```
    </Accordion>

    <Accordion title="Filesystem Metrics">
      Total device storage and available space, plus storage usage broken down by component (store, attachments, replication, auth)

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "fs_device_available",
        "namespace": "core",
        "timestamp": 1762469347,
        "value": 370601351103
      }
      ```

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "fs_device_total",
        "namespace": "core",
        "timestamp": 1762469347,
        "value": 994662584320
      }
      ```

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "fs_usage_store",
        "namespace": "core",
        "timestamp": 1762469347,
        "value": 1225401728
      }
      ```

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "fs_usage_attachment",
        "namespace": "core",
        "timestamp": 1762469347,
        "value": 4861774
      }
      ```

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "fs_usage_replication",
        "namespace": "core",
        "timestamp": 1762469347,
        "value": 52129130
      }
      ```

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "fs_usage_auth",
        "namespace": "core",
        "timestamp": 1762469347,
        "value": 8649
      }
      ```

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "fs_usage_total",
        "namespace": "core",
        "timestamp": 1762469347,
        "value": 1300317779
      }
      ```
    </Accordion>

    <Accordion title="Transport Configuration">
      Complete snapshot of enabled transports and their settings, connection endpoints (WebSocket URLs, TCP servers), and peer-to-peer transport settings (Bluetooth LE, LAN, AWDL, etc.)

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "transport_config",
        "namespace": "core",
        "timestamp": 1762468011,
        "value": {
          "peer_to_peer": {
            "bluetooth_le": { "enabled": true },
            "lan": { "enabled": true, "mdns_enabled": true }
          }
        }
      }
      ```
    </Accordion>

    <Accordion title="System Parameters">
      Non-default configuration parameters and collection sync scopes

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "non_default_system_parameter[dql_strict_mode]",
        "namespace": "core",
        "timestamp": 1762468011,
        "value": false
      }
      ```

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "non_default_system_parameter[user_collection_sync_scopes]",
        "namespace": "core",
        "timestamp": 1762468011,
        "value": {
          "benchmark_baselines": "LocalPeerOnly",
          "movies": "LocalPeerOnly"
        }
      }
      ```
    </Accordion>

    <Accordion title="Store Metrics">
      Document counts per collection

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "collection_num_docs[orders]",
        "namespace": "store",
        "timestamp": 1762469342,
        "value": 5030
      }
      ```

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "collection_num_docs[menus]",
        "namespace": "store",
        "timestamp": 1762469342,
        "value": 780
      }
      ```

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "collection_num_docs[__collections]",
        "namespace": "store",
        "timestamp": 1762469342,
        "value": 29
      }
      ```

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "collection_num_docs[__presence]",
        "namespace": "store",
        "timestamp": 1762469342,
        "value": 5
      }
      ```
    </Accordion>

    <Accordion title="Active Subscriptions">
      Local observer subscriptions currently registered

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "local_subscriptions[SELECT * FROM orders]",
        "namespace": "replication",
        "timestamp": 1762469332,
        "value": null
      }
      ```

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "local_subscriptions[SELECT * FROM menus]",
        "namespace": "replication",
        "timestamp": 1762469332,
        "value": null
      }
      ```

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "local_subscriptions[SELECT * FROM COLLECTION __presence WHERE v == 3 && t > 1762387200000]",
        "namespace": "replication",
        "timestamp": 1762469332,
        "value": null
      }
      ```
    </Accordion>

    <Accordion title="Connectivity">
      Active peer connections by transport type (Bluetooth, LAN, P2P WiFi, WebSocket, Access Point), cloud connection status, and device name

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "connections_bluetooth",
        "namespace": "presence",
        "timestamp": 1760652643,
        "value": 0
      }
      ```

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "connections_p2pwifi",
        "namespace": "presence",
        "timestamp": 1760966174,
        "value": 2
      }
      ```

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "connections_websocket",
        "namespace": "presence",
        "timestamp": 1760652643,
        "value": 0
      }
      ```

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "connections_accesspoint",
        "namespace": "presence",
        "timestamp": 1760968133,
        "value": 2
      }
      ```

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "is_connected_to_ditto_cloud",
        "namespace": "presence",
        "timestamp": 1762469340,
        "value": true
      }
      ```

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "device_name",
        "namespace": "presence",
        "timestamp": 1762469339,
        "value": "DTO-A116"
      }
      ```
    </Accordion>

    <Accordion title="Logging Configuration">
      Whether logging is enabled and minimum log level

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "enabled",
        "namespace": "logs",
        "timestamp": 1762469332,
        "value": false
      }
      ```

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "minimum_level",
        "namespace": "logs",
        "timestamp": 1762469332,
        "value": "WARN"
      }
      ```
    </Accordion>

    <Accordion title="Eviction on Deleted Documents (Reaper)">
      Last reaper execution time and number of tombstones reaped

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "last_reap_time",
        "namespace": "reaper",
        "timestamp": 1760909557,
        "value": "2025-10-19T21:32:37.211Z"
      }
      ```

      ```json theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
      {
        "key": "num_tombstones_reaped",
        "namespace": "reaper",
        "timestamp": 1760909557,
        "value": 0
      }
      ```
    </Accordion>
  </AccordionGroup>

  ### Usage

  Query the collection using standard DQL:

  ```sql theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
  SELECT * FROM system:system_info
  WHERE key LIKE 'collection_num_docs%'
  ```

  This collection is useful for debugging, monitoring storage usage, and understanding your Ditto instance configuration at runtime.

  ## Additional Improvements

  ### Connection & Network Reliability

  * **Smarter logging**: Connection failures now use adaptive log levels, starting at warning and escalating to error only after repeated failures, reducing log noise during temporary network issues
  * **Parallel connections**: TCP client now attempts to connect to all discovered addresses in parallel for faster, more reliable connections
  * **mDNS optimization**: mDNS now only advertises connectable addresses based on TCP server binding configuration
  * **Callback handling**: Fixed issue where long-running connection callbacks could cause timeout failures

  ### Attachment Access Improvements

  * **Fixed attachment retrieval**: Resolved an issue where attachment requests would sometimes fail to resolve even when the attachment was available locally, making attachment access more reliable

  ### Bug Fixes & Stability

  * Fixed memory leak in disk usage monitoring
  * Fixed bug causing small peers to re-upload logs on every startup
  * Fixed post-eviction cleanup to properly retain metadata for non-evicted documents in disconnected sync sessions
  * Improved logging for document deserialization errors

  ## 4.13 Full Change Log

  <AccordionGroup>
    <Accordion title="Flutter Specific Changes">
      <Icon icon="plus" iconType="solid" horizontal /> **Added**: Support for Windows Platform

      <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: crash when force-closing iOS apps (#SDKS-1652)
    </Accordion>

    <Accordion title="Common Changes">
      <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: disk usage monitoring no longer leaks memory. (#18531)

      <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: Connection failures now use smart log levels, starting at warning and escalating to error only after repeated failures. (#18779)

      <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: mDNS now only advertises connectable addresses based on TCP server binding address. TCP Client now attempts to connect to all addresses in parallel (#18930)

      <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: the default value of `ENABLE_ATTACHMENT_PERMISSION_CHECKS` store configuration parameter to `false` (#18931)

      <Icon icon="plus" iconType="solid" horizontal /> **Added**: `system:system_info` virtual collection for DQL access to system info (#CORE-751)

      <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: A bug that caused small peers to re-upload remotely requested logs on every startup (#CORE-810)

      **Performance**: Document sync avoids sending large, redundant updates after reconnecting a long-dormant session between two peers that are otherwise well-synced with the mesh. (#DS-433)

      <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: Improved avoidance of large redundant doc sync updates after session reconnect, based on the number of diffs sent in the initial post-reconnect update. (#DS-475)

      <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Post eviction cleanup of disconnected document sync sessions now retains metadata for non-evicted documents. (#DS-487)

      <Icon icon="plus" iconType="solid" horizontal /> **Added**: Improved logging for document deserialization errors (#DS-568)

      <Icon icon="plus" iconType="solid" horizontal /> **Added**: UNION & INTERSECT scans. (#QE-398)

      <Icon icon="plus" iconType="solid" horizontal /> **Added**: Index support for array-based `IN` and `NOT IN` filter expressions in DQL queries. (#QE-417)

      <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: A long-running on connecting callback no longer causes `ReceiveTimeout` failures in connectivity. (#TRAN-729)
    </Accordion>
  </AccordionGroup>
</Update>

<Update label="4.12.5" description="Release Date: Mar 31, 2026">
  ## 4.12.5 Common Changes

  **Performance**: Disk usage monitor now runs on a dedicated thread, reducing blocking operations that might impact performance. (#20191)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: A deadlock could occur where a device would fail to establish new P2P connections until restarted. (#20810)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: A race condition where `fetchAttachment` could permanently fail to find locally-created attachments due to stale in-memory cache entries. (#21146)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: The thread ID is now included in small peer console logs. (#CORE-1201)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: Query engine operator execution logs now identify which operator is being executed. (#CORE-1266)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: The number of tokio worker and/or blocking threads can now be configured by setting the `DITTO_TOKIO_WORKER_THREADS` and `DITTO_TOKIO_BLOCKING_THREADS` environment variables. (#CORE-1273)

  **Performance**: Store observer no longer re-queries unrelated collections when writes occur. (#CORE-1389)

  **Performance**: Observers using a single ID equality builder query now shortcut all query execution and get the document directly in constant time. (#CORE-1433)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: Write transaction diagnostic logs now include the blocking transaction's current operation, elapsed time, and queue depth. (#CORE-1449)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: High latency when write transactions trigger evictions. (#CORE-1453)

  **Performance**: Improved write performance during rapid eviction bursts by coalescing redundant garbage collection jobs that competed for CPU and disk I/O. (#CORE-1453)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: More information is logged at debug level around peer GC and eviction progress including what remote peers are being deleted. (#CORE-1455)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: More information is logged when a Ditto peer receives data that it cannot deserialize due to a hash mismatch. (#CORE-897)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: We now make an additional attempt to recover from some kinds of document deserialization errors, which may reduce errors or crashes due to deserialization. (#CORE-916)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: Automatic generation of USE IDS clause from \_id equality predicates when possible. (#QE-313)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: Periodic dumping of the Query Engine system:request\_history cache to the Ditto log for debugging purposes. (#QE-583)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: A long-running on connecting callback no longer causes `ReceiveTimeout` failures in connectivity. (#TRAN-729)
</Update>

<Update label="4.12.4" description="Release Date: Oct 29, 2025">
  ## 4.12.4 Flutter Specific Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: crash when force-closing iOS apps (#SDKS-1652)

  ## 4.12.4 Common Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: disk usage monitoring no longer leaks memory. (#18531)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: mDNS now only advertises connectable addresses based on TCP server binding address. TCP Client now attempts to connect to all addresses in parallel. (#18930)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: a bug that caused small peers to re-upload remotely requested logs on every startup. (#CORE-810)
</Update>

<Update label="4.12.3" description="Release Date: Oct 09, 2025">
  ## 4.12.3 Common Changes

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: Enabled opentelemetry tracing in core. (#18464)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: An issue where peers could fail to connect other local peers via mDNS on macOS. (#18488)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: a bug that meant document id indexes were not created. (#18512)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Document sync session metadata became unlinked after session reset. (#DS-509)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: Improved logging for document deserialization errors. (#DS-568)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: query vitals. (#QE-296)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Performance of the DQL parser for large statements. (#QE-321)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Issue with planner picking an index when an `OR` is present in a statement's predicate leading to partial results. (#QE-373)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Planner not selecting an index for `_id` field filters. (#QE-374)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Android devices that fail to acquire an IP address will now continue to sync over LAN. (#TRAN-725)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: A long-running on-connecting callback no longer causes `ReceiveTimeout` failures in connectivity. (#TRAN-729)
</Update>

<Update label="4.12.2" description="Release Date: Sep 30, 2025">
  ## 4.12.2 Common Changes

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: Explicit log flushing before aborting due to panic (#CORE-723)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: on-disk log file limits now apply to the compressed size, significantly increasing log retention (#CORE-729)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: A rare scenario where an attachment fetch could be delayed by up to 60 seconds. (#DS-461)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: query vitals (#QE-296)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: use deterministic summaries for documents created by observers (#QE-310)
</Update>

<Update label="4.12.1" description="Release Date: Sep 03, 2025">
  ## 4.12.1 Common Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: A bug where x509 refresh could speed up uncontrollably. (#17947)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: A bug where a peer could get stuck with incorrect connection information. (#17967)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: `ENABLE_ATTACHMENT_PERMISSION_CHECKS` ALTER SYSTEM parameter to be set to `false` to avoid certain rare cases of attachment fetcher hanging (#18016)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Network connections close gracefully when Ditto is stopped. (#18053)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: The `system:data_sync_info` collection may briefly report sync immediately after connecting (#18137)

  **Other**: improve error reporting for document (de)serialization (#18165)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Live queries being unable to use indices. (#DS-447)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Use of DISTINCT with ORDER BY & OFFSET/LIMIT. (#QE-281)
</Update>

<Update label="4.12.0" description="Release Date: Aug 14, 2025">
  ## 4.12 - DQL Enhancements & Platform Expansion

  Version 4.12 brings significant enhancements to DQL (Ditto Query Language) with production-ready projections and aggregates, expanded platform support with Flutter for Linux and macOS, and marks the deprecation of legacy query builder APIs in preparation for DQL as the primary interface.

  ## DQL Projections & Aggregates

  DQL projections and aggregates are now out of preview and fully production-ready. These powerful features enable sophisticated data analysis and optimized query performance directly within DQL.

  ### Projections

  Select specific fields and create calculated columns to reduce data transfer and processing:

  ```sql DQL theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
  -- Select specific fields
  SELECT make, model, year FROM cars

  -- Create calculated fields with aliases
  SELECT make, model, price * 0.9 AS discounted_price FROM cars

  -- Remove duplicates
  SELECT DISTINCT color FROM cars
  ```

  ### Aggregate Functions

  Perform calculations across multiple documents with SQL-standard aggregate functions:

  ```sql DQL theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
  -- Count documents
  SELECT COUNT(*) AS total_cars FROM cars

  -- Calculate statistics
  SELECT 
    AVG(price) AS avg_price,
    MIN(price) AS lowest_price,
    MAX(price) AS highest_price,
    SUM(price) AS total_value
  FROM cars

  -- Group and aggregate
  SELECT make, COUNT(*) AS models, AVG(price) AS avg_price
  FROM cars
  GROUP BY make
  HAVING COUNT(*) > 3
  ```

  <Tip>For complete documentation, see [DQL SELECT operations](/dql/select)</Tip>

  ## DQL Index Management

  Create and manage indexes directly through DQL for improved query performance:

  ```sql DQL theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
  -- Create an index
  CREATE INDEX idx_cars_make ON cars (make)

  -- Drop an index
  DROP INDEX idx_cars_make ON cars

  -- View all indexes
  SELECT * FROM system::dql_indexes
  ```

  <Tip>For complete documentation, see [DQL Indexing](/dql/indexing)</Tip>

  ## Flutter Platform Expansion

  ### Linux Support

  Flutter developers can now build and deploy Ditto-powered applications on Linux desktops:

  * Native Linux binary (`libdittoffi.so`) included
  * Full support for development, testing, and production deployments
  * Configurable binary path via `$LIBDITTOFFI_PATH` environment variable
  * Compatible with Flutter's standard Linux development workflow

  <Tip>See [Flutter Install Guide](/sdk/latest/install-guides/flutter) for Linux setup instructions</Tip>

  ## Legacy Query Builder Deprecation

  The entire legacy query builder API is deprecated across all SDKs. Developers should migrate to DQL for all data operations:

  **Migration Benefits:**

  * SQL-like syntax familiar to developers
  * Unified interface for all data operations
  * Better performance and optimization
  * More powerful query capabilities

  <Warning>
    Legacy query builder APIs will be removed in SDK v5. Start migrating to DQL now using the [migration guide](https://docs.ditto.live/dql/legacy-to-dql-adoption).
  </Warning>

  ## Additional Enhancements

  ### System Improvements

  * **Enhanced disk observer**: Now enabled at startup with configurable batch settings
  * **Improved error handling**: Better error propagation and syntax error identification in DQL
  * **Memory optimizations**: Reduced memory usage for aggregate operations and projections

  ### DQL Function Additions

  * Duration scalar functions for date/time calculations
  * Dynamic field references in queries
  * Support for arrays as operation values
  * Extended multiplication operations for better numeric handling

  ### Security & Diagnostics

  * Support for `SSLKEYLOGFILE` for debugging TLS connections
  * New `system::data_sync_info` virtual collection for sync diagnostics
  * Transport diagnostics APIs across multiple SDKs

  ## Upgrading to 4.12

  To take advantage of these new features:

  1. Update your SDK to version 4.12.0 or later
  2. Begin migrating legacy query builder code to DQL
  3. Explore projections and aggregates for query optimization
  4. Consider Flutter Linux support for desktop deployments

  <Note>
    Version 4.12 maintains full backward compatibility while encouraging migration to modern DQL APIs. Legacy APIs continue to function but should be replaced in preparation for SDK v5.
  </Note>

  ## 4.12.0 Common Changelog

  ### Added

  * The `transports_discovered_peers` system parameter to dynamically update peers discovered out-of-band (#17009)
  * The new `system::indexes` virtual collection for viewing DQL indexes on small peers (#17011)
  * Support for `SSLKEYLOGFILE` for inspecting network traffic in tools like Wireshark (#17029)
  * `UPDATE_LOCAL_DIFF` id conflict strategy for INSERT statements (#17310)
  * A system:data\_sync\_info virtual collection that exposes per-remote data sync status via DQL (#17360)
  * `transports_tcp_so_nodelay` system parameter to control TCP\_NODELAY for TCP and TCP-based websockets connections (#17673)
  * Additional metadata to keep track of the timestamp of the last update file received (#DS-290)
  * Observers for DQL queries can now access system virtual collections (#DS-294)
  * Query executor runner to observers - they now support all of the new DQL features like projections, aggregates, use ids... (#QE-143)
  * SYSTEM:COLLECTIONS & SYSTEM:ALL\_COLLECTIONS virtual collections to list accessible collections (#QE-146)
  * Support for ARRAYs as the value options list in IN DQL expressions (#QE-167)
  * DQL scalar functions for durations (#QE-170)
  * DQL support for CREATE INDEX (#QE-182)
  * DQL support for DROP INDEX (#QE-183)
  * Support for dynamic field references in DQL statements (#QE-2)
  * Query request history cache qualifiers for system datasource deletes and general mutations (#QE-207)
  * Basic RBO for index scan selection (#QE-210)
  * Query parser handles context dependent keyword (#QE-241)
  * Virtual collections for active and historical DQL engine requests (#QE-82)

  ### Changed

  * device\_disk\_observer\_is\_enabled system parameter can now be changed at runtime (#CORE-612)
  * After eviction, document sync now retains high-level session metadata for non-expired sessions, for sync status tracking purposes (#DS-348)
  * Projection, distinct and aggregate features out of preview mode! (#QE-100)
  * Wildcard expansion to top-level with left-to-right, last-wins projection aliasing (#QE-156)
  * Improved ScalarExpr representation in EXPLAIN output (#QE-193)
  * Improved syntax error identification in UPDATE statements (#QE-199)
  * ALTER SYSTEM DQL statements now accept static expressions (#QE-204)
  * USE IDS clause to accept expressions that can be statically evaluated (#QE-217)
  * Permit use of unary plus in DQL expressions (#QE-220)
  * Extended DQL multiplication to better handle multiplying two large negative integers (#QE-224)
  * Query directives processing to accept USE INDEX as the equivalent of USE DIRECTIVES `{"#index":...}` (#QE-255)
  * CREATE & DROP INDEX statements accept IF \[NOT] EXISTS to permit repeated execution without error (#QE-259)
  * Websocket connectivity errors are now logged with additional detail (#TRAN-511)
  * Ditto no longer includes a peer's device name and OS during P2P advertisement (BLE, mDNS, Wi-Fi Aware, AWDL) (#TRAN-652)

  ### Fixed

  * A rare race condition which caused connection handshakes to erroneously fail (#17251)
  * Merge tombstone summaries when applying remote tombstone (#17654)
  * Set default TCP\_NODELAY socket option to true to improve latency, notably on Linux (#17673)
  * DQL collation order is based on length of arrays / objects, not padding values with extra MISSING (#QE-171)
  * DQL scalar function clock() and "local" timezone in WASM environments (#QE-181)
  * Error propagation from collection scans (#QE-191)
  * Collation in DQL aggregates (#QE-216)
  * Panic when using COUNT(\*) in a dynamic object (#QE-219)
  * Panic when subtracting a large positive integer value from a large negative integer value (#QE-223)
  * Aggregate output on empty result sets (#QE-242)

  ### Performance

  * Revised fetching documents by ID in Query to operate in batches (#QE-248)

  ### Other

  * Added a warning to the log when a subscription query uses a LIMIT or ORDER BY (#QE-169)

  ## 4.12.0 Flutter Specific Changes

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: Linux desktop support - Flutter developers can now build and deploy Ditto-powered applications on Linux (#17486)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: Read-only property `commitID` to class `QueryResult` (#SDKS-1280)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: Devtools extension to view the configuration and status of Ditto in Flutter applications (#17005)
</Update>

<Update label="4.11.6" description="Release Date: Oct 14, 2025">
  ## 4.11.6 Common Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: disk usage monitoring no longer leaks memory. (#18531)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Document sync session metadata became unlinked after session reset. (#DS-509)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: Improved logging and error handling for handle\_get\_txid\_query.
</Update>

<Update label="4.11.5">
  ## 4.11.5 Common Changes

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: Explicit log flushing before aborting due to panic.

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: On-disk log file limits now apply to the compressed size, significantly increasing log retention.

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: A rare scenario where an attachment fetch could be delayed by up to 60 seconds.

  **Other**: improve error reporting for document (de)serialization

  ## 4.11.5 Flutter Specific Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: A bug which caused the websocket retry interval to be higher than it should be.
</Update>

<Update label="4.11.4">
  ## 4.11.4 Common Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: A bug where x509 refresh could speed up uncontrollably.

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: A bug where a peer could get stuck with incorrect connection information.
</Update>

<Update label="4.11.3" description="Release Date: Aug 15, 2025">
  ## 4.11.3 Common Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: An issue with BLE on some Android 9 and earlier devices that prevented connection establishment.
</Update>

<Update label="4.11.2" description="Release Date: Aug 1, 2025">
  ## 4.11.2 Common Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: A rare race condition which caused connection handshakes to erroneously fail.

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: `device_disk_observer_is_enabled` system parameter can now be changed at runtime.
</Update>

<Update label="4.11.1" description="Release Date: Jul 16, 2025">
  ## 4.11.1 Common Changes

  *No Specific Changes*
</Update>

<Update label="4.11.0 " description="Release Date: June 10, 2025">
  ## 4.11 - DQL & Legacy Compatibility

  With 4.11 we are excited to introduce legacy compatibility for DQL, which allows
  developers to use the new DQL APIs while maintaining compatibility with existing
  code and data. This capability, called [STRICT MODE](/dql/strict-mode), is designed to ease the transition
  to the new APIs and ensure that existing applications continue to function as
  expected.

  ## DQL Strict Mode

  DQL Strict Mode provides control over how DQL statements are evaluated and how
  data types are inferred. When disabled, it offers more flexibility in working
  with documents without requiring explicit collection definitions.

  <Tip>For more information see [`DQL Strict Mode`](/dql/strict-mode)</Tip>

  With strict mode disabled (`DQL_STRICT_MODE=false`), Ditto is more flexible and will infer the CRDT type based on the document's shape:

  * Objects are treated as CRDT maps
  * Scalars and arrays are treated as Registers
  * Counters and attachments are inferred from operations
  * Collection definitions are no longer required

  **Setting DQL Strict Mode**

  ```sql DQL theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
  ALTER SYSTEM SET DQL_STRICT_MODE = false
  ```

  ## DQL Differ

  DQL 4.11 introduces a new `Differ` API for calculating diffs between query results.
  This API can be used with a store observer to understand how its results change
  over successive callbacks. The `Differ` API provides a way to track changes in
  the data and can be used to optimize data synchronization and conflict resolution.

  [Differ API documentation](/sdk/latest/crud/read#diffing-results).

  ## DQL Transactions

  DQL 4.11 introduces support for *transactions*. Transactions can be used to group multiple DQL statements together, ensuring
  that either all of the statements are executed successfully or none of them are.
  This is particularly useful in scenarios where multiple updates or inserts
  need to be made to the database, and you want to ensure that either all of them
  are applied or none of them are.

  [Transactions API documentation](/sdk/latest/crud/transactions).

  ## Advanced DQL Features

  DQL 4.11 introduces numerous advanced querying and manipulation features:

  | Feature             | Description                                  | Example                                                                |
  | ------------------- | -------------------------------------------- | ---------------------------------------------------------------------- |
  | `UNSET` clause      | Remove fields from documents                 | `UPDATE orders UNSET items.abc WHERE _id = 'my-id'`                    |
  | CAST function       | Explicitly convert between data types        | `SELECT * FROM products WHERE CAST(price AS INT) > 10`                 |
  | USE IDS clause      | Direct document retrieval by ID              | `SELECT * FROM products USE IDS '123', '456'`                          |
  | SIMILAR TO          | Pattern matching expressions                 | `SELECT * FROM products WHERE name SIMILAR TO '%phone%'`               |
  | Runtime expressions | Use expressions in object/array construction | `UPDATE products SET metadata = { 'updated_at': current_timestamp() }` |
  | Counters            | Support for legacy compatible counter type   | `UPDATE products APPLY in_stock PN_INCREMENT BY 1.0`                   |

  <Warning>
    In 4.11, functional operations are denoted with an arrow (`->`) are deprecated. [Read more](https://docs.ditto.live/dql/update#update-multiple-fields).
  </Warning>

  ## Tombstone Reaper

  The tombstone reaper is now enabled by default for all SDKs. This feature helps
  clean up deleted document markers (tombstones) to improve database performance
  and reduce storage requirements.

  The reaper:

  * Automatically removes tombstones after a configurable time-to-live (TTL)
  * Uses read transactions for efficiency
  * Includes random scheduling variations to prevent performance problems
  * Tracks the number of tombstones evicted for monitoring
  * Remembers previous reap times across restarts

  This improves overall system performance by reducing the long-term accumulation of
  tombstones when calling `DELETE` to remove documents.

  ## 4.11.0 Common Changelog

  ### Added

  * Introduced `DQL_STRICT_MODE` as a system parameter to opt-out of requiring collection definitions (#16573)
  * Added transports\_ble\_adapter\_mac system parameter to allow configuring bluetooth adapter MAC address (#16159)
  * Small peers now log the result of OnlinePlayground authentication, including if the supplied shared token was incorrect (#16301)
  * A cumulative running total of the number of tombstones ever evicted by the reaper to Small Peer Info (#16424)
  * Added system parameters to fine-tune Ditto behavior when it encounters a locked persistence directory (#CORE-479)
  * New DQL CAST function to explicitly cast between types (#QE-108)
  * Conditional functions for unknowns (#QE-111)
  * DQL DATE processing functions (#QE-112)
  * New DQL clause USE IDS for direct document retrieval by id (#QE-114)
  * Additional string functions (#QE-124)
  * SIMILAR TO filter expression (#QE-125)
  * PN\_COUNTER support (APPLY clause in UPDATE statement) (#QE-127)
  * UNSET clause to the UPDATE statement (#QE-128)
  * MERGE as an alias for UPDATE in the ON ID CONFLICT clause of an INSERT statement (#QE-132)
  * The ability to use runtime-evaluated expressions in object constructs in DQL statements (#QE-133)
  * The ability to use runtime-evaluated expressions in array constructs in DQL statements (#QE-134)
  * Static expressions in mutators (#QE-139)
  * Additional object manipulation DQL scalar functions (#QE-159)
  * EXPLAIN for query plan (#QE-105)
  * More detailed messages about network problems are logged when authentication fails (#SEC-124)

  ### Changed

  * Use the modern rustls-platform-verifier TLS crate on all platforms rather than rustls-native-certs (#15956)
  * The tombstone reaper scheduling to remember the previous reap times across shutdown and restart of the small peer (#16237)
  * The tombstone reaper scheduling code to add random variations, which helps prevent performance problems if/when all peers run the reaper simultaneously (#16286)
  * The tombstone reaper to be enabled by default for all SDKs (#16350)
  * INSERT to now accept either DOCUMENTS or VALUES as the keyword introducing the list of values to insert (#QE-140)
  * Date functions accept "local" as a timezone & use the executing peer's local timezone (#QE-168)
  * Unified dedicated TCP servers across different transports (Multicast, mDNS, and WiFi Aware) by utilizing a single static TCP server implementation (#TRANS-131)

  ### Fixed

  * Fixed issue where user\_collection\_sync\_scopes could not be updated after initial set (#16299)
  * Fixed: A rare crash on Android devices when shutting down Bluetooth. (#17069)
  * Fixed: Bluetooth connectivity on Apple devices works when background Bluetooth permissions are missing. (#17065)

  ### Removed

  * Old multihop networking stack and system parameter `network_use_nextgen_multihop_stack` (#16370)
  * TLS certificate compression, which led to incompatibilities (#SDKS-1046)

  ### Performance

  * The tombstone reaper uses read transactions for some of its work instead of holding open a long-running write transaction, thus reducing contention on the small peer database (#16338)
  * Improved speed and efficiency of the tombstone reaping process (#16535)

  ## 4.11.0 Flutter Specific Changes

  * Added `DittoDiff` class to represent diffs produced by the `DittoDiffer`
  * Added `DittoDiffer` class for calculating diffs between query results
  * Added `transaction()` method on `DittoStore` for performing DQL transactions
  * Added `DittoTransaction` class to represent an active DQL transaction
  * Added `DittoTransactionInfo` class for transaction information
  * Added `DittoTransactionCompletionAction` for commit/rollback actions
</Update>

<Update label="4.10.4" description="Release Date: June 3, 2025">
  # 4.10.4 Security & Stability Improvements

  We've enhanced our TLS certificate handling to provide more robust and reliable secure connections while maintaining our high security standards.

  * Improved reliability of secure connections by gracefully handling certificate validation challenges
  * Enhanced network stability with smarter handling of security certificates
  * Added flexibility in secure connection handling while maintaining robust security standards
</Update>

<Update label="4.10.3" description="Release Date: May 6, 2025">
  # 4.10.3 Stability Improvements, DQL Enhancements

  We've enhanced our query capabilities with improved sorting and filtering for UPDATE operations, while also focusing on overall reliability improvements.

  * Added powerful sorting and filtering capabilities to UPDATE operations, giving you more control over how you modify data on Small Peer devices
  * Enhanced reliability and performance of data queries across your application
</Update>

<Update label="4.10.2" description="Release Date: May 1, 2025">
  # 4.10.2

  * No significant changes. Bumped version to 4.10.2 to align with other SDKs.
</Update>

<Update label="4.10.1" description="Release Date: March 26, 2025">
  # 4.10.1

  * Added support for the web platform
  * Attachment fetchers now successfully complete the attachment fetch operation
  * The `isStopped` property of `AttachmentFetcher` instances now becomes `true` after completing an attachment fetch
  * Resolved a memory leak that affected `QueryResult` and `QueryResultItem`
  * `ditto.store.newAttachment` now returns a `Future<Attachment>` rather than an Attachment
  * `ditto.close()` now returns a `Future<void>` rather than `void`
</Update>

<Update label="4.10.0" description="Release Date: March 17, 2025">
  # 4.10.0 New Capabilities

  ## Now Supporting Flutter 3.19+

  Ditto’s Flutter SDK now supports Flutter 3.19 and later, broadening compatibility and making it easier for more developers
  to integrate Ditto into their apps. This update ensures greater flexibility, allowing teams to adopt Ditto without needing
  to upgrade immediately to the latest Flutter version.

  ## Experimental Support for Hot Restart in Flutter

  The Ditto team is excited to preview support for Hot Restarts in Flutter.

  To allow users experiment and provide feedback on hot restarts we've shipped a specific SDK version with
  hot restarts enabled by default.

  To use hot restarts update your version to `4.10.0-experimental-hot-restart.0`. This version is identical to `4.10.0` but
  has Hot Restart enabled by default. In an upcoming release this capability will be integrated into Ditto's standard package
  as a developer mode config that can be set by the user on Ditto class initialization.

  Flutter Dart has limited support for Hot Restarts with native binaries, such as Ditto. The Ditto team is working to mitigate
  these issues. If you run into any issues while experimenting with Flutter Hot Restarts reach out to [Ditto Customer Support](https://support.ditto.live/hc/en-us).

  **Known issues include:**

  * Logging must be disabled. To do this set `DittoLogger.isEnabled = false`
    immediately after calling `await Ditto.init()`.
  * Attempting to use attachments will cause a crash.
  * Hot restarting will leak some resources, notably memory. In our testing,
    approximately 20-30MB is leaked per hot-restart.
  * Data integrity cannot be guaranteed. You may experience data corruption when
    hot-restarting, which may be propagated to any peers that are being synced
    with.
  * Sporadic crashes can occur.

  <Warning> Hot Restarts is a developer mode config and can cause application instability, especially for long running sessions. Do not ship to any production environment using version `4.10.0-experimental-hot-restart.0`.</Warning>

  <Capabilities4_10 />

  ## 4.10.0 Flutter Specific Changelog

  * Add support for Flutter 3.19 (Flutter - support 3.19 #16080)
  * Throw an error when trying to use Ditto APIs before awaiting `Ditto.init()` (#15880)
  * persistenceDirectory now supports relative paths and no longer needs to exist, and also works on web (#15890)
  * compiling with --wasm now works. Required for upcoming Flutter Web release. (#15991)
  * LAN transport shuts down when `stopSync()` is called (#SDKS-707)

  <Changelog4_10 />
</Update>

<Update label="4.9.2" description="Release Date: Feb 26, 2024">
  # 4.9.2

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** Fixed a bug that caused
  observer events to not be triggered in profile and release mode (either via the `onChange` parameter
  or the `StoreObserver.changes` stream)
</Update>

<Update label="4.9.1" description="Release Date: Feb 24, 2024">
  # 4.9.1

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** Support for Flutter 3.19 for iOS and Android

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** Failing to call
  `await Ditto.init()` will now throw. This is to prevent improper initialization.

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** `ditto.transportsConfig = config;` will now throw if `config` enables
  transports which don't exist on the current platform (e.g. AWDL on Android or P2P Wifi on iOS).

  `TransportConfig.setAllPeerToPeerEnabled()` will now take the current platform
  into account, and will only modify transports which are available. A newly
  created `Ditto` instance will not have transports enabled that are not
  available on the current platform

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** Resolve an uncaught exception
  that could happen in `ditto.presence.graph` when there were P2PWifi connections.

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** The persistence directory
  behaves differently if a relative path is provided.

  If a relative path is provided, it will be treated as a subdirectory of
  `getApplicationDocumentsDirectory()`. If an absolute path is given, its value
  is not modified. The `persistenceDirectory` parameter in `Ditto.open` is now
  optional, and defaults to `"ditto"`. If the directory does not exist, it will be created.
</Update>

<Update label="4.9.0 (GA Release)" description="Release Date: Jan 27, 2024">
  # 4.9.0 (GA Release)

  We’re excited to announce the General Availability of the Ditto Flutter SDK! Designed to
  empower developers building cross-platform apps, the Flutter SDK delivers reliable real-time
  data synchronization and offline-first capabilities, now production-ready!

  ## API Support Guarantees

  General Availability (GA) means API stability! Starting with `4.9.0` Ditto will guarantee semver
  support of all APIs following industry standards. For more on semver see
  [semver.org](https://semver.org/).

  ## Changes from the Public Preview

  To provide the best product with our GA release we've made some final modifications to the
  underlying architecture that bridges Dart and the Ditto Core for Android. The goal with this change
  is to provide a higher quality product with improved performance, reliability, and developer
  experience.

  These changes provide the following benefits:

  * Enhanced developer ergonomics through synchronous APIs
  * Improved performance for all operations across all platforms
  * Reduced complexity improving reliability
  * Reduced background operations for better battery life
  * Lower memory consumption

  ## Breaking Changes

  This release contains a handful of minor syntax changes to provide an improved developer
  experience and better support the underlying framework. These syntax changes all stem from
  the ability to support non-async calls across the Dart-Ditto Core FFI.

  In the initial Dart-Ditto implementation all Dart internal calls were required to make async calls
  into Ditto. This required us to make all Ditto API methods `async`. Due to the improvements
  with our recent changes we are now able to provide synchronous methods. This change will bring a more
  natural developer experience.

  #### Ditto Initialization Required using `await Ditto.init()`

  From `4.9.0` and later it's required to call `await Ditto.init()` before using *any* Ditto
  functionality. Failing to do so can result in incorrect initialization of Ditto and unexpected
  failures.

  Notably, this must happen after `WidgetsFlutterBinding.ensureInitialized()` has
  been called.

  Flutter's `runApp` already calls
  `WidgetsFlutterBinding.ensureInitialized()`, so if calling `Ditto.init()` inside
  the `initState` of a `StatefulWidget`, it will just work.

  To initialize `Ditto` in `main`, use the following syntax:

  ```dart theme={null}
  Future<void> main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await Ditto.init();
      runApp(MyCoolApp());
  }
  ```

  #### Select `async` functions have become sync

  Select functions that don't require asynchronous execution have been converted from `async`
  to standard sync operations.

  *Changed Methods Include:*

  * `ditto.startSync();`
  * `ditto.store.registerObserver(...);`
  * `ditto.sync.registerSubscription(...);`

  *Example with basic replacement:*

  ```dart theme={null}
  // Previous syntax
  final observer = await ditto.store.registerObserver("SELECT * FROM tasks");

  // New syntax
  final observer = ditto.store.registerObserver("SELECT * FROM tasks");
  ```

  *Example chaining Future's with `.then()` (often seen in `initState()`):*

  ```dart theme={null}
  // Previous syntax
  ditto.store.registerObserver("SELECT * FROM tasks").then((observer) {
    setState(() {
      _observer = observer;
    });
  });

  // New syntax
  final observer = ditto.store.registerObserver("SELECT * FROM tasks");
  setState(() {
      _observer = observer;
  });
  ```

  #### Methods to setter/getter variables

  Async getter/setter method pairs have been converted to properties using Dart's getter/setter syntax, for a more natural
  developer experience.

  *Changed Methods Include:*

  | Previous                                                                        | New                             |
  | ------------------------------------------------------------------------------- | ------------------------------- |
  | `DittoLogger.setMinimumLogLevel(...)` `DittoLogger.getMinimumLogLevel(...)`     | `DittoLogger.minimumLogLevel`   |
  | `DittoLogger.setCustomLogCallback(...)` `DittoLogger.getCustomLogCallback(...)` | `DittoLogger.customLogCallback` |

  *Examples*

  ```dart theme={null}
  // Previous syntax
  await DittoLogger.setMinimumLogLevel(LogLevel.debug);
  await DittoLogger.getMinimumLogLevel();

  // New syntax
  DittoLogger.minimumLogLevel = LogLevel.debug;
  ```

  ```dart theme={null}
  // Previous syntax
  await DittoLogger.setCustomLogCallback((logLevel, logString) {
      print("$logLevel: $logString");
  });

  // New syntax
  DittoLogger.customLogCallback = (logLevel, logString) {
      print("$logLevel: $logString");
  }
  ```

  #### Boolean functions renamed from `getFoo`/`setFoo` to `isFoo`

  For property types where the value type is `bool`, the functions will have been renamed
  from `getFoo` and `setFoo` to `isFoo`.

  *Changed Methods Include:*

  | Previous                                                  | New                     |
  | --------------------------------------------------------- | ----------------------- |
  | `DittoLogger.setEnabled()` `DittoLogger.getEnabled()`     | `DittoLogger.isEnabled` |
  | `ditto.setTransportConfig()` `ditto.getTransportConfig()` | `ditto.transportConfig` |

  *Examples*

  ```dart theme={null}
  // Previous syntax
  await DittoLogger.setEnabled()
  await DittoLogger.getEnabled()

  // New syntax
  DittoLogger.isEnabled
  ```

  ```dart theme={null}
  // Previous syntax
  await ditto.setTransportConfig()
  await ditto.getTransportConfig()

  // New syntax
  ditto.transportConfig
  ```

  #### Select Async Initialization is now Sync

  Objects with `async` constructors that didn't require asynchronous initialization have
  been changed for a more natural developer experience.

  *Changed Methods Include:*

  * All `Identity` subclass (E.g. `OnlinePlaygroundIdentity`)

  *Example:*

  ```dart theme={null}
  // Previous syntax
  final identity = await OnlinePlaygroundIdentity.create(
    appID: appID,
    token: token,
  );

  // New syntax
  final identity = OnlinePlaygroundIdentity(
    appID: appID,
    token: token,
  );
  ```

  #### Restricted Class Modifiers

  Many of our types are now either `final` classes (which prevent *all*
  subtyping), or `interface` classes (which allow `implements` but disallow
  other forms of subtyping).

  If you were previously extending or implementing a type and this is now
  disallowed, you can create a wrapper type:

  *Example:*

  ```dart theme={null}
  // Previous syntax
  class MockDitto extends Mock implements Ditto {}

  // New syntax
  class DittoWrapper {
      final Ditto _ditto;
      // constructor

      Future<List<Task>> loadTasks() => ...;
  }

  class MockDitto extends Mock implements DittoWrapper {}
  ```

  Some types may explicitly allow subtyping. Follow the API docs to understand when subtyping is best used.

  #### Removal of `dart:io` types in public API

  `Directory` and `File` are no longer found in our public API.

  For example `Ditto.open()` previously took a `Directory persistenceDirectory`,
  but this has been changed to `String`.

  This can be resolved by calling `.path`:

  ```dart theme={null}
  // Previous syntax
  final persistenceDirectory = Directory("/my/cool/directory");
  final ditto = await Ditto.open(
    persistenceDirectory: persistenceDirectory,
    // ...
  );

  // New syntax
  final persistenceDirectory = Directory("/my/cool/directory");
  final ditto = await Ditto.open(
    persistenceDirectory: persistenceDirectory.path,
    // ...
  );
  ```

  #### Min Kotlin Gradle Plugin Version Upgraded to 1.8.0

  Supporting new Android capabilities requires using Kotlin Gradle Plugin version `1.8.0` or later.

  *To upgrade:*

  1. Navigate to the root folder
  2. Open `./android/settings.gradle`
  3. Update the `org.jetbrains.kotlin.android` plugin to `1.8.0`
     ```gradle {3} theme={null}
     plugins {
         // ...
         id "org.jetbrains.kotlin.android" version "1.8.0" apply false
     }
     ```
</Update>

<Update label="4.8.0-publicpreview.2" description="Release Date: Oct 25, 2024">
  Final Preview Release

  **Contains:** Reliability and stability improvements.
</Update>

<Update label="4.8.0-publicpreview.1" description="Release Date: Oct 17, 2024">
  We’re excited to announce the public preview of the Ditto Flutter SDK!

  While you can expect major feature compatibility with our production SDKs, we’re continuously refining the experience and closing any minor gaps. Join us on this journey, and share your feedback to help shape the future of Ditto for Flutter!
</Update>

<Update label="4.8.0-beta.12" description="Release Date: Oct 10, 2024">
  This change has a large number of new capabilities as well as some minor namings API Breaking Changes.

  <Icon icon="plus" iconType="solid" horizontal /> Added: Presence API - Allows receiving syncing information about other peers. See Using Mesh Presence

  <Icon icon="plus" iconType="solid" horizontal /> Added: WifiAware as a Transports protocol.

  <Icon icon="plus" iconType="solid" horizontal /> Added: Retrieving active subscriptions. Syncing Data > Retrieving Subscriptions

  <Icon icon="plus" iconType="solid" horizontal /> Added: Canceling subscriptions. Syncing Data > Canceling Subscriptions

  <Icon icon="plus" iconType="solid" horizontal /> Added: Support for sync groups. Creating Sync Groups

  <Icon icon="plus" iconType="solid" horizontal /> Added: Support to intercept and reject new connections. Handling Connection Requests

  <Icon icon="exclamation" iconType="solid" horizontal /> Breaking change: AuthenticationStatus.authenticated renamed to isAuthenticated

  <Icon icon="exclamation" iconType="solid" horizontal /> Breaking change: Various TransportConfig-related types have enabled properties renamed to isEnabled

  <Icon icon="exclamation" iconType="solid" horizontal /> Breaking change: HttpListenConfig.interfaceIp renamed to interfaceIP

  <Icon icon="exclamation" iconType="solid" horizontal /> Breaking change: HttpListenConfig.websocketSync renamed to webSocketSync

  <Icon icon="exclamation" iconType="solid" horizontal /> Breaking change: StoreObserver.cancelled renamed to isCancelled
</Update>

<Update label="4.8.0-beta.11" description="Release Date: Oct 4, 2024">
  <Icon icon="plus" iconType="solid" horizontal /> Added: Logger class that provides diagnostics capabilities.
  <Icon icon="plus" iconType="solid" horizontal /> Added: Device Dashboard Support - customers can now see device information on the Ditto Portal.
  <Icon icon="plus" iconType="solid" horizontal /> Added: Support for Attachments.

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> Changed:  The default `deviceName` will now represent the device's model.
</Update>

<Update
  label="4.8.0-beta.10"
  description="Release Date: Sept 13, 2024
"
>
  <Icon icon="plus" iconType="solid" horizontal /> Added: OnlineWithAuthenticationIdentity and ditto.auth

  <Icon icon="plus" iconType="solid" horizontal /> Added: User-configurable transport config. Customizing Transports Configurations
</Update>

<Update label="4.8.0-beta.8 & 4.8.0-beta.9" description="No Notable Changes" />

<Update label="4.8.0-beta.7" description="Release Date: Aug 26, 2024">
  <Icon icon="plus" iconType="solid" horizontal /> Added: Ability to stop sync `ditto.stopSync()`

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> Fixed: Cancelling a subscription currently doesn't trigger any action

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> Fixed: Observer API no longer fires every 50ms. Previously the observer API was using a polling mechanism internally which resulted in an event ever 50ms no matter if there were changes or not. This has been updated with an event listener pattern.

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> Changed: Performance and battery life improvements from observers not continuously firing
</Update>

<Update label="4.8.0-beta.6" description="Release Date: Aug 21, 2024">
  Version 4.8.0-beta.6 has been Retracted due to an issue found with Android observer API not firing correctly.

  Please use earlier or later releases.
</Update>

<Update label="4.8.0-beta.5" description="Release Date: July 23, 2024">
  The initial beta release of Flutter
</Update>
