Published OnOctober 28, 2026October 27, 2026

Ditto SDK 5.2 - Troubleshoot Faster. Operate Better.

Ditto SDK 5.2 delivers faster troubleshooting, more stable wireless connectivity that is self healing, apps that use less memory and disk space, and data encryption for Swift and Kotlin.

Ditto SDK 5.2 - Troubleshoot Faster. Operate Better.

Today we're excited to highlight the top features in the Ditto SDK 5.2 release. In total, this release includes:

  • 71 platform-level improvements that benefit every application.
  • 100 SDK-specific refinements across our language SDKs.

Ditto is a database that makes it easy to keep applications running even when the Internet drops or network connectivity is spotty. Anyone can build their application on top of Ditto.

Our database runs locally. Every read and write completes even if the Internet or network is down. If connectivity drops, nearby devices connect peer-to-peer over Bluetooth, Wi-Fi, or the local network to share data without a server in the middle. Our database engine will take in new updates, then synchronize that data across your devices. When the Internet comes back, every device shares its data and catches up automatically. If the Internet is available, devices can also sync globally through a Ditto Server in the cloud.

Key takeaway: Ditto SDK 5.2 gives apps faster troubleshooting, more durable wireless network connectivity, improved memory and storage usage, and data encryption for apps built in Swift and Kotlin.

1
Faster Troubleshooting: Request a support bundle on any device with one query statement. A new system collection shows which documents aren't syncing.
2
Wireless Stability: Network connectivity over Bluetooth Low Energy, Wi-Fi Aware on Android, and Apple's peer-to-peer Wi-Fi is more stable and self healing. You don't need to restart your app to reconnect.
3
Connections: Devices will start sync faster after a network blip, and connections to the cloud that have quietly stopped working will close instead of lingering.
4
Memory and Storage: Live queries hold less memory and are more efficient. Ditto's database files no longer grow unchecked on devices that run for months.
5
Encryption at Rest: Swift and Kotlin apps can encrypt Ditto's local database with a key the app controls. Sensitive information is protected, and documents on a lost or stolen device are unreadable without the key.

1. Faster Troubleshooting

In edge computing, it's tough to troubleshoot and fix a device that misbehaves in the field. The device might have spotty connectivity, be far away, or be constantly in use. Now, it's easier to remotely pull and analyze troubleshooting information from a device.

A device in the field ? Orders stopped syncing on one handheld No one can reproduce it in the lab, and the device is 3,000 miles away. Ask the device for a support bundle with DQL EXECUTE FUNCTION system_request_support_bundle() Run it from an admin screen, a remote command, or the debug socket. Bundle Then query it like any other data SELECT * FROM system:support_bundles lists the bundles on the device SELECT * FROM system:sync_degradations orders/1042 → sync degraded Diagnostics from a query. No debug build, no site visit.
  1. A device misbehaves, far from the lab
  2. One DQL statement requests a support bundle
  3. List the bundles and documents that aren't syncing
1/3

Request a support bundle

A support bundle is a package of logs, configuration, and metrics that show how one device is running and using Ditto. It's the first troubleshooting step for every customer and the Ditto support team when something goes wrong. Previously, customers had to pull the support bundle from inside their app. In SDK 5.2, you can request a bundle with a single remote statement.

DQL is Ditto's query language, and it looks a lot like SQL. The new system:support_bundles collection lists every support bundle on the device. System collections are built-in collections that describe Ditto itself, and you can query them the same way you query your own data.

EXECUTE FUNCTION system_request_support_bundle()
SELECT * FROM system:support_bundles

Because it's a query, you can trigger it from wherever your app already runs Ditto queries. That includes an admin screen, a remote command from your backend, or a debug socket. Bundle data has been expanded to include the device's recent request history and a snapshot of its index metadata.

See which documents aren't syncing

"Why hasn't this document synced?" is one of the most common questions our support team hears. The new system:sync_degradations collection answers it directly. It lists documents whose sync is degraded, so you can find a stuck document before a user reports it.

When a device isn't syncing, it's easier to identify the root cause. system:metrics adds query-engine metrics for request counts, failures, execution time, and network connection health metrics. We made some small changes to reduce noisy logs, and on-disk logs no longer lose entries when log files rotate quickly.

2. Wireless Stability

Peer-to-peer radios allow Ditto apps to stay connected when the network goes down. Three transports are relevant to most phones and tablets:

  • Bluetooth Low Energy (BLE) is a short-range and low-power radio in nearly every phone. It's always available but it has less network bandwidth.
  • Wi-Fi Aware (WFA) lets Android devices connect directly over Wi-Fi without a router or access point in the middle. It has more network bandwidth for data transfer.
  • Apple Wireless Direct Link (AWDL) is Apple's version of Wi-Fi Aware. It's the technology behind AirDrop, and it lets Ditto sync data between nearby Apple devices without a router.

SDK 5.2 fixes a set of wireless connectivity problems that showed up in production. These problems required one (or multiple) application restarts to fix the connectivity issue.

Wi-Fi Aware has better mesh formation and stability

Wi-Fi Aware gets the most fixes in this release:

  • Meshes of three or more devices no longer split into isolated pairs (islands). This isolation would prevent devices from syncing with the rest of the mesh.
  • When a connection looks unhealthy, Ditto refreshes its connections instead of entirely restarting the Wi-Fi Aware stack.
  • Active connections survive rapid transport restarts, subsystem restarts, and two devices discovering each other at the exact same time.

Bluetooth LE on Android handles channel failures gracefully

When an Android device connects to a peer over BLE, Ditto tries to open a special high-speed BLE channel to sync data. Previously, if that channel couldn't be opened or closed, your app could crash. This can happen if Bluetooth is turned off while two peers are connecting. In SDK 5.2, sync will recover smoothly and continue over the standard Bluetooth path instead.

Apple peer-to-peer Wi-Fi recovers on its own

AWDL connectivity now recovers automatically after a temporary network setup failure. Previously, it could remain unavailable until an app was restarted. Now, Ditto runs more consistently on devices like an iPad mounted in a kiosk that rarely restarts.

3. Connections: Faster Reconnects and Stalled-Connection Detection

A device can only sync while it has a live connection to another peer. Wireless links drop all the time in the real world, like when a forklift drives behind racking, a phone goes into a pocket, or a router reboots. SDK 5.2 shortens the time it takes to get back to syncing after an interruption, and it makes it harder for a dead connection to silently linger.

Device Peer Two peers syncing over the local network The link drops Someone walks out of range, a metal doorway blocks the signal, or a router reboots. Every second before sync resumes is a second the two devices disagree. Before 5.2 full handshake: verify identities, agree on keys syncing Now with 5.2 resume recent session syncing Reconnecting to a peer you've seen recently skips most of the handshake. the cloud, over WebSocket probe after 30s idle probe probe closed, reconnecting A stalled connection that looks open but nothing moves TCP keepalive is now on by default for WebSocket connections. The device reconnects instead of waiting on a bad connection.
  1. Two peers are syncing
  2. The link drops
  3. 5.2 resumes the session instead of starting over
  4. A stalled cloud connection is caught and closed
1/4

Faster reconnects to peers you've seen before

Before two devices can sync, they go through a handshake. Each device verifies the other's identity, and the two agree on encryption keys. It's essential, but it takes time, especially on a slow or lossy link. Ditto syncs over several transports, and on a local network it uses TCP with TLS. In 5.2, reconnecting to a peer the device has seen recently over that transport can use an abbreviated TLS handshake, which skips redundant handshake negotiation. That cuts the time between a network blip and the first synced change.

Starting up is smoother too. Local-network peer discovery on Linux and Android causes smaller traffic spikes when many devices start at the same time. Customers often see this use case when a store opens for the day or a fleet of vehicles powers on.

Stalled connections are detected

Some network connections don't drop cleanly. The operating system thinks they are open, but nothing moves across them. This can happen when the device on the other side vanishes, or a timer on one end stops firing. A stalled connection is worse than a dropped one, because a device will keep waiting on it instead of creating a new healthy connection.

WebSocket is the transport a device uses to reach Ditto's cloud and other servers. Native WebSocket connections now turn on TCP keepalive by default, on both the client and server sides. Keepalive is a kernel-level check. If a connection sits idle, the operating system sends small probes. If the probes go unanswered, the device closes the connection so Ditto can reconnect. The defaults are:

SettingDefault
Idle time before the first probe30 seconds
Interval between probes10 seconds
Unanswered probes before closing3

Ditto's own protocol-level keepalive is still the first line of defense. TCP keepalive is a backstop for when Ditto's timers or the runtime itself has stalled. You can tune it with the transports_websocket_so_keepalive_* system parameters, and browser clients aren't affected.

4. Memory and Storage Health

Edge devices share a fixed amount of memory and disk between every app that is installed. They often run for months without a restart. Both resources can leak slowly if you're not careful. SDK 5.2 trims what Ditto holds in memory, skips work that produces no new result, and keeps the on-disk footprint from growing without bound. Existing apps built on Ditto will get these improvements without code changes.

Live queries hold less memory

A store observer is a live query. You register a query once, and Ditto calls you back with fresh results whenever the matching data changes. Most app screens are built on observers, and long-lived observers over large data sets can consume more memory over time. We've made a number of query improvements to optimize memory usage:

  • Query results stay compact until you read them.
  • Observers no longer keep observed documents fully decoded between updates, and reading a document no longer pins its decoded form in memory.
  • Observers whose queries can't be updated incrementally, such as projections or index-backed lookups, no longer keep a copy of the previous result set.
  • Peak memory is lower while an observer builds its callback result.

Less wasted work

Store observers are also more efficient. A store observer runs a query against a data set (called a collection in Ditto), and then it updates your app whenever that query's result changes. Previously, any local write would fire every observer on the device. This happened even if a write updated a collection that an observer didn't watch. A write to orders would make an observer for products check for updates, only to find nothing new.

Now, an observer only runs when the collection it watches is written to. Your callbacks fire exactly as before. Devices will spend far less time checking collections unnecessarily. Observers on system collections will now fire when the data changes instead of polling on a timer. This removes a steady source of background work on idle devices.

Write to orders Local store orders products Observer on orders Observer on products Your app writes a document to the orders collection Each observer watches one query and calls your app when that query's result changes. Before: Every observer woke up and re-ran its query re-ran, result changed re-ran, found nothing The observer on products did the work of a query for a write that could never affect it. After SDK 5.2: Only the observer on orders runs re-ran, result changed stays asleep Your callbacks fire exactly as before. The device just skips the queries that can't have changed.
  1. A write lands in orders
  2. Before: Every observer re-ran its query
  3. After SDK 5.2: Only the orders observer runs
1/3

Database files stay bounded on long-running devices

Ditto's local data store is built on SQLite which keeps a write-ahead log. It is a file where new writes land before they're folded into the main database. On devices that run for weeks or months, that log could grow continuously. SDK 5.2 keeps it in check and reclaims free disk space automatically. If the write-ahead log keeps growing anyway, Ditto logs a warning that usually points to a long-held read transaction, which gives you a lead to follow.

Oversized documents no longer stall sync

Ditto documents have a hard size limit. When a device receives a change that would push a document over that limit, it now drops that change. The oversized document gets no more updates until it's evicted and synced again. Evicting removes a document from the local store without deleting it anywhere else.

5. Encryption at Rest for the Local Data Store

Many Ditto apps run on devices that can be lost or stolen, like handhelds, tablets, and kiosks. For some customers, that's a reportable incident and a big risk. Encryption at rest is important to customers that handle sensitive data in industries like healthcare, government, and finance. Apps in these industries often handle data like personally identifiable information, military operations, or payment details.

Encryption at rest means Ditto's documents on disk are unreadable without a key. Copying the app's files or pulling the storage from a device doesn't expose your data. SDK 5.2 adds application-level encryption for the local data store, with a key your app generates and keeps.

A handheld ditto_store/ (on disk) orders/1042 customer: "A. Rivera" total: 184.20 orders/1043 customer: "J. Okafor" total: 92.00 customers/88 phone: "+1 555 0142" address: "..." inventory/sku-7 count: 31 location: "Aisle 4" 9f3a c01e 77b2 4d8e 1a90 e5c3 0b7f 62d4 ab11 3e9c 5c2d 8e41 f07a 93bb 6e1d 2c58 d4a9 0f36 71e8 b2c0 e17b 04c9 a6f2 3d85 b9e0 5a1c 7f48 c3d6 20ab 9e57 38d0 f6a1 2b7e c94d 05e3 81fa 4c6b d2e9 a70f 1b3c Your app's documents live on the device, in Ditto's local store. Without encryption at rest copy the files, read the data If a handheld is lost, you can remove it from the mesh. The data on disk is still readable. 5.2: Encrypted with your key unreadable without it Swift and Kotlin apps set the key when they open Ditto. The key is yours to protect.
  1. Documents live on the device
  2. The device is lost and the files are readable
  3. 5.2: Encrypted with a key your app controls
1/3

Encrypt the local store with your own key

Swift and Kotlin apps can now encrypt the local store at rest with a raw 32-byte key through DittoConfig.encryptionKey. You generate and manage the key, and Ditto uses it to protect documents on disk. Keep the key in your own secure storage, never next to the store it protects. Here's an example of how to use this data encryption feature in Kotlin:

val keyBytes: ByteArray = loadKeyFromSecureStorage() // 32 bytes
val config = DittoConfig(
    databaseId = "REPLACE_ME_WITH_YOUR_DATABASE_ID",
    connect = DittoConfig.Connect.Server(url = "REPLACE_ME_WITH_YOUR_URL"),
    encryptionKey = DittoEncryptionKey.raw(keyBytes)
)
val ditto = Ditto.open(config)

Typed encryption errors

Every SDK now reports a typed error when a store fails to open for an encryption reason like key required, key unexpected, key invalid, unsupported scheme, or metadata corrupt. Your app can tell a missing key from a corrupted store and respond to each one, instead of treating every failure the same way.

Wipe a device cleanly

Swift adds Ditto.close() and Ditto.deleteStore(). Kotlin adds DittoFactory.deleteStore(). Flutter's Authenticator.logout accepts a cleanup callback that runs after logout completes. Together with encryption at rest, they make it simple to remove Ditto's local data on logout or when a device changes hands.

Bonus: Set system parameters when you open Ditto

System parameters determine how Ditto behaves on a device like connection limits, keepalive timers, and feature switches. Most apps never touch them. Some special deployments need to, like a large mesh that needs a higher connection limit.

Previously, you had to change a system parameter with a DQL ALTER SYSTEM SET statement after Ditto.open() returned. Some parameters are only read during open(), so they could never be changed at all. Now, every SDK can pass system parameters into DittoConfig, and Ditto applies them before it starts. Startup-only parameters can be set, and there's no window where Ditto unexpectedly runs on the defaults before applying ALTER SYSTEM SET changes. Invalid values fail at open(). ALTER SYSTEM SET still works the same way at run time.

let config = DittoConfig(
    databaseID: "REPLACE_ME_WITH_YOUR_DATABASE_ID",
    connect: .server(url: "REPLACE_ME_WITH_YOUR_URL"),
    systemParameters: [
        "transports_websocket_so_keepalive_idle_secs": 60
    ]
)
let ditto = try await Ditto.open(config: config)

Try Ditto for free

New to Ditto? It takes a few minutes to see offline-first sync working on your own devices.

  • Create a free account and follow the quickstart for your language.
  • Build the sample app, run it on two devices, and turn off the Wi-Fi.
  • Watch the devices connect peer-to-peer and sync data locally.

New to Ditto? Contact us to see what offline-first sync can do for your application.

Read the release notes

This post covers the five biggest feature themes. The full release notes cover all 171 improvements, including:

  • Platform fixes for Flutter, React Native, Kotlin, and C#, with the per-SDK changelogs.
  • Query engine fixes for DELETE, EVICT, ANY ... SATISFIES, and composite indexes.
  • Every system parameter and behavior change in SDK 5.2.

Upgrade to SDK 5.2 today

When you upgrade to SDK 5.2, existing apps are easier to troubleshoot, more resilient over wireless links, and lighter on resources without any code changes.

  • Bump your dependency to 5.2.0. Most apps need no code changes.
  • Customers may see new SDK warnings depending on their Ditto implementation.
  • Apps on SDK 5.2 sync with apps on earlier versions. The upgrade is backward compatible.
  • Read the upgrade section in the release notes for more detailed information.
Read more
Python SDK Preview: Sync for Robots and AI at the Edge
Product
Announcement
September 29, 2026
Python SDK Preview: Sync for Robots and AI at the Edge
by
Chris Draper
Today, Ditto's Edge SDK for Python is now available in preview. You can get started in minutes by building with the Python quick start app. We'll also dive into a code example that shows how Ditto can help robot fleets continue working through poor network conditions and we'll outline Ditto's path to AI at the edge.
Breaking Data Silos at the Edge
September 14, 2026
Breaking Data Silos at the Edge
by
Eric Hanft