> ## 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.

# Kotlin 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 Kotlin & Java Specific Changes

  **Performance**: Lower overhead on every serialization and deserialization operation. (#SDKS-3755)

  ## 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 Kotlin & Java 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**: Identity-based `Ditto` constructor, `DittoIdentity`, `DittoDependencies`, and `DefaultAndroidDittoDependencies` in favor of `Ditto.open(config)` / `Ditto.openSync(config)`. (#SPO-203)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: Warning log when `DittoSubscription` or `DittoLiveQuery` is garbage collected without `close()` being called. (#SPO-443)

  ## 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 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 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 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)

  **Lowered minimum Kotlin version**: The Ditto Kotlin SDK now supports Kotlin 1.7.20 and above, expanding compatibility with older Android projects and reducing upgrade friction for existing applications

  ## 4.14.0 Full Change Log

  <AccordionGroup>
    <Accordion title="Kotlin & Java Specific Changes">
      <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: WiFi Aware now respects system data path limits to prevent resource exhaustion. (WiFi Aware: Adhere to system constraints on available data paths #18503)

      <Icon icon="plus" iconType="solid" horizontal /> **Added**: WiFi Aware transport configuration option to reset the device WiFi stack in Android profile owner scenarios, improving reliability. (#NETW-435)

      <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: A crash during SDK initialization when integrating Ditto into host applications with isolated class loaders (e.g. plugins). The SDK now correctly handles certificate verification in these environments. (#SDKS-1395)

      <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: Reduce minimum required Kotlin version to 1.7.20. (#SDKS-2373)
    </Accordion>

    <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 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 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 Kotlin & Java Specific Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: A crash during SDK initialization when integrating Ditto into host applications with isolated class loaders (e.g. plugins). The SDK now correctly handles certificate verification in these environments. (#SDKS-1395)

  ## 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 - 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="Kotlin & Java Specific Changes">
      <Icon icon="plus" iconType="solid" horizontal /> **Added**: `close()` method to `DittoConnectionRequest` class, which now implements `Closeable`. (#SDKS-1542)

      <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Memory leaks from `DittoConnectionRequest`. Instances of this type are now auto-closed after the event is handled. (#SDKS-1542)

      <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: clientInfo not returned on auth failure (#SDKS-1656)

      <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Memory leaks around string handling at the following APIs: DittoStore.queriesHashMnemonic, DittoSingleDocumentLiveQueryEvent.hashMnemonic, Ditto.setOfflineOnlyLicenseToken. (#SDKS-1763)

      <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: DittoDocument now implements AutoCloseable (#SDKS-1889)

      <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Memory leak from listing and observing collections. (#SDKS-963)
    </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 Kotlin & Java Specific Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: memory leaks around string handling at the following APIs: DittoStore.queriesHashMnemonic, DittoSingleDocumentLiveQueryEvent.hashMnemonic, Ditto.setOfflineOnlyLicenseToken. (#SDKS-1763)

  ## 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 Kotlin & Java Specific Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: `clientInfo` not returned on auth failure. (#SDKS-1656)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Memory leak on DittoDiffer, ensuring it gets cleaned up even if not explicitly closed. (#SDKS-1722)

  ## 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 connection request handler no longer causes `ReceiveTimeout` failures in connectivity. (#TRAN-729)
</Update>

<Update label="4.12.2" description="Release Date: Sep 30, 2025">
  ## 4.12.2 Kotlin & Java Specific Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Memory leak on `DittoQueryResultItem.jsonString()`. (SDKS-1625)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: WiFi Aware transport will only attempt to be started on device's that support it. (#18482)

  ## 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 Kotlin & Java Specific Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: DittoQueryResult.items throwing IllegalStateException when accessed after parent query result was garbage collected. Items now remain valid unless the parent was explicitly closed. (#SDKS-1540)

  ## 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 Kotlin Specific Changes

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: `DittoError.StoreErrorReason.PersistenceDirectoryLocked` which is now thrown by `Ditto.open()` and `Ditto.openSync()` when trying to open a second Ditto instance with the same persistence directory instead of crashing.

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: system parameters to enable/disable WiFi Aware client/server (#17314)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: read-only property `commitId` to class `DittoQueryResult`. (#SDKS-1280)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: `Ditto.open()` — **(Preview)** a suspending fallible factory method for creating `Ditto` instances, alongside the synchronous convenience variant `Ditto.openSync()`. These will replace all previous initializers in v5.

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: `Ditto.config` — **(Preview)** a read-only property to access the configuration used during initialization of a `Ditto` instance. This will be the standard way to access configuration in v5.

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: `DittoAndroidConfig` — **(Preview)** a unified configuration class that encapsulates all initialization parameters for Ditto. Required by the new `Ditto.open()` and `Ditto.openSync()` factory methods. This API will become the standard way to initialize Ditto instances in v5.

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: `DittoConfig.default` - **(Preview)**  default configuration applied to new Ditto instances.

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: `DittoConfig.databaseId` - **(Preview)**  a replacement for `Ditto.appId`.

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: `DittoConfig.defaultDatabaseId()` - **(Preview)** default identifier for a Ditto instance.

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: `Ditto.absolutePersistenceDirectory` — a read-only property that returns the absolute file path to the persistence directory, replacing the now deprecated `Ditto.persistenceDirectory`.

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: `DittoAuthenticationExpirationHandler` — **(Preview)** a suspending lambda-based handler for authentication expiration events. This provides a modern, Kotlin-native alternative to the `DittoAuthenticationCallback` interface and will replace it in v5.

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: `DittoAuthenticationProvider` - **(Preview)** a type which represents authentication providers. Use `development()` or `custom()` with the new suspending `DittoAuthenticator.login()`. Supports both built-in and custom providers in a consistent and ergonomic way in v5.

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: `DittoAuthenticator.login()` - a suspending overload that takes a `DittoAuthenticationProvider`.

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: `DittoAuthenticator.expirationHandler` — **(Preview)** a lambda-based replacement for the `callback` property, offering a more modern approach to handling authentication expiration events. This will replace the delegate pattern in v5.

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: `DittoError.ValidationError.InvalidDittoConfig` — A validation error reason signaling an invalid `DittoConfig`.

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: `DittoError.AuthenticationErrorReason.ExpirationHandlerMissing` — An authentication error reason signaling that the `DittoAuthenticationExpirationHandler` needs to be set.

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: The ditto native library on Android is now 16KB aligned to meet Google Play's upcoming requirement, effective November 2025. (#SDKS-1333)

  <Icon icon="triangle-exclamation" iconType="solid" horizontal /> **Deprecated**: `DittoError.LockedWorkingDirectoryError` - replaced by `DittoError.StoreError(StoreErrorReason.PersistenceDirectoryLocked)`.

  <Icon icon="triangle-exclamation" iconType="solid" horizontal /> **Deprecated**: `Ditto.persistenceDirectory` — replaced by `Ditto.absolutePersistenceDirectory` which guarantees an absolute file path.

  <Icon icon="triangle-exclamation" iconType="solid" horizontal /> **Deprecated**: `DittoAuthenticator.loginWithCredentials()` - use `login()` instead.

  <Icon icon="triangle-exclamation" iconType="solid" horizontal /> **Deprecated**: `DittoExperimental.constructDittoFallible()` — replaced by the new `Ditto.open()` and `Ditto.openSync()` factory methods.

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: `stopSync` does not properly terminate WiFi Aware connections (#17235)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: crash on startup on devices running Android 8.1 and below (#17460)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Transactions are now disposed deterministically upon completion, rather than relying on the garbage collector. This prevents potential hangs or resource leaks. (#17470)
</Update>

<Update label="4.11.6" description="Release Date: Oct 14, 2025">
  ## 4.11.6 Kotlin & Java Specific Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Memory leak on DittoDiffer, ensuring it gets cleaned up even if not explicitly closed. (#SDKS-1722)

  ## 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" description="Release Date: Sep 25, 2025">
  ## 4.11.5 Kotlin & Java Specific Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Memory leak on `DittoQueryResultItem.jsonString()`. (SDKS-1625)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: WiFi Aware transport will only attempt to be started on devices that support it. (#18482)

  ## 4.11.5 Common Changes

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

  <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)
</Update>

<Update label="4.11.4" description="Release Date: Aug 28, 2025">
  ## 4.11.4 Kotlin & Java Specific Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: DittoQueryResult.items throwing IllegalStateException when accessed after parent query result was garbage collected. Items now remain valid unless the parent was explicitly closed. (#SDKS-1540)

  ## 4.11.4 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)
</Update>

<Update label="4.11.3" description="Release Date: Aug 15, 2025">
  ## 4.11.3 Kotlin & Java Specific Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Memory leak in DittoQueryResult.close(), which now also closes its DittoQueryResultItem instances. This eliminates the need for manual cleanup and resolves excessive memory usage with large query results. (#SDKS-1463)

  ## 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. (#17760)
</Update>

<Update label="4.11.2" description="Release Date: Aug 1, 2025">
  ## 4.11.2 Kotlin & Java Specific Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Transactions are now disposed deterministically upon completion, rather than relying on the garbage collector. This prevents potential hangs or resource leaks. (#17470)

  ## 4.11.2 Common Changes

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

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: device\_disk\_observer\_is\_enabled system parameter can now be changed at runtime (#CORE-612)
</Update>

<Update label="4.11.1" description="Release Date: Jul 16, 2025">
  ## 4.11.1 Kotlin & Java Specific Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: `stopSync` does not properly terminate WiFi Aware connections (#17235)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: system parameters to enable/disable WiFi Aware client/server (#17314)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: crash on startup on devices running Android 8.1 and below (#17460)

  ## 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 Kotlin & Java Specific Changes

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: `DittoTransaction` representing an active DQL transaction. (#15873)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: `DittoTransactionInfo` encapsulating information about a transaction. (#15873)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: Method `transaction()` on `DittoStore` allowing a DQL transaction to be performed. (#15873)

  <Icon icon="plus" iconType="solid" horizontal /> - `DittoTransactionCompletionAction` representing an action to be taken upon the completion of a transaction: commit or rollback. (#15873)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: An opt-in Android foreground service which allows Ditto to sync in the background. (#16097)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: The new `DittoDocumentPath::number` and `DittoDocumentPath::numberValue` accessors. (#16776)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: transport config changes that are made directly on the `DittoTransportConfig` object that a `Ditto` instance references are now applied when `startSync` is called. (#16835)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: WiFi Aware occasional failure to start advertising (#16844)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Transaction hints in log messages from calls to `upsert()` included `$name` instead of the actual collection name. (#SDKS-1012)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: class `DittoDiffer`, which calculates diffs between query results. This can be used with a store observer to understand how its results change over successive callbacks. (SDKS-981)

  <Icon icon="plus" iconType="solid" horizontal /> **Added**: class `DittoDiff` to represent diffs produced by the `DittoDiffer`. (SDKS-981)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: Unify dedicated TCP servers across different transports (Multicast, mDNS, and WiFi Aware) by utilizing a single static TCP server implementation (#TRANS-131)
</Update>

<Update label="4.10.5 " description="Release Date: Jun 24, 2025">
  ## 4.10.5 Kotlin/Java Specific Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: transport config changes that are made directly on the `DittoTransportConfig` object that a `Ditto` instance references are now applied when `startSync` is called. (#16835)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: A rare crash on Android devices when shutting down Bluetooth. (#17069)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: hard crash on Android 10 Bluetooth (#17073)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: stopSync\` does not properly terminate WiFi Aware connections (#17235)

  ## 4.10.5 Common Changes

  *No Specific Changes*
</Update>

<Update label="4.10.2 " description="Release Date: Apr 25, 2025">
  ## 4.10.2 Common Changes

  <Icon icon="bin-recycle" iconType="solid" horizontal /> **Removed**: zlib certificate compression for small peer TLS 1.3 session negotiation, which caused incompatibilities (#1005)
</Update>

<Update label="4.10.1 " description="Release Date: Apr 02, 2025">
  ## 4.10.1 Common Changes

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: The tombstone reaper scheduling to remember the previous reap times across shutdown and restart of the small peer. (#16237)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: the tombstone reaper scheduling code to add random variations, which helps prevent performance problems if/when all peers run the reaper simultaneously. (#16286)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed**: Unable to update user\_collection\_sync\_scopes after initial set bug (#16299)

  **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)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: The tombstone reaper to be enabled by default for all SDKs. (#16350)
</Update>

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

  ## Small Peer User Collection Sync Scopes

  User Collection Sync Scopes let you control how data from each user collection is shared with other connected Peers.
  This is useful when you want to fine-tune which collections do not sync, which collections sync with only Ditto Server and which collections sync only with connected Small Peer devices.

  Sync scopes can be used to control how documents sync, reduce unnecessary data transfer, and improve performance.

  <Tip>For more information see [`SDK>Configuring Collection Sync`](/sdk/latest/sync/sync-scopes)</Tip>

  <Warning>There is a known issue that once a `startSync()` is called `USER_COLLECTION_SYNC_SCOPES` cannot be updated without
  closing and reopening a new Ditto instance. This will be resolved in the next release. For more information
  see [`Updating Sync Scopes`](/sdk/latest/sync/sync-scopes#updating-sync-scopes) </Warning>

  ### Details

  | Sync Scope           | Purpose                                                                                              |
  | -------------------- | ---------------------------------------------------------------------------------------------------- |
  | "AllPeers" (default) | Sync with both Ditto Server and other Small Peers. This is the default behavior for all collections. |
  | "BigPeerOnly"        | Sync only with Ditto Server (Big Peer). Do not sync with other Small Peers.                          |
  | "SmallPeersOnly"     | Sync only with other Small Peers. Do not sync with Ditto Server.                                     |
  | "LocalPeerOnly"      | Do not sync this collection to Ditto Server or other Small Peers.                                    |

  **DQL Syntax for setting a Sync Scope**

  ```sql DQL theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
  ALTER SYSTEM SET USER_COLLECTION_SYNC_SCOPES = {
      collection_1: "BigPeerOnly",
      collection_2: "SmallPeersOnly",
      collection_3: "LocalPeerOnly"
  }
  ```

  **Example Setting A Sync Scope in the SDKs**

  In the example below we'll set the collection `local_mesh_orders` to only sync with other small peers in the mesh and not with Ditto Server using the `SmallPeersOnly` sync scope.

  <CodeGroup>
    ```swift Swift theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
    var syncScopes = [
    "local_mesh_orders": "SmallPeersOnly"
    ];
    await ditto.store.execute(
        query: "ALTER SYSTEM SET USER_COLLECTION_SYNC_SCOPES = :syncScopes",
        arguments: ["syncScopes": syncScopes]);
    ```

    ```kotlin Kotlin theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
    ditto.store.execute(
    "ALTER SYSTEM SET USER_COLLECTION_SYNC_SCOPES = :syncScopes",
    mapOf("syncScopes" to mapOf(
        "local_mesh_orders" to "SmallPeersOnly"
    )))
    ```

    ```javascript JS theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
    const syncScopes = {
    local_mesh_orders: "SmallPeersOnly"
    };
    await ditto.store.execute(
    "ALTER SYSTEM SET USER_COLLECTION_SYNC_SCOPES = :syncScopes",
    { syncScopes }
    );
    ```

    ```java Java theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
    Map<String, String> syncScopes = new HashMap<>();
    newCar.put("local_mesh_orders", "SmallPeersOnly");

    DittoQueryResult result = (DittoQueryResult) ditto.store.execute(
        "ALTER SYSTEM SET USER_COLLECTION_SYNC_SCOPES = :syncScopes",
        Collections.singletonMap("syncScopes", syncScopes));
    ```

    ```csharp C# theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
    var args = new Dictionary<string, object> {
    "syncScopes", new { local_mesh_orders = "SmallPeersOnly" }
    };

    await ditto.Store.ExecuteAsync(
    "ALTER SYSTEM SET USER_COLLECTION_SYNC_SCOPES = :syncScopes",
    args);
    ```

    ```cpp C++ theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
    std::map<std::string, std::map<std::string, std::string>> args;
    args["syncScopes"] = {{"local_mesh_orders", "SmallPeersOnly"}};

    ditto.get_store().execute(
    "ALTER SYSTEM SET USER_COLLECTION_SYNC_SCOPES = :syncScopes",
    args);
    ```

    ```rust Rust theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
    struct Args {
    syncScopes: SyncScopes,
    }
    struct SyncScopes {
    local_mesh_orders: String,
    }
    // ...
    let args = Args {
    syncScopes: SyncScopes {
        local_mesh_orders: "SmallPeersOnly".to_string()
    },
    };
    ditto.store().execute(
    "ALTER SYSTEM SET USER_COLLECTION_SYNC_SCOPES = :syncScopes",
    args);
    ```

    ```dart Dart theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
    final syncScopes = {
    "local_mesh_orders": "SmallPeersOnly"
    };
    await ditto.store.execute(
    "ALTER SYSTEM SET USER_COLLECTION_SYNC_SCOPES = :syncScopes",
    arguments: {"syncScopes": syncScopes},
    );
    ```
  </CodeGroup>

  ## Store Observers Run Multi-Threaded By Default

  Ditto store observers (e.g `ditto.store.registerObserver(...)`) will now run multi-threaded on all platforms (except for in Web Browsers)
  by default. Prior to `4.10.0` all store observers would run on the same thread which could lead to performance issues for applications
  with multiple store observers. Users may see performance improvements on applications using more than one store observer, especially during
  high-volume usage.

  Ditto guarantees order sequencing for a single observer. Because observers now run in parallel there is not a guarantee for order
  sequencing between observers. This behavior change should not have an impact on your application. If you have concerns or questions
  about this behavior change reach out to [Ditto's Customer Support](https://support.ditto.com).

  To reset Ditto to only use a single thread for all Ditto observers use the following system parameter. For instruction on how to set
  a system parameter in your specific SDK see [`SDK>Customizing System Settings`](/sdk/latest/sync/using-alter-system)

  ```sql DQL theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
  ALTER SYSTEM SET STORE_OBSERVERS_NUM_THREADS = 1
  ```

  ## DQL Support for `LIKE` operator

  The `LIKE` operator can now be used for pattern matching of string values.

  <Tip>For more information see [`DQL>Operator Expressions`](/dql/operator-expressions#string-operators)</Tip>

  | Pattern | Meaning                                             |
  | ------- | --------------------------------------------------- |
  | %       | Matches zero or more characters (like .\* in regex) |
  | \_      | Matches exactly one character (like . in regex)     |

  **Example**

  ```sql DQL theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
  SELECT * FROM my_collection
  WHERE some_field LIKE 'abc%'
  ```

  ## DQL New Objects operators

  DQL now supports two new methods for querying over the keys and values in an object.

  * `object_keys(object)`: Returns an `array` with all the keys in the given `object`.
  * `object_values(object)`: Returns an `array` with all the values in `object`.

  <Tip>For more information see [`DQL>Operator Expressions`](/dql/operator-expressions#object-operators)</Tip>

  ## DQL LIMIT/ OFFSET / ORDER BY support for mutation operators

  Users can now use `LIMIT`, `OFFSET` and `ORDER BY` in `EVICT` and `UPDATE` statements.

  **DQL Example**

  ```sql DQL theme={null} theme={null} theme={null} theme={null} theme={null} theme={null}
  EVICT FROM users
  WHERE status = 'inactive'
  LIMIT 10;
  ```

  ## 4.10.0 Kotlin/Java Specific Changelog

  * New `triggerTestPanic` method on `DittoExperimental` to intentionally trigger a panic in the Ditto Core for testing purposes. (#15408)
  * ProGuard configuration file, ensuring isMinifyEnabled can be used with Ditto. (#15523)
  * Repeated reads of a document within an ID-specific transaction scope of the query builder API now reflect changes made in the same transaction. (SDKS-245)
  * (Experimental) Bus API correctly falls back to multihop connectivity if a direct connection is lost. (#15670)
  * Clarified API docs for `DittoStoreObserver` and `DittoSyncSubscription`. (#SDKS-563)
  * Deprecated `DittoAddress.siteId`. Use PeerKeyString instead. (#SDKS-589)
  * Deprecated `DittoBase.siteId`. Use PeerKeyString instead. (#SDKS-589)
  * Deprecated `DittoIdentity.OfflinePlayground.siteId`. Use PeerKeyString instead. (#SDKS-589)
  * Deprecated `DittoIdentity.SharedKey.siteId`. Use PeerKeyString instead. (#SDKS-589)

  ## 4.10.0 Common Changelog

  ### Added

  * In DQL, an element of an array can be accessed by expression. (feat: Disallow double-quoted identifiers inside of new operators #12529)
  * DQL field and element selection (DQL: Support field and element selection. #13920)
  * Full support for DQL virtual collections, and the system:dual virtual collection (parser changes for virtual collections #14954)
  * On Android, logs now indicate if a missing permission is not declared in an app's AndroidManifest.xml. (Clarify Android missing permission messages based on manifest presence #15094)
  * LIKE DQL operator. (#QE-104)
  * Added `object_keys` and `object_values` scalar DQL functions. (#QE-73)
  * A new system parameter network\_use\_nextgen\_multihop\_stack to switch between our existing and experimental next generation network stacks (#15362)
  * Enabled zlib certificate compression (RFC8879) for small peer TLS 1.3 session negotiation (\[security] enable TLS certificate compression #15801)
  * A system parameter to selectively disable the BLE peripheral (server) transport. (New System Parameter: transports\_ble\_peripheral\_is\_enabled #15802)
  * A STORE\_OBSERVERS\_NUM\_THREADS system parameter to tweak the number of threads used by our store observer runtime to dispatch the sdk callback invocations. (Allow different live queries to be called in *parallel* #15814)
  * The ability to configure a TTL for tombstones in the small peer store, which can be cleaned up via periodic sweeps from the new "reaper" module. (Finish porting the prototype tombstone reaping implementation into main #15886)
  * Support for the new DQL DELETE statement on small peers. (Stabilize the DQL DELETE statement on SP #15899)
  * A new Small Peer Info section named "reaper" and a field named "last\_reap\_time" that indicates the last time the tombstone reaper successfully completed its cleanup of expired tombstones. (Add small-peer-info field to track last completed reaper timestamp #16000)
  * Add support for LIMIT, OFFSET and ORDER BY for mutation statements iin DQL (feat(query/dql): Support ORDER BY, LIMIT, OFFSET in mutation statements #16020)
  * Added support for permanent system wide document deletes with the DELETE keyword in DQL for all Small Peer SDKs. This change requires a coordinated
    release with Ditto Server to ensure data is completely removed from the system. The Ditto Server change will be rolling out over the coming month and
    Ditto will be making a larger announcement upon release. For usage on deletes prior to the larger announcement see the following documents. Note that these documents are only accessible via their direct
    links and will not appear in the navigation bar just yet.

    * [DQL DELETE Syntax](/dql/delete)
    * [Removing Documents with Deletes](/sdk/latest/crud/delete)

    For support on using deletes in your application reach out to [Ditto Customer Support](https://support.ditto.com) to get started.

  ### Fixed

  * A rare scenario where stopping sync with in-progress TCP connections could result in a crash. (#TRANS-303)
  * If Ditto's storage is cloned to another device (not recommended), clones which connect to each other will automatically create a new Peer Key and reauthenticate so that sync can proceed (Trigger reset peer identity when another peer clearly has the same Peer Key, add integration test #14653)
  * On Android, missing system permissions will no longer crash Ditto. (Check for normal permissions in DittoSyncPermissions #15233)
  * Fixed initialisation failing for the Linux Bluetooth transport due to invalid dbus messages (Linux BLE baseline bugfixes #15717)
  * Fix OldQL and DQL comparison between large floats and integers returning an arbitrary result (Fix OldQL and DQL comparison between large floats and integers #15949)
  * Reduced duplicate notifications for authentication state changes. (auth client: validity\_update only on changes #15981)

  ### Changed

  * The link\_enabled system parameter has been renamed to network\_enable\_multihop (\[network] Add configurability for switching between legacy & next gen networking stacks #15362)
  * Improve authentication flow over bad connections (Auth client/server improvements around challenge tokens #15430)
  * Store observers are now invoked in parallel by default. (STORE\_OBSERVERS\_NUM\_THREADS to default to 0 = num\_cpus #16064)
  * Synchronization protocol enhanced to reduce re-transmission of document data and metadata after eviction. (#DS-188)
</Update>

<Update label="4.9.4 " description="Release Date: Feb 17, 2025">
  ## 4.9.4 Common Changes

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** new system parameter which defines the number of threads used by the store observer runtime to dispatch the sdk callback invocations. For more information reach out to Ditto's Support (#15814)
</Update>

<Update label="4.9.3 " description="Release Date: Jan 23, 2025">
  ## 4.9.3 Common Changes

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed**: Added more actionable information to common connection handshake issues. (#15298)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:**  Fixed: Some Android devices could fail to export logs to the portal due to a file permissions error (#15582)
</Update>

<Update label="4.9.2 " description="Release Date: Dec 19, 2024">
  ## 4.9.2 Kotlin Specific Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** Race condition causing NullPointerException trying to initialize Ditto.
</Update>

<Update label="4.9.1 " description="Release Date: Dec 13, 2024">
  <Warning>
    Known NullPointerException bug introduced in 4.9.0 please use 4.9.2 or later.
  </Warning>

  ## 4.9.1 Kotlin/Java Specific Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** Crash in Android WiFi Aware due to too many requests (#15288)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** avoid duplicated multicast connection on WiFi Aware (#15337)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** WiFi Aware does not restart after a stopSync/startSync cycle (#15349)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** Exceptions thrown from user-provided registerObserver lambdas are now logged as an error and re-thrown instead of triggering an unreadable rust panic. Use Thread.setDefaultUncaughtExceptionHandler to handle these exceptions.

  ## 4.9.1 Common Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** iOS 18 crashes related to Bluetooth LE are now resolved. (#15351)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** Disk usage stats are now reported in small peer info on android devices
</Update>

<Update label="4.9.0 " description="Release Date: Nov 21, 2024">
  <Warning>
    Known `NullPointerException` bug introduced in `4.9.0` please use `4.9.2` or later.
  </Warning>

  ## 4.9.0 Kotlin/Java Specific Changes

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** Replacement suggestions to a few deprecated DittoError subclasses, making it easier to update error handling code. (#13162)

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** parameters to control WiFi Aware staleness detection (#13438)

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** INFO log for application background/foreground events (#13493)

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** Error log & transport condition updates in case of insufficient BLE capabilities (#13793)

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** transports\_wifi\_aware\_background\_mode system parameter to control WiFi Aware terminating on background behaviour (#13970)

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** API docs for DittoSmallPeerInfo class. (#14202)

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** New Ditto.updateTransportConfig() method which takes a lambda expression for modifying the active DittoTransportConfig. (#7377)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** properly handle all foreground events (#14118)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** Any exceptions thrown by a custom log callback will be logged as an error instead of crashing. (#14229)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** internal presence observing is now only active when at least one DittoPresenceObserver is active, improving performance. (#14256)

  <Icon icon="triangle-exclamation" iconType="solid" horizontal /> **Deprecated:** DittoBluetoothLeConfig.maxOutgoing. This value can now be configured using the mesh\_chooser\_max\_active\_ble\_clients system parameter. See docs for details: [Using Alter System](../sync/using-alter-system). (#12320)

  <Icon icon="triangle-exclamation" iconType="solid" horizontal /> **Deprecated:** DittoLogger.ffiCustomLog(). Use DittoLog.i() and friends to write to the Ditto log. (#12617)

  <Icon icon="exclamation" iconType="solid" horizontal /><Icon icon="bin-recycle" iconType="solid" horizontal /> **Removed (Experimental):** Experimental Bus API pending a newer stable API. (#13777)

  <Icon icon="exclamation" iconType="solid" horizontal /><Icon icon="bin-recycle" iconType="solid" horizontal /> **Removed:** dittoHandle property, delete(), swigReleaseOwnership() and swigTakeOwnership() methods from Presence. These are internal memory management APIs that can cause memory leaks or crashes if used. (#14201)

  ## 4.9.0 Logging Clarity Improvements

  This release comes with a number of logging clarity improvements. The goal of these changes are to make Ditto logs more consumable and actionable for end users. While there are wide ranging changes one of the principal goals of this work is to make our INFO level logs contain the right information to understand the state and health of the Ditto SDK.

  * More information is included when physical connections start and end (such as the type of connection and the remote peer’s key)

  * Devices that try to connect to themselves now say “device has connected to itself” instead of an error about the remote site ID being the same as the local peer

  * Authentication client logs have been made more human readable. In particular:

  * Recoverable errors are logged together with information about the recovery actions that are being undertaken

  * Several abbreviations have been replaced with human-readable descriptions

  * Errors are printed using their descriptions rather than by dumping debug representations

  * Abbreviated jargon has been replaced with clearer wording in various log lines

  * “phy ended” has become “physical connection ended”

  * “error getting char” has become “required Ditto BLE characteristic not found”

  * “error getting radio state” has become “error getting Windows Bluetooth radio state”

  * Peer events that represent a transport starting or stopping are now logged with the message “transport started”/”transport ended” rather than as a raw peer\_event=... log

  * Reduced the noisiness of “starting” log lines around Ditto initialization time

  * Noise from long peer keys in logs has been reduced in some places by replacing them with their truncated form

  * Noise from duplicated peer ID/peer key information in replication logs has been reduced by consolidating the information

  * “starting compression and export” is now followed by a “completed export” log at the same level

  * Successful SQLite WAL recovery logs were further lowered from INFO to DEBUG

  ## 4.9.0 Common Changes

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** regexp\_like function in DQL. (#12129)

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** peer\_metadata and identity\_service\_metadata to the small peer info document (#12477)

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** WebSocket connections now send X-DITTO-PEERPUBKEY and X-DITTO-ROUTING-HINT headers as part of the client connect handshake on all platforms except wasm32 (#13171)

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** Small Peer Info now includes information about the current logger configuration (#14317)

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** Permission rules can be written in DQL. (#14563)

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** Ditto logs clearly indicate if a device has established a connection to itself. (#14634)

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** the ability for DQL select statement to produce arbitrary projection lists. (#7979)

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** local subscription info to small peer info (#9412)

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** "device\_disk\_usage" information to small peer info (#9784)

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** "store" information to small peer info (#9785)

  <Icon icon="star" iconType="solid" horizontal /><Icon icon="exclamation" iconType="solid" horizontal /><Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** Internal sync metadata format changed. Peers that downgrade to a previous SDK version after upgrading may require full resynchronization. (#14799)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** Improved (de)serialization performance and reduced its contribution to the library size (#11545)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** In updated replication protocol, verification of a received update file no longer requires both peers to use the same approach to subscription hashing. (#12672)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** Experimental multihop connectivity is more resilient to mesh disruptions (#13648)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** Synchronization protocol enhanced to reduce the amount of redundant data sent from small peers to big peers. (#13737)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** Failed certificate verification due to a lagging device clock now results in a clearer error message (#14035)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** Multicast peer-to-peer transport is no longer deprecated to improve support for environments where mDNS is unavailable (#14188)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** Replication no longer redundantly re-transmits unchanged subscriptions after eviction. (#14290)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** truncated peer keys are now logged in lieu of site IDs. (#14362)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** improved logging in the authentication code to provide more useful error context. (#15038)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** made the small peer "log request" feature much more responsive (#9777)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** Windows P2P LAN now can connect to IPv6 peers (#11468)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** In certain rare cases, resetting the same replication session multiple times could cause failure to converge. (#12616)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** Internal connection TLS caches are now bounded in size. This prevents a long living peer from holding onto more memory than required. (#13801)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** small peer info "metadata" is now persisted across app launches. (#13987)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** Bluetooth peers are handled better when disconnections occur, fixing a possible loop where a device might repeatedly try and fail to connect. (#14018)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** When replication sessions time out, write transactions on the document store may be blocked for a long period. (#14148)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** Multicast peer-to-peer transport (non-MDNS) is no longer influenced by TCP listen configuration in DittoTransportConfig (#14187)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** an issue preventing attachment transfers under high document sync load is now resolved. (#14189)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** A race condition that could cause attachments to unexpectedly crash under heavy load. (#14342)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** device name no longer incorrectly defaults to "ditto" in small peer info, when a named device first starts syncing (#14674)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** presence observers are now less-likely to fire when there is no observable change to presence data. (#14807)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** Logs report blocked\_by="no blocking transaction" when blocking transaction is known (#14966)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** In-band authentication data is now cleared on logout. (#15039)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** switching appIDs now invalidates cached authentication material correctly. (#15040)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** Transport conditions are now reported for a wider range of failures when starting Bluetooth and mDNS transports. (#8729)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** documentation for the stopSync() method to clarify that the Ditto store can be used locally after stopping sync. (#8849)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** Auth Client would hang when cached X.509 was expired. (#15110)

  <Icon icon="triangle-exclamation" iconType="solid" horizontal /> **Deprecated:**

  <Icon icon="exclamation" iconType="solid" horizontal />**Removed:**
</Update>

<Update label="4.8.4 " description="Release Date: Jan 31, 2024">
  ## 4.8.4 Common Release Notes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** Some Android devices could fail to export logs to the portal due to a file permissions error (#15582)
</Update>

<Update label="4.8.3 " description="Release Date:Dec 18, 2024">
  ## 4.8.3 Common Release Notes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** iOS 18 crashes related to Bluetooth LE are now resolved. (#15351)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** Added more actionable information to common connection handshake issues. (#15298)
</Update>

<Update label="4.8.2 " description="Release Date: Sept 25, 2024">
  ## 4.8.2 Kotlin/Java Specific Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** Crash on WiFi Aware stalling and Ditto being re-created (#14423)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** Crash on Android after logout (#14562)

  ## 4.8.2 Common Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** Setting the minimum log level to WARN or ERROR will now correctly filter out very early logger initialization messages. (#14451)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** A bug that could prevent an attachment created with the same data on multiple peers from syncing. (#14481)
</Update>

<Update label="4.8.1 " description="Release Date: Sept 5, 2024">
  ## 4.8.1 Kotlin/Java Specific Changes

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** Crash in WiFi Aware when registering network publisher callback (#14013)

  ## 4.8.1 Common Changes

  **<Icon icon="plus" iconType="solid" horizontal /> Added:** The presence\_use\_multihop system parameter can be used to disable replicating presence information to other peers in the mesh, reducing network overhead. Use **ONLY** with guidance from the Ditto Customer Experience team. (#14128)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** When failing to load document data sync (replication) metadata, Ditto now attempts to clear and regenerate the metadata. This is a behavior change where previously Ditto would fail to start. This serves to prevent problems after SDK version downgrades. (#13111)

  **<Icon icon="screwdriver-wrench" iconType="solid" horizontal /> Fixed:** A rare issue where attachments may not be transferred between two peers.(#14158)

  **<Icon icon="screwdriver-wrench" iconType="solid" horizontal /> Fixed:** On-disk logs are more robust in situations with unexpected Ditto shutdown. (#13723)
</Update>

<Update label="4.8.0 " description="Release Date: Aug 28, 2024">
  The version 4.8.0 SDK release update brings a substantial number of improvements and new features designed to enhance your development experience and provide even more powerful tools for building robust, real-time applications.

  ## 4.8.0 Kotlin/Java Specific Changes

  <Icon icon="star" iconType="solid" horizontal /> <Icon icon="plus" iconType="solid" horizontal /> **Added:** Method exportToFile() to DittoLogger, which exports collected logs to a compressed and JSON-encoded file on the local file system. Logs returned through this method are at DEBUG log level. This new API can be used to do forensic log gathering on a device. Logs are always collected and restricted to a fixed specific size limit to ensure they don't grow endlessly. Once the size limit has reached new logs replace the oldest logs. (#11961)

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** Synchronous method exportToFileBlocking() to DittoLogger for Java callers.

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** A new getter and setter for Presence.connectionRequestHandler which take a DittoConnectionRequestHandlerCallback, making the API much easier to call from Java. (#12770)

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** Properties peerKeyString1 and peerKeyString2 on DittoConnection replacing the deprecated properties peer1 and peer2 (#12799)

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** Documentation for startSync() and disableSyncWithV3() to include a recommendation for performance improvement. (#13098)

  Performance of initial sync when bootstrapping a new peer can be improved by calling disableSyncWithV3() before calling startSync().

  Only do this when all peers in the mesh are known to be running Ditto v4 or higher.

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** Documentation for property peerMetadata on DittoPeer to add information about how the property behaves over the lifecycle of the DittoPresenceGraph (#13479)

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** optional hint parameter to upsert() on DittoCollection and DittoScopedWriteTransaction. By providing a hint you can better track the source of blocked write transactions (#7110)

  <Icon icon="star" iconType="solid" horizontal /> <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** Android Wifi Aware internal logic to avoid duplicate attempts to create the network and speed up time to successful connection (#12458)

  <Icon icon="star" iconType="solid" horizontal /> <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** Improve Android WifiAware stability by actively terminate when the application goes into the background and resume when the application comes back to the foreground (#12804)

  <Icon icon="star" iconType="solid" horizontal /> <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** Improve staleness detection in Android Wifi Aware leading to a more reliable connection. (#12866)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** API docs no longer include unintentionally exposed protected members. (#13200)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** (Linux\&Android) Increased mDNS multicast TTL from 1 to 255 to allow for cross-VLAN announcements (#13590)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** Slow or blocked write transactions now log hints showing the waiting and blocking transactions (#7110)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** The SDK will no longer crash when it observes malformed mDNS traffic (#12396)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** The SDK will no longer crash when multiple threads call stopSync() (#11554)

  <Icon icon="triangle-exclamation" iconType="solid" horizontal /> **Deprecated:** Properties peer1 and peer2 on DittoConnection, please use peerKeyString1 and peerKeyString2 instead (#12799)

  <Icon icon="triangle-exclamation" iconType="solid" horizontal /> **Deprecated:** Property queryOverlapGroup on DittoPeer and DittoRemotePeerV2, always return 0 going forward. Query Overlap Groups was an experimental feature that has been removed after it was determined this would not support production scenarios. (#13215)

  <Icon icon="xmark" iconType="solid" horizontal /> **Removed:** delete(), swigReleaseOwnership() and swigTakeOwnership() methods from DittoLogger. These are internal memory management APIs that were unintentionally exposed and can cause memory leaks or crashes if used (#12617)

  <Icon icon="xmark" iconType="solid" horizontal /> **Removed (Experimental):** property queryOverlapGroup of DittoExperimental

  <Icon icon="xmark" iconType="solid" horizontal /> **Removed (Experimental):** method setPriorityForQueryOverlapGroup() from DittoExperimental. (#13215)

  <Icon icon="xmark" iconType="solid" horizontal /> **Removed (Experimental):** deprecated methods setQueryOverlapGroup(queryOverlapGroup:) and setPriority(\_:forQueryOverlapGroup:ditto:) of DittoExperimental

  ## 4.8.0 Common Changes

  <Icon icon="exclamation" iconType="solid" horizontal /><Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** The Logging output format for Ditto SDKs has been changed in 4.8.0 as part of our process to improve readability and observability across the Ditto platform. Customers should validate the new data format in their existing data ingestion pipelines.

  ***New Logging Schema:***

  YYYY-MM-DDTHH:MM:SS.ssssss LEVEL TARGET: MESSAGE \{field1=value1, field2=value2, ...}

  * **Timestamp (YYYY-MM-DDTHH:MM.ssssss):**

  * **Format:** ISO 8601 format (e.g., 2024-08-16T14:23:05.123456Z).

  * **Description:** The exact time when the log entry was generated.

  * **Log Level (LEVEL):**

  * **Format:** One of the following levels— DEBUG, INFO, WARNING, ERROR.

  * **Description:** Indicates the severity or importance of the log entry.

  * **Target (TARGET):**

  * **Format:** A string, representing the internal module/area

  * **Description:** The source of the log entry, often corresponding to the internal module where the error was called. (e.g. ditto\_init or peer\_event\_listener)

  * **Message (MESSAGE):**

  * **Format:** A human-readable string.

  * **Description:** The main content of the log entry.

  * **Structured Fields (\{field1=value1, field2=value2, ...}):**

  * **Format:** A list of key-value pairs enclosed in curly braces.

  * **Description:** Any additional structured data associated with the log entry. These fields can include custom data that you attach to the log entry using the tracing::info!(field1 = value1, "Message") syntax.

  ***4.7 and earlier Logging Format Example***

  \[INFO] 2024-08-02T10:25:39.981Z: AuthClient: using cached SiteId; site\_id = 16248337916605943930

  ***4.8.0 and later Logging Format Example***

  2024-08-02T11:32:25.905562+01:00 INFO ditto\_init:new\_auth\_client: ditto\_auth: using cached SiteId site\_id=16248337916605943930

  <Icon icon="star" iconType="solid" horizontal /> <Icon icon="plus" iconType="solid" horizontal /> **Added:** DQL support for string functions byte\_length and char\_length #12147

  <Icon icon="star" iconType="solid" horizontal /> <Icon icon="plus" iconType="solid" horizontal /> **Added:** DQL support for inline object and array literal creation #12312

  <Icon icon="star" iconType="solid" horizontal /> <Icon icon="plus" iconType="solid" horizontal /> **Added:** object\_length and deserialize\_json functions in DQL #12605

  <Icon icon="star" iconType="solid" horizontal /> <Icon icon="plus" iconType="solid" horizontal /> **Added:** DQL INSERT statements support inlining the construction of an object #12761

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** Remote query capability allows Big Peer to execute read-only queries on Small Peers. Usage currently internal to Ditto Customer Experience team members #12268

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** Diagnostics are now provided when collecting Small Peer Info on-disk logs #12080

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** output version, sdk and build information on startup for easier debugging #12845

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** Introduced new internal capabilities ensure a large data payload (e.g. a large attachment file) cannot use all the bandwidth and prevent other data from being synced.

  <Icon icon="plus" iconType="solid" horizontal /> **Added:** mDNS transport can now be configured with a static port for the TCP server using the tcp\_server\_bind\_mdns\_server\_port system parameter #13442

  <Icon icon="star" iconType="solid" horizontal /> <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** New logging format that includes detailed information #10794

  <Icon icon="star" iconType="solid" horizontal /> <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** The Ditto logger is now more verbose by default, with a minimum log level of INFO instead of WARNING #11141

  <Icon icon="star" iconType="solid" horizontal /> <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** small peer info collection is now enabled by default and its default sync scope is now BigPeerOnly #12709 (Device dashboard will populate information automatically)

  <Icon icon="exclamation" iconType="solid" horizontal /><Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** (**Experimental**) Multihop connections are formed more efficiently, e.g., for Ditto Bus. This is an incompatible protocol change from previous versions #12108, #12623

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** Improve performance by avoiding deserializing the entire Document if only part of it is required #10887

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** Attachments now sync independently of documents, improving rainbow connection efficiency #11156

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** Updating several dependencies for security patching (Patch multiple old packages #12087)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** How network OS capabilities are internally linked into the library to allow for more reliable and reusable internal logic #12362

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** API documentation for execute method to include information about its interaction with sync subscriptions #12365

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** Default to creating backup Bluetooth connections when there is an existing WiFi connection (Default mesh\_chooser\_avoid\_redundant\_bluetooth to false #13398)

  <Icon icon="rotate-reverse" iconType="solid" horizontal /> **Changed:** console logging will now output to STDERR instead of STDOUT (\[logs] logging now outputs to STDERR instead of STDOUT #13477)

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** Bytes and Arrays not being always comparable in the legacy query language #10887

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:** Legacy query language casting counters and maps with tombstones to the wrong boolean value #10887

  **<Icon icon="screwdriver-wrench" iconType="solid" horizontal /> Fixed:** Lowered the log level of a few SQLite3 notices that were being unnecessarily logged as warnings #12032

  **<Icon icon="screwdriver-wrench" iconType="solid" horizontal /> Fixed:** A crash that can occur if a DQL query contains a multi-byte character #12324

  **<Icon icon="screwdriver-wrench" iconType="solid" horizontal /> Fixed:** An issue with the transports multiplexer that could lead to a hung process. This occurred when dealing with large messages spanning multiple chunks (>64KB) #12428

  **<Icon icon="screwdriver-wrench" iconType="solid" horizontal /> Fixed:** A rare edge case that could slow down data sync between peers #12527

  **<Icon icon="screwdriver-wrench" iconType="solid" horizontal /> Fixed:** Frequent subscription changes along with eviction calls could cause failure to converge on data leading to inconsistent data state #11431

  **<Icon icon="screwdriver-wrench" iconType="solid" horizontal /> Fixed:** Memory leak in third party library used for peer-internal messaging #12895

  **<Icon icon="screwdriver-wrench" iconType="solid" horizontal /> Fixed:** Transport inactive connection tracking no longer stores identifiers indefinitely. This could lead to a slow growth in memory consumption for long lived applications (\~ 1MB/day on transports with high rate, unreliable discovery - such as BLE) #13147

  **<Icon icon="screwdriver-wrench" iconType="solid" horizontal /> Fixed:** Unexpected failures to obtain a certificate for peer-to-peer sync are now logged at ERROR level instead of WARNING #13323

  <Icon icon="exclamation" iconType="solid" horizontal /><Icon icon="bin-recycle" iconType="solid" horizontal /> **Removed:** (**Experimental**) Ditto no longer supports the experimental Query Overlap Groups feature and support has been removed. This experimental feature has been removed after running a determining a lack of feasibility in production scenarios. The team is iterating and plan on introducing improved capabilities. #13075
</Update>

<Update label="4.7.4 ">
  ### ADDED: Support for specifying the mDNS connection ports for Small Peer SDK instances

  Allows you to specify a specific port that can will be used for mDNS announcements and connections on a given device. This can be used for connect with peers across a VLAN while scanning for open ports.

  Not setting the config will result in the current default behavior of a random port being assigned.

  <Warning>
    If running multiple application on the same device, for example a debug and/or test flight application along side a production application, each application needs to have a unique port.

    Failure to do this will result in only one application being able to establish connections at a given time.
  </Warning>

  ***Setting the config***

  The config can be set using DQL `ALTER SYSTEM` and the `tcp_server_bind_mdns_server_port` config.

  ```sql DQL theme={null}
  ALTER SYSTEM SET tcp_server_bind_mdns_server_port TO 1234
  ```

  This command should be run using the `ditto.store.execute(...)` command within your application.

  <Warning>
    `tcp_server_bind_mdns_server_port` needs to be set \*\*\*before \*\*\*`startSync()` is called to be applied.
  </Warning>

  <CodeGroup>
    ```swift Swift theme={null}
    let result = await ditto.store.execute(query: "ALTER SYSTEM SET tcp_server_bind_mdns_server_port TO 1234")
    ```

    ```kotlin Kotlin theme={null}
    val result = ditto.store.execute("ALTER SYSTEM SET tcp_server_bind_mdns_server_port TO 1234")
    ```

    ```javascript JS theme={null}
    const result = await ditto.store.execute("ALTER SYSTEM SET tcp_server_bind_mdns_server_port TO 1234");
    ```

    ```java Java theme={null}
    DittoQueryResult result = ditto.store.execute("ALTER SYSTEM SET tcp_server_bind_mdns_server_port TO 1234");
    ```

    ```csharp C# theme={null}
    var result = await ditto.Store.ExecuteAsync("ALTER SYSTEM SET tcp_server_bind_mdns_server_port TO 1234");
    ```

    ```cpp C++ theme={null}
    auto result = ditto.get_store().execute("ALTER SYSTEM SET tcp_server_bind_mdns_server_port TO 1234").get();
    ```

    ```rust Rust theme={null}
    let result = ditto.store().execute("ALTER SYSTEM SET tcp_server_bind_mdns_server_port TO 1234", None);
    ```

    ```dart Dart theme={null}
    final result = await ditto.store.execute("ALTER SYSTEM SET tcp_server_bind_mdns_server_port TO 1234");
    ```
  </CodeGroup>

  ### FIXED: A finalizer issue that was causing crashes when closing sync subscriptions (#13849, #13732, #13738)

  Resolves a race condition that could be hit when closing a sync subscription or stopping sync that caused Ditto to crash.

  ### IMPROVED: (Linux/Android) Increased mDNS multicast TTL from 1 to 255 to allow for cross-VLAN announcements (#13590)

  To support scenarios with cross-VLAN device discovery we increated the TTL to ensure message have enough time to reach their destination and get acknowledged.

  ### Fixed: Intermittent crash when finalizing a legacy `DittoSubscription` that contained a `sort()` clause. (#13394)

  Resolves and issue where using `sort()` in sync subsriptions with the legacy query builder would result in a crash.

  ### Fixed: Included necessary symbols so that Ditto Core crashes can be properly symbolicated with crash reporters. (#13696)

  Previously not all symbols were being included in the package bundle and this led to crashes not being able to be symbolicated and ultimately made readable.

  Now the Kotlin bundle includes the correct packages

  <Warning>
    The extra symbols slightly increase the bundle size. If this additional size is an issue for your application, we recommend stripping these symbols when compiling your production build.

    However, please note that stripping symbols will make crash reports in production unreadable, which could lead to longer resolution times for live site incidents.
  </Warning>
</Update>

<Update label="4.7.3 ">
  ### FIXED: An issue causing a race condition with a Live Query callback. (#13180)

  This fix addresses the issue causing a Live Query callback to receive a delta update, known as a *diff*, before the initial document.&#x20;

  ### FIXED: A compatibility issue between documents created using different CRDT versions. (#13236)

  Previously, there was an issue in which two documents on different internal versions could fail to integrate changes created using an older CRDT version.

  ### IMPROVED: Logging for batch write transactions. (#13339, #13339)

  Due to a race condition caused by the logging system mistakenly identifying the previous transaction as blocking the current one, the logger would inaccurately indicate the current transaction as being blocked by the previous one from an `unknown` originator.

  ### FIXED: An issue in the Small Peer datastore causing slow performance or process termination. (#13395)

  This issue was due to an aging dependency with a race condition, which caused thread tasks to get stuck and transactions to be blocked for extended periods.

  ### IMPROVED: The Ditto SDKs compilation performance. (#13174)

  We've optimized compilation by reducing the size of each binary slice of the Ditto SDKs by 19% and fixing incompatibility with `PLCrashReporter`.

  ### FIXED: Kotlin and Java Android devices now appear as `JVMBased` in the Device Dashboard instead of `Unknown`. (#13251)

  ### FIXED: An issue causing a crash with the message `gatt must not be null`. (#13411)
</Update>

<Update label="4.7.2 ">
  ### ADDED: `mesh_chooser_avoid_redundant_bluetooth` system parameter. (#12984)

  This new system parameter allows greater control over the use of Bluetooth Low Energy (LE) connections in Ditto's peer-to-peer mesh network. When set to `false`, Ditto creates Bluetooth LE connections alongside other peer-to-peer connections, serving as a fallback if the primary transport, such as Apple Wireless Direct Link (AWDL) or LAN, fails.

  However, before you enable the `mesh_chooser_avoid_redundant_bluetooth` parameter, consider the following technical tradeoffs:

  * Benefits:
    * Provides additional fallback to maintain connection stability when primary connections cease to function.
    * Reduces time to establish new connections since, by having multiple fallback options, Ditto can more quickly re-establish connections.
  * Drawbacks:
    * Increases network traffic since using multiple transports results in additional network overhead
    * Using Bluetooth LE alongside other transports increases resource consumption. In the worst case, enabling this setting can result in slower sync performance and battery drain.

  To enable the `mesh_chooser_avoid_redundant_bluetooth` parameter, use the following DQL query:
  `ALTER SYSTEM SET mesh_chooser_avoid_redundant_bluetooth = false`

  ### CHANGED: The `AuthClient` by improving the log message for certificate issues returned from the Big Peer Authentication Service. (#13138)

  ### FIXED: A performance-related issue affecting bulk eviction operations for documents with attachments. (#12331)

  ### ADDED: Improved data compression in the handshake protocol when establishing connections to other peers. (#11264)

  This allows peers with large permission sets to establish connections on low bandwidth transports like Bluetooth LE more quickly.&#x20;

  ### FIXED: The HTTP protocol by adding `content-length: 0 header` compliance in empty `POST` requests. (#12346)

  Before, if you invoked an empty `POST` request, the cloud load balancer would reject your request with a `411 - Length Required` error message.

  Now you must explicitly state that the body of your `POST` request is empty by setting `content-length: 0` in the header of your HTTP API call.

  ### FIXED: Handling of malformed subscription queries in the legacy query builder API by adding validation logic early to ensure invalid queries are identified early and logged. (#12463)

  There was an issue where invoking `subscribe()` on an invalid query caused sync to be silently disabled.

  Invalid queries in the `subscribe()` method are now identified, disabled, and logged as errors.

  ### FIXED: Subscription assumption logic so all acknowledgments are processed, regardless of subscription changes. (#12541)

  In scenarios where subscriptions rapidly changed back and forth while documents were being concurrently altered, documents would diverge at merge.

  We’ve removed subscription logic ignoring acknowledgements based on assumed subscription mismatch and introduced salting functionality to ensure each document is unique for each occurrence of a subscription. This helps differentiate between new and reverted subscription states.

  ### FIXED: Sync inefficiency where changing a subscription resulted in unnecessary syncing of redundant update files. (#12967)

  To eliminate redundant data from being synced unnecessarily, regardless of whether the remote peer previously acknowledged them, we’ve added validation checks ensuring that only unacknowledged data is synced.

  This fix reduces sync update file sizes, leading to more performant session sync updates, particularly in apps consisting of large, stable subscriptions and infrequent document changes.

  ### CHANGED: Reduced Bluetooth LE `warn` log noise. (#12674)

  Changed: handle reverse DNS lookup queries in Android mdns to avoid mdns failing to connect in specific network configs &#x20;

  ### CHANGED: Android `mdns` to handle reverse DNS lookup queries. (#13000)

  By adding reverse DNS lookup queries, Android `mdns` no longer fails to connect in specific network configurations.&#x20;

  ### FIXED: Wi-fi Aware so it is available on API level 32. (#12631)

  ### FIXED: Missing version metadata. (#12843)

  Now version metadata is correctly included in the string returned from `Ditto.sdkVersion`.
</Update>

<Update label="4.7.1 ">
  ### FIXED: Misleading errors related to attachment fetch operations. Now, associated error logs are more accurate and clear. (#12409)

  ### FIXED: A specific issue where incorrect sync metadata rollback caused problems with data consistency at merge. (#12422)

  ### FIXED: The documentation for the DittoStore.fetchAttachment API method. (#11783)

  Before this patch release, the documentation incorrectly stated that the return value had to be kept in scope for the fetch to complete.  As of this release, the documentation specifies that the return value does not need to be kept in scope.

  ### ADDED: DittoExperimental.constructDittoFailable() API method. (#11801)

  Previously, your app crashed if the persistence directory was already in use by another Ditto instance. Now, rather than crashing in such scenarios, Ditto throws a `DittoError.LockedWorkingDirectoryError` error.&#x20;

  ### ADDED: DittoExperimental.constructDittoFailable() API method.&#x20;

  Now, you can use this experimental alternative to the original Ditto constructor to prevent crashes when the persistence directory is still in use by another Ditto instance at the time of calling the constructor. Now, rather than crashing in such scenarios, Ditto throws a `DittoError.LockedWorkingDirectoryError` error. (#11801)

  ### FIXED: Exceptions that occur while creating or fetching attachments now include more details about the underlying cause in their error message for easier debugging. (#12235)

  ### Fixed: An issue that prevented some attachment fetcher events from being delivered to event handlers. (#12331)

  ### FIXED: Closing an attachment fetcher that failed to start downloading no longer results in an exception. (#12490)

  ### FIXED: Handling of document-paths containing non-alphanumeric characters. Previous versions may have removed these characters from document-paths. (#12556)
</Update>

<Update label="4.7 ">
  ### FIXED: The legacy query language error-throwing mechanism to accept invalid field names properly. (#11888)

  After upgrading to version 4.7 of the SDK, you may notice unexpected errors while using the legacy query builder language. These errors are likely due to invalid field names or path expressions previously undetected.

  In addition, make sure to start `unquoted_string` with an underscore (`_`), a letter, or an alphanumeric character. For example, the following equivalent regular expression: `[A-Za-z_][A-Za-z0-9_]*`.

  <Warning>
    In the legacy query builder language, invalid field names and path expressions now throw explicit errors. Previously these invalid names did not throw and would cause undefined behavior.

    **Note: This new error-throwing behavior applies only to the legacy query builder language; DQL is unaffected by this improvement.**
  </Warning>

  ### REMOVED: The `is_connected_to_big_peer` field from the Small Peer Info document. (#11883)

  ### CHANGED: The small peer info JSON metadata by increasing the depth limit to 64 levels. (#11891)

  ### IMPROVED: Transaction contention time for the `ATTACHMENT` data type, reducing potential timeouts. (#11893)

  Before this improvement, concurrent write transactions were long-lived, potentially causing deadlocks and request timeouts. Now you'll experience more effective handling of multiple attachments being processed at the same time.

  ### FIXED: The issue causing sync crashes due to missing update files. (#11952)

  With the latest release, Ditto handles unexpected situations or errors in a way that allows it to recover and continue functioning without crashing or causing disruptions.

  ### ADDED: Parameters for adjusting certain settings during runtime. (#11968)

  This rollout includes new system parameters for the `MeshChooser` feature for configuring a limited set of variables, allowing you to adjust certain settings during runtime.

  ### RESOLVED: The warning message when peers connect is no more. (#11977)

  The warning message previously logged when peers connected within the mesh is no longer recorded or printed.&#x20;

  ### IMPROVED: Sync performance by sending the entire state of the data. (#12029)

  Previously, when syncing in mixed mesh environments from Ditto SDK version 4.0.0 of the SDK to version 3.0.0, only partial updates were transmitted. With this release, all updates are transmitted, resulting in greater data consistency and completeness when syncing across different versions of the SDK.

  ### FIXED: The issue causing the Small Peer Info collector to become stuck. (#12051)

  Previously, the Small Peer Info collector would become stuck when attempting to upload logs in certain situations. Since resolving this issue, the Small Peer Info collector functions properly in those conditions.

  ### FIXED: The issue causing fetch operations to appear unresponsive. (#9501, #12067)&#x20;

  With this fix, operations related to fetching attachments function as expected.

  ### FIXED: The issue causing type check failures when setting duration parameters through ALTER SYSTEM SET. (#12070)

  When using `SystemParameter` to configure timeouts before this fix, if using different types to encode the values representing the timeout, for instance, `Milliseconds` and `Seconds`, the values failed to downcast, an error log printed, and the new value ignored.

  Now, when using mismatched wrapper types, Ditto performs a compatibility check, validates, and, if needed, converts them as appropriate.

  ### FIXED: P2P LAN now advertises on newly added interfaces, such as enabling WiFi at runtime.

  ### FIXED: The deviceName property on Ditto instances now reflects the truncation of the value to 24 bytes when starting sync.

  ### ADDED: Property connectionRequestHandler to ditto.presence, including related types, allowing filtering of incoming connections from other peers.

  ### Added: Properties `peerMetadata` and `peerMetadataJsonString` to `ditto.presence`.

  ### Added: Property `identityServiceMetadata` to DittoPeer.

  ### Added: Property `peerKeyString` to `DittoPeer` as a replacement for the now deprecated `peerKey`.

  ### DEPRECATED: Property peerKey on DittoPeer, please use the newly added peerKeyString instead.

  ### ADDED: Runtime checks and locks to guard against dangling raw Ditto pointer usage in extremely unlucky race condition scenarios.

  ### FIXED: Possible crash while downloading an attachment due to improper decoding of the attachment token.
</Update>
