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.

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
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 misbehaves, far from the lab
- One DQL statement requests a support bundle
- List the bundles and documents that aren't syncing
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.
- Four devices in range on Wi-Fi Aware
- Before: The mesh splits into pairs
- After SDK 5.2: The mesh stays whole
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.
- Two peers are syncing
- The link drops
- 5.2 resumes the session instead of starting over
- A stalled cloud connection is caught and closed
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:
| Setting | Default |
|---|---|
| Idle time before the first probe | 30 seconds |
| Interval between probes | 10 seconds |
| Unanswered probes before closing | 3 |
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.
- A write lands in orders
- Before: Every observer re-ran its query
- After SDK 5.2: Only the orders observer runs
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.
- Documents live on the device
- The device is lost and the files are readable
- 5.2: Encrypted with a key your app controls
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.



