# Chat Source: https://docs.ditto.live/best-practices/example-projects/Chat-App # Inventory Source: https://docs.ditto.live/best-practices/example-projects/Inventory # Point-of-Sale Source: https://docs.ditto.live/best-practices/example-projects/Point-of-Sale # Task List Source: https://docs.ditto.live/best-practices/example-projects/quickstarts # Optimizing Bundle Sizes for Android Source: https://docs.ditto.live/best-practices/optimizing-bundle-sizes-for-android ### Ditto SDK Size The Ditto SDK for Android is a fairly large package. The bulk of the size is made up of native binaries compiled from native Rust code which - unlike Kotlin and Java - need to be compiled for each CPU type (ABI) that the SDK will be used on. We currently support [all 4 ABIs](https://developer.android.com/ndk/guides/abis#sa) supported by the Android NDK. This means that there are 4 native binaries included inside the Android archive `.aar` file we publish to [Maven Central.](https://central.sonatype.com/artifact/live.ditto/ditto/versions) Below are various options to reduce the size of your application package. These change aspects of the Ditto SDK as it is included inside your app’s final `.apk` file. ## Publishing to Google Play Store If you publish your app to the Google Play Store, the easiest way to [reduce your app size](https://developer.android.com/topic/performance/reduce-apk-size) is to package your app as an [Android App Bundle](https://developer.android.com/guide/app-bundle). This format allows Google Play to generate optimized APKs for each device configuration so that users download packages streamlined for their specific device. ## Publishing to Private Distribution Channels If your app is distributed privately to enterprise users via an MDM system, check with your MDM vendor to see whether they integrate with [Managed Google Play](https://www.android.com/enterprise/management/). If so, they may support Android App Bundles (`.aab` files) and automatic package optimization. However, if your MDM system does not support this, there are several options for manually optimizing the size of your app package. ### Compress Native Binaries The native binaries included with the Android Ditto SDK are included in an app’s package in uncompressed form by default. However, setting the `useLegacyPackaging` value to `true` in your app’s Gradle configuration will change this to store the binaries in compressed form. Compressed binaries will take up less space and help to reduce the app’s final `.apk` file size. In your app’s `build.gradle(.kts)` file, add the following `jniLibs` block inside the `packaging` block. ```js theme={null} android { packagingOptions { jniLibs { useLegacyPackaging = true } } } ``` ```js theme={null} android { packaging { jniLibs { useLegacyPackaging = true } } } ``` Compressed binaries has shown to reduce a simple demo app’s size by 50%. This `useLegacyPackaging` build option can also be controlled using the (deprecated)[`android:extractNativeLibs` attribute](https://developer.android.com/guide/topics/manifest/application-element#extractNativeLibs) on the `` element in the Android manifest. This option used to be available using the `android.bundle.enableUncompressedNativeLibs` Gradle property. #### Caveats While this `useLegacyPackaging` option can help to reduce your final `.apk` file size, it is important to be aware of the side effects of changing this setting and to test your application to understand how it will behave. * Increased app launch time as compressed binaries need to be decompressed. * Increased app install size as uncompressed binaries are copied into app’s data directory. * App updates through the Google Play Store will be larger. #### More details * [Reduce your app size](https://developer.android.com/topic/performance/reduce-apk-size#extract-false) * [Use the DSL to package compressed native libraries](https://developer.android.com/build/releases/past-releases/agp-4-2-0-release-notes#compress-native-libs-dsl) * [Native libraries package uncompressed by default](https://developer.android.com/build/releases/past-releases/agp-3-6-0-release-notes#extractNativeLibs) ### Exclude Unused CPU Architectures If your app does not need to support all of the different types of CPUs (ABIs) that the Ditto SDK supports, you can configure your build to exclude the unwanted files. There are two main approaches to this. The first is to just exclude the one or more ABIs that you don’t want. The second approach is more extreme and involves building multiple APKs, each with only a single ABI, but it is more complicated to deploy. Including only a single ABI has shown to reduce a simple demo app’s size by 70%. In order to use either of these approaches you need to understand the CPU architecture (ABI) of all the devices you will be deploying your app to. Excluding the ABI for a device and then attempting to run the app on a device that uses the missing ABI will cause the Ditto SDK to crash. #### Single APK with reduced ABIs This approach is very simple and just excludes one or more Ditto native binaries from your app package. In your app’s `build.gradle(.kts)` file, add an `ndk` block inside the `defaultConfig` block like so: ```java theme={null} android { ... defaultConfig { ndk { abiFilters.clear() abiFilters("arm64-v8a", "armeabi-v7a", "x86_64", "x86") } } } ``` ```kotlin theme={null} android { ... defaultConfig { ndk { abiFilters.clear() abiFilters.addAll(listOf("arm64-v8a", "armeabi-v7a", "x86_64", "x86")) } } } ``` The example snippet above adds all 4 ABIs that are contained in the Ditto Android SDK. Reduce this list to just the ABIs of the devices that your app is deployed to. Android devices with Intel CPUs (`x86*` ABIs) are rare nowadays, but Chromebooks often have these types of CPUs. For more details about this `ndk.abiFilters` configuration, see [Generate Code for a specific ABI](https://developer.android.com/ndk/guides/abis#gc). #### Caveats * Your app will crash with message "Native library failed to load" if run on a device that uses an ABI excluded using this method. #### Separate APKs for each Supported ABI This is the most involved process but it yields the absolute smallest APK size possible. There are several caveats with this approach but it may be necessary if your deployment system has very limited requirements. Add the following `splits` block to your app’s `build.gradle(.kts)` file inside the `android` block. ```java theme={null} android { ... splits { abi { enable = true reset() include("arm64-v8a", "armeabi-v7a", "x86_64", "x86") universalApk = false } } } ``` ```kotlin theme={null} android { ... splits { abi { isEnable = true reset() include("arm64-v8a", "armeabi-v7a", "x86_64", "x86") isUniversalApk = false } } } ``` The above configuration will generate a separate APK for each ABI listed above in the `include` configuration. You may remove any ABIs that your environment doesn’t need. For more details see about the `splits.abi` Gradle configuration, see [Configure multiple APKs for ABIs](https://developer.android.com/build/configure-apk-splits#configure-abi-split). Note that the Google Play Store requires each APK you publish to have a unique `versionCode`. Check with your MDM system’s requirements as to what their app versioning policies are. A strategy for generating a unique `versionCode` for each APK is detailed in the [Build multiple APKs](https://developer.android.com/build/configure-apk-splits#configure-APK-versions) guide. For more information about this topic, see [Assigning version codes](https://developer.android.com/google/play/publishing/multiple-apks#VersionCodes). #### Caveats * Single-ABI APKs need to be carefully deployed to the correct devices via MDM. * APK versioning can be more complicated, depending on your MDM system’s requirements. # What is Ditto? Source: https://docs.ditto.live/home/about-ditto Ditto is the only mobile database with built-in edge device connectivity and resiliency, enabling apps to synchronize without relying on a central server or constant cloud connectivity. Through the use of CRDTs and P2P mesh replication, Ditto allows you to build collaborative, resilient applications where data is always available and up-to-date for every user. This allows you to keep mission-critical systems online when it matters most. ## Overview The Ditto Edge Sync Platform consists of two key components. An embedded database that runs on mobile or edge devices to power applications that use the Ditto SDK. As well as providing a local database, the Ditto SDK (sometimes referred to as a small peer) also has built-in mesh connectivity to other Ditto-enabled devices (peers), enabling apps to synchronize data without relying on a central server or constant cloud connectivity. A cluster of servers that can run on-premises or in the cloud, that augments the SDK's local-first capabilities with cloud-based synchronization, identity management, monitoring and data integration features. While synchronization does not rely on Ditto Server, adding Ditto Server removes all of the complexity of:
• Integrating a P2P system like Ditto with your wider data ecosystem (e.g. Analytics, MongoDB, Object Storage, etc.)
• Providing a synchronization fallback for physically dispersed devices
• Monitoring and managing your fleet of devices running the Ditto SDK
Ditto melds a local-first database with intelligent networking and synchronization. Its offline-first operation, real-time peer-to-peer sync, CRDT-driven conflict resolution, and JSON document storage all work together to provide a robust platform for building modern, distributed applications. By handling the hard problems of data sync and consistency for you, Ditto lets you focus on your app's features - confident that your data will stay **available**, **consistent**, and **in sync** across every device and environment. ## Built for Offline-First Operation Ditto uses an **offline-first architecture**, which means your app remains fully functional even when offline. Each device maintains a local database, so it can always read and write data **without a network connection**. Any changes made offline are stored on the device and automatically synced out, and any changes made elsewhere are automatically merged into your local database, when the device comes back online. Your users can keep working uninterrupted; Ditto will seamlessly handle all connectivity, data replication, and conflict resolution. This ensures a smooth experience in unreliable network environments, as the application never has to “pause” or degrade functionality due to lack of internet access. Under the hood, Ditto employs **Conflict-Free Replicated Data Types (CRDTs)** to handle data consistency and merging. This means that if multiple devices or users edit the same piece of data concurrently - even while offline - Ditto can **merge those changes automatically** once the devices sync up, without dropping or overwriting data. Every device maintains its own copy of the data and thanks to CRDTs, all copies will *eventually converge* to the same consistent state after synchronization, following a causal consistency model. Developers don't need to write complex conflict resolution logic or worry about “last write wins” scenarios; Ditto's CRDT-based engine resolves conflicts deterministically based on its data type rules. The end result is true multi-writer collaboration: all peers can edit data independently, and Ditto will transparently reconcile any conflicts, ensuring no changes are lost and all devices see a unified dataset. ## Peer-to-Peer Mesh Networking A key differentiator of Ditto is its **peer-to-peer (P2P) mesh networking** capability. Ditto-enabled devices can discover and communicate with each other directly, forming an ad-hoc mesh network rather than routing everything through a cloud server. The platform automatically handles the complexity of discovery and connectivity using whatever channels are available - for example, Bluetooth, peer-to-peer Wi-Fi, or local LAN - to find nearby devices and sync data with them. This means your apps can share data in real time even in local or offline-only scenarios (for instance, on an airplane, in a remote field site, or during an internet outage). You do not need to write a single line of custom networking code, Ditto will automatically handle the complexity of discovery and connectivity using whatever channels are available - for example, Bluetooth, peer-to-peer Wi-Fi, or local LAN - to find nearby devices and sync data with them. ## Real-Time Data Synchronization Ditto is built for **real-time sync**, ensuring that updates propagate to other devices almost instantly. When data changes on one device, Ditto's engine quickly distributes that change to all other connected peers. There's no need for you to implement manual refresh logic or polling; Ditto uses a reactive subscription model that pushes updates as soon as they happen, so apps get data changes **in real time**. This low-latency synchronization is ideal for collaborative applications. Because Ditto syncs at the document level, it can synchronize only the relevant documents or even specific fields (deltas) to each peer, conserving bandwidth and storage. ## JSON Database Data in Ditto is stored as [JSON-like documents](/key-concepts/document-model), making it a flexible, document-oriented database. This schemaless JSON data model means you can store structured objects without defining a rigid schema up front - your documents can have arbitrary fields, nested sub-objects, and evolve over time as your application needs change. Each document is saved in the local embedded database on the device, and Ditto provides DQL, an expressive SQL-like query language, to work with this data. You can query documents using familiar query syntax with advanced filters, sorting, and transactions, allowing the app to efficiently find and update the data it needs. The JSON document approach not only gives developers flexibility in modeling data, but it also pairs naturally with Ditto's sync engine - any change to a JSON document (like adding a field or updating a value) will be captured and propagated to other devices in the network. This combination of a developer-friendly data format with powerful local queries and seamless syncing makes it straightforward to build data-rich features that work reliably online or offline. # FAQs Source: https://docs.ditto.live/home/faq This article provides expert answers to frequently asked questions (FAQs) for the following Ditto topics: ## General SDK There are 3 ways for Ditto enabled apps to sync without connectivity: **WiFi Access Point (LAN)** WiFi Access Point, also known as LAN, is when devices discover and sync with each other over the same local network. Typically, this means you have a wireless access point where your devices are all connected to. Even if the internet or modem fails, devices will still be able to synchronize. This is completely cross-platform. **WiFi Aware and Apple Wireless Direct Link (AWDL)** iOS and Android devices are able to create peer to peer WiFi connections with each other. However these are not cross platform. Meaning that, iOS devices are only able to connect to other iOS devices via Apple Wireless Direct Link. Android devices are able to make P2P WiFi Aware connections with each other. **Bluetooth Low Energy** iOS and Android devices are able to connect with each other over a standard Bluetooth Low Energy (BLE) connection. Ditto supports both Bluetooth 4.x and 5.x protocols seamlessly. Bluetooth 5 devices are able to communicate with each other over a higher bandwidth (an average of 1.8 Megabits per second). If a Bluetooth 5.x device needs to connect with a Bluetooth 4.x device, the devices will connect over a Bluetooth 4.x protocol. Ditto offers a large range of devices and OS support for each of our SDKs. For specific support see the compatibility map for your given language [Directory of Compatibility Maps](/sdk/latest/compatibility/compatibility) At the heart of Ditto is a realtime database that takes in JSON-like data structures. That means that even if a device with Ditto is completely disconnected from other devices, it will still have the data stored locally. That means even in a completely offline environment, users will still be able to edit, read, and observe data. When devices reconnect, they will exchange relevant information that was edited when they were offline. You can think of this as a similar behavior to Google Docs or Google Sheets. ## Database & Sync Yes. All participating devices must be subscribing to the same data query. No. Ditto does not support more than one app using the database at the same time. Yes. The Ditto SDK provides `sync.start()` and `sync.stop()` methods that will enable and disable network sync. iOS offers best-effort background sync provided Bluetooth LE is enabled and the Bluetooth central and peripheral background modes are enabled. Android can sync in the background over WiFi. See above about background mode. This will depend on the type of data, query complexity and the performance required. As a rule of thumb, a device running the Ditto SDK such as a mobile device is designed to handle up to 2GB of key-value data and tens of thousands of documents in a collection. Data synced using the file attachments API is stored outside the main database and does not contribute towards the 2GB. Even very large attachments are supported and the limits will depend mostly on the storage and network bandwidth available on your device. The data will be merged when the data from one device reaches the other device. Yes. You can perform multiple updates, across multiple documents in multiple collections, inside a single write transaction. [Read more](/sdk/latest/crud/transactions) ## Connection Ditto provides a Presence Viewer UI on iOS and Android that can be launched within your app to show all active connections to other devices. This information can also be accessed programmatically using the `ditto.presence` SDK function. If a device is disconnected, this will be reflected through the `ditto.presence.observe()` callback. You can specify which transport types to enable, e.g. Bluetooth only, WiFi only, or everything. Ditto will use its own algorithms to decide which devices to connect to and which modes to use. Ditto always prioritizes the fastest connection that is available, and will optimistically upgrade to a faster connection whenever possible. If, separate to Ditto, you know the complete list of devices in your team then you can use the `ditto.presence` functionality provided by the SDK to keep track of which devices are online. Therefore you'll be able to determine which devices are offline. If you don't maintain a separate list of devices in your team then the best you can currently do is to keep track of all devices that Ditto sees, again by making use of the `ditto.presence` API. You can then use this list of all known devices to keep track of which of those are online/offline at any given moment. Use the Instruments tool that ships with Xcode to monitor both bytes and packets sent and received from a process on a macOS, as well as on a simulated iOS device. For low-level, yet powerful monitoring, use Wireshark or similar tool to analyze all WiFi and Bluetooth traffic in a given area, and then filter the results by Mac address or similar identifiers. Since all Ditto traffic is encrypted, you can only monitor packet bytes that are sent and received; individual protocol messages cannot be recovered. Yes. You can use both direct communication between devices running the Ditto SDK (device-to-device) and communication by way of a server ([Ditto Server](/cloud/overview)) that connects and transmits data between devices running the Ditto SDK (device-to-server-to-device). This dual approach provides flexibility — your app remains efficient in any network environment and you control when and what routes through a central server. However, web browsers do not support peer-to-peer transports. That means a web app will only be able to connect to Ditto Server over WebSockets. It should not affect the performance of the Android and Angular apps. If you see any performance degradation, please let us know as soon as possible. No. The browser-based Web SDK connects to Ditto Server exclusively over WebSockets. It does not support peer-to-peer transports such as Bluetooth LE, LAN, or P2P Wi-Fi. This means a web app cannot participate in local device-to-device mesh sync when the network is down. This is because the web browser blocks web applications' access to peer-to-peer transports such as BLE. If your use case requires offline or LAN-only sync without Ditto Server, use a native SDK (iOS, Android, Linux, Windows, or macOS) instead. No. Android Wi-Fi Aware is only capable of syncing with other Android devices. Apple devices running iOS and macOS are capable of syncing over Apple Wireless Direct Link. These two transports are not compatible with each other. *However, other transports like Bluetooth Low Energy and Access Points will be able to sync with each other just fine.* ## Security Use Online Playground for development and Online With Authentication for production. (See [Cloud Authentication](/sdk/latest/auth-and-authorization/cloud-authentication)) Ditto does not encrypt its local database at rest. Both iOS and Android provide OS-level disk encryption (iOS Data Protection and Android file-based encryption, respectively) that can protect data stored on the device. However, this protection is only active when a screen lock (passcode, PIN, or biometric) is configured and the device is in a locked state. On unmanaged devices — such as those used by end users who download your app from a public App Store — you cannot guarantee that device-level encryption is enabled, since your app has no control over the user's device settings. For applications handling regulated or sensitive data (for example, PHI under HIPAA, payment data under PCI, or similar requirements), relying solely on OS-level encryption may not satisfy compliance controls. Your app cannot programmatically verify or enforce whether the end user's device has encryption enabled. If you are building for a regulated environment, consider encrypting sensitive field values at the application level before writing them to Ditto. You can also contact the Ditto team for guidance on architecture patterns that address compliance requirements. For more on Ditto's authentication and security model, see [Cloud Authentication](/sdk/latest/auth-and-authorization/cloud-authentication). The JavaScript (Web) SDK stores all data in memory (RAM) only for the duration of the browser session. No data is written to `localStorage`, `sessionStorage`, or `IndexedDB`. When the browser tab or window is closed, all local Ditto data is released. The Web SDK does not leave persistent data artifacts in the browser, which can be a relevant consideration for applications handling sensitive data. Ditto will only connect to devices that advertise the same "application name". Further controls are under development. Please speak to us for advice if you have special requirements for limiting connections. Communication is encrypted using TLS 1.3 and peer identities are verified using certificates. This is the same state-of-the-art technology used in web browsers. It applies to every communication mode from Bluetooth to WiFi. The certificates that you provide to devices contain a set of permissions. You can use these permissions to specify whether or not a given device should be able to access given data. If you only want a device to sync a subset of the data that it has access to then you do this by only using queries for that device's live queries and subscriptions that relate to the data that you wish to be synced. Ditto provides multiple production security modes that robustly protect against eavesdropping. You can either use a shared secret key, or device-specific keys with a central authority. Ditto also has a development security mode which does not require you to provide a key. This is not secure, and provided for ease of development. Ditto certificates are standard X.509 certificates. Each device has a keypair and the certificate grants that device a unique ID and rules for which collections and documents it is permitted to read and write. Organizations with strict on-premises requirements may operate their own certificate authority (CA). Certificates can also be generated and distributed automatically from Ditto Server. For more information about certificate deployments please speak to us. ## Bluetooth Bluetooth Classic is an older mode used for accessories like headphones. It requires a manual pairing procedure between devices. Ditto does not use Bluetooth Classic. Bluetooth Low Energy (BLE) is a more recent mode of Bluetooth that consumes less power and removes the need for user interaction when connecting to another device. Ditto's Bluetooth synchronization employs this mode exclusively. No. Ditto uses exclusively Bluetooth Low Energy, which does not require pairing. Ditto will take advantage of features in newer versions of BLE when they are supported by both devices. These features are optional, and Ditto sync will work with even the earliest BLE hardware adapters. Approximately 100 metres (tested in the open with modern Apple hardware). Newer hardware usually performs better. Yes, Bluetooth Low Energy sync can operate at the same time as other Bluetooth devices such as headphones. ## Battery The SDK is designed to be as power-efficient as possible. We strive to keep CPU and network usage to a minimum. Ditto should not be affected in most circumstances, although background sync on iOS may become less reliable. ## Performance Ditto can be used in Airplane Mode. If Bluetooth or WiFi is manually toggled on after selecting Airplane Mode, then Ditto will be able to sync using those modes. * WiFi: the full speed of your connection, typically 1 gigabyte of data in times as low as 8 seconds. * WiFi Aware: similar to WiFi speeds * Bluetooth LE: typically 20 kB/second (however, if you’re using a device that is below Android 10, then Ditto will use BLE GATT which is only 4 kB/second.) * Ditto Server: 40k transactions per second (25k write txns + 15k reads) There isn't a size limit to a Ditto document or store. Like other databases, Ditto will use as much data as you insert into the device. Controlling the size of Ditto in your app is completely up to your discretion. No there are no limits to the number of collections. While there is no limit, try to keep the names shorter than 30 characters. The collection names are stored with each document. This is merely a suggestion. Your results may vary depending on the size of your documents and the number of them you are querying. Contact us for help with implementing performance testing for your use case. ## Versioning & Upgrading Please see versioning documentation. Please see versioning documentation. We aim to have a version of the iOS SDKs that is compatible with latest iOS version before the iOS version has been made available to the public. We will likely publish alpha or beta releases of the SDKs during the iOS beta period, if necessary. # Glossary Source: https://docs.ditto.live/home/glossary Here you'll find Ditto-specific terms and their definitions, as well as links to related information. ## A ### Actor Used by [conflict-free replicated data types](#conflict-free-replicated-data-type-crdt) (CRDTs) to identify the source or author of a data mutation. Actors enable Ditto to track which peer made each change, allowing proper conflict resolution during data merges. An actor's identity changes whenever its peer begins a new [epoch](#epoch). ### Attachment A component for storing large binary files separately from documents. Attachments are referenced by documents via attachment tokens but must be explicitly fetched—they do not automatically sync with document subscriptions. Once created, attachments are immutable; to update, create a new attachment and replace the token in the document. See also: [Blob Store](#blob-store) ### Authentication Webhook An HTTP service hosted by the developer which receives credentials and responds with metadata about the user and which permissions they should have. The [Identity Service](#identity-service) uses this information to dynamically produce the required certificates. Configured through the [Portal](#portal). ### AWDL (Apple Wireless Direct Link) A proprietary Apple-developed technology that establishes a point-to-point Wi-Fi connection between two Apple devices. When available in their environment, Small Peers utilize AWDL to create a mesh network connection and replicate data. AWDL provides faster transfer speeds than Bluetooth LE. ## B ### Backend The underlying key-value store which Ditto uses for database-like persistence. ### Big Peer Previous name for [Ditto Server](#ditto-server). Indicates that Ditto Server acts as a peer in the meshed network of devices. ### Blob Store An internal component which offers general blob storage. Used by any internal Ditto components which need to persist "files". The blob store does not necessarily require a true filesystem and might operate purely in memory. ### Bluetooth LE (BLE) A wireless technology for short-range communication that serves as one of Ditto's primary [transports](#transports). Bluetooth LE operates in two modes: [GATT](#gatt-generic-attribute-profile) (slower, wider compatibility) and [L2CAP](#l2cap-logical-link-control-and-adaptation-protocol) (faster, newer devices). It enables peer-to-peer synchronization without internet connectivity. ### BYOC Bring Your Own Cloud. A model for deploying the Ditto Platform managed by Ditto in your own cloud account where you (the customer) share responsibility and control over the account—and therefore the cost, security, and compliance needs—with Ditto. ## C ### Certificate Authority (CA) The cryptographic root of trust for all identities and certificates within a Ditto [Database](#database). Originally this was a standard X.509 CA for peer TLS certificates, but its role has expanded to include JWT and In-Band Certificate signatures. It is by knowing the public keys of the CA that one offline peer can verify the authenticity of another offline peer. ### Change Data Capture (CDC) A system for tracking data modifications for integration purposes, enabling external systems to receive notifications when data changes in Ditto. Change events are delivered through [Data Bridges](#data-bridge) to Kafka topics you configure. See also: [Data Bridge](#data-bridge) ### Channel A bidirectional message-oriented data flow running over the top of a Virtual Connection. These can offer reliable or lossy delivery characteristics and be opened either mutually or as a client/server type relationship. Channels are protocol-agnostic, like TCP/UDP, and are consumed by [Services](#service). ### Chooser Also known as the "Mesh Chooser", a stateful algorithm which decides at any moment which outgoing connections should be made. This considers the peers currently connected, the peers whose advertisements have been detected by transports, and past failures. ### Collection A grouping of [documents](#document) under a name. Loosely equivalent to a table in SQL terms. A database may have many collections. Each document within a collection must have a unique `_id` field (primary key). ### Conflict-Free Replicated Data Type (CRDT) An advanced class of data type designed to manage and replicate data changes in a way that allows multiple distributed peers to make updates concurrently without the need to reach consensus. CRDTs automatically merge to form a single meaningful value. Ditto implements several CRDT types: * **[REGISTER](#register)**: Stores scalar values (strings, numbers, booleans, arrays) using last-write-wins strategy * **[MAP](#map)**: Stores object properties using add-wins strategy for automatic concurrent merge For more information, see Ditto's blog post: [An Inside Look at Ditto's Delta State CRDTs](https://www.ditto.com/blog/dittos-delta-state-crdts). ## D ### Data Bridge A mechanism that directs data egress from a Ditto Cloud database to an external destination. A Kafka Data Bridge publishes change events to user-consumable Kafka topics for downstream systems to consume. Data Bridges are how [Change Data Capture](#change-data-capture-cdc) output leaves Ditto Cloud, and a single database can direct data to multiple destinations. See also: [Change Data Capture (CDC)](#change-data-capture-cdc) ### Database A named data store identified by a [Database ID](#database-id). All peers configured with the same database ID form a mesh and synchronize the database's [collections](#collection). In v4 this was called an "app"; v5 renamed it to avoid confusion with mobile applications. Databases hosted on Ditto's cloud are created and managed in the [Portal](#portal). ### Database ID The unique identifier for a Ditto [database](#database), formerly called "App ID" in v4. All peers with the same database ID will automatically form a mesh network and synchronize data. Passed to the [DittoConfig](#dittoconfig) during initialization. ### DELETE A [DQL](#dql-ditto-query-language) statement that permanently removes documents and creates [tombstones](#tombstone), which propagate the deletion to other peers. Contrast with [eviction](#eviction), which removes data locally without syncing the removal. For documents that may be updated concurrently, prefer [logical deletion](#logical-deletion-soft-delete-pattern) to avoid [husked documents](#husked-document) and [zombie data](#zombie-data). ### Delta Sync A bandwidth optimization technique where only field-level changes (not entire documents) are transmitted between peers. This minimizes network usage and is especially important for battery-constrained devices and low-bandwidth connections like Bluetooth LE. ### Device A physical hardware unit (smartphone, tablet, IoT device, etc.) that can run Ditto-enabled applications. A single device can host multiple [peers](#peer) when running multiple Ditto instances. Distinct from [Small Peer](#small-peer), which refers to a Ditto SDK instance rather than the hardware it runs on. ### Ditto Server A cluster of servers that can run on-premises or in the cloud, augmenting the SDK's local-first capabilities with cloud-based synchronization, identity management, monitoring, and data integration features. Previously called [Big Peer](#big-peer). ### DittoConfig The configuration object used in v5 to initialize a Ditto instance, replacing the v4 identity types. A DittoConfig takes the [database ID](#database-id) and a connect mode: `.server(url:)` to sync with a [Ditto Server](#ditto-server) (copy the URL from the [Portal](#portal)), or `.smallPeersOnly(privateKey:)` for peer-to-peer-only and air-gapped deployments. Authentication credentials are no longer part of the configuration; they are supplied through the auth namespace at login. ### Document A schema-flexible unit of data contained in a [collection](#collection); analogous to a row in a table. Each document must have a unique `_id` field (primary key) which is immutable after creation, and each field is backed by a specific [CRDT](#conflict-free-replicated-data-type-crdt) type. ### DQL (Ditto Query Language) A SQL-like query language for interacting with Ditto documents. DQL uses string-based queries executed via `ditto.store.execute()`. It features SQL-like syntax, schema-less document orientation, and does not support JOIN operations in current versions. ### DQL Strict Mode A configuration option (`DQL_STRICT_MODE`) that enforces structure and CRDT type safety in collections. When enabled, all fields are treated as [REGISTER](#register) by default; when disabled, objects are automatically treated as [MAPs](#map) with field-level merging. Strict mode defaults to `true` in SDK 4.x and `false` in SDK 5.0 and later. All peers must use the same setting for consistent behavior. ## E ### Epoch A concept which identifies a "version" of a peer's CRDT knowledge. Used by replication and CRDT to identify whenever a peer has changed in some fundamental way that obsoletes prior knowledge of them. An Epoch changes each time a peer performs data [Eviction](#eviction). ### Eviction The process a peer takes to deliberately "forget" data locally. Unlike [DELETE](#delete), eviction is a local-only operation that does not propagate to other peers, does not create [tombstones](#tombstone), and immediately frees disk space. Evicted data may resync if an active subscription matches it. Important for use cases like cabin crew apps where data from the last flight is not needed on the next flight. ## G ### GATT (Generic ATTribute Profile) An older, slower mode of Bluetooth LE data transfer with typical speed of 3 to 6 kB/s. Works back to very old Android and iOS phones. Where possible, the Bluetooth transport upgrades a connection to [L2CAP](#l2cap-logical-link-control-and-adaptation-protocol). ## H ### HTTP API The request-response API that external systems use to read and write documents in a [Ditto Server](#ditto-server) database without running an SDK peer. It is designed following remote procedure call (RPC) principles rather than REST resource conventions, so it is the HTTP API rather than a REST API. Typical uses are pushing cloud-side data into the mesh and reading data back out; endpoints cover [DQL](#dql-ditto-query-language) execution and [attachment](#attachment) upload and download. ### Husked Document A partially deleted document that results from concurrent [DELETE](#delete) and UPDATE operations on the same document. When the operations merge, Ditto's CRDT combines them field-by-field: fields touched by the update keep their new values while the rest become null, leaving a "husk". Prevent this by using [logical deletion](#logical-deletion-soft-delete-pattern) for documents that may be updated concurrently. ### Hybrid Logical Clock (HLC) Used to track when mutations occurred to a [CRDT](#conflict-free-replicated-data-type-crdt), or component thereof. A Ditto HLC combines a physical clock portion (the local timestamp on a peer as Unix milliseconds) together with a logical portion (a number unique to each peer that increases by one with each change they make). ## I ### Identity Who a peer is: how it proves itself to other peers in the same [database](#database) and what [permissions](#permission) it carries. In v5, identity is established at login through the auth namespace using a provider: `development` (formerly [Online Playground](#online-playground); development and testing only) or an Authentication Provider backed by an [Authentication Webhook](#authentication-webhook) and configured in the [Portal](#portal) for production permissions (the successor to v4's `onlineWithAuthentication` identity type). Air-gapped deployments use a shared private key via `.smallPeersOnly(privateKey:)` instead. Some modes rely on the database having a common [CA](#certificate-authority-ca). Not to be confused with the v4 `DittoIdentity` configuration type, which was replaced by [DittoConfig](#dittoconfig) in v5. ### Identity Service The part of [Ditto Server](#ditto-server) which handles login requests, invoking [Authentication Webhooks](#authentication-webhook) if required, and generating the cryptographic material for peers to authenticate each other by acting as the [CA](#certificate-authority-ca). ### Index A data structure (SDK 4.12+) that improves query performance for large datasets by enabling faster lookups on specific fields. Currently supports simple indexes on single fields only, and is most effective for highly selective queries that return a small percentage of documents. ### INITIAL Documents A DQL keyword for INSERT statements that creates documents treated as "default data from the beginning of time" across all peers, such as seed data, form templates, or category lists that every peer should initialize independently. Documents inserted with INITIAL do nothing if the `_id` already exists locally, preventing unnecessary synchronization traffic. ## L ### L2CAP (Logical Link Control and Adaptation Protocol) A faster mode of Bluetooth LE transport at a lower level/complexity than [GATT](#gatt-generic-attribute-profile). Platforms that support it have much faster speeds (\~20 kB/s). ### LAN (Local Area Network) A network transport that enables Ditto peers to communicate over a shared local network, such as Wi-Fi or Ethernet. LAN provides higher throughput than [Bluetooth LE](#bluetooth-le-ble) and is one of the [transports](#transports) used to form the Ditto [mesh network](#mesh-network). ### Link An encrypted connection between two peers who are not directly connected, with traffic routed via intermediate peers. Used for [multi-hop sync](#multi-hop-sync) via [Query Overlap Groups](#query-overlap-groups). ### Live Query The legacy query builder's mechanism for observing query results over time (`observeLocal`), replaced by DQL-based [Local Store Observers](#local-store-observer). For migration guidance, see [Replacing Live Queries](/dql/replacing-live-queries). ### Local Store Observer An object that monitors database changes in the local store matching a given query over time, enabling real-time UI updates as data changes locally or syncs from other peers. Previously referred to as "Observer" or "Live Query." Created via `ditto.store.registerObserver()`, which automatically signals readiness for the next callback once your handler returns. If your handler needs time to process results—such as expensive rendering or batch operations—use the overload with a `signalNext` callback to control when the next update is delivered. ### Logical Deletion (Soft-delete pattern) A soft-delete pattern where documents are marked as deleted (e.g., `isDeleted: true`) but not physically removed from the database. This approach avoids [zombie data](#zombie-data) problems and [husked documents](#husked-document) that can occur with physical [DELETE](#delete) operations. ## M ### MAP A [CRDT](#conflict-free-replicated-data-type-crdt) type that stores object properties using an "add-wins" strategy. When multiple offline peers make concurrent updates to different keys in a MAP, both changes are preserved after sync (field-level merging). Prefer MAP structures over arrays for data that may be updated concurrently by multiple peers. ### Mesh Network A network topology where peers connect directly to each other (peer-to-peer) without requiring a central server. Ditto creates mesh networks using multiple [transports](#transports) including Bluetooth LE, P2P Wi-Fi (AWDL/Wi-Fi Aware), LAN, and WebSockets. ### mTLS (Mutual TLS) Mutual Transport Layer Security, a security protocol where both parties in a connection authenticate each other using certificates. Ditto uses mTLS (TLS 1.3) by default to encrypt data in transit between [peers](#peer), ensuring that only authorized peers can communicate within the [mesh network](#mesh-network). ### Multi-hop Sync The ability for Ditto to relay documents through intermediate devices that are not directly connected. An intermediate device can only relay documents it has in its local store—if a device's [subscription](#subscription) is too narrow, it won't store certain documents and cannot relay them to other devices. ### Multiplexer A synchronous machine inside a Virtual Connection to a single remote peer, performing packet fragmentation and reassembly for all of the Physical Connections arriving from various [transports](#transports). ## O ### Offline-First An architectural approach where applications are designed to function fully without network connectivity. In Ditto, this means the local database remains readable and writable offline, and data automatically merges with other [peers](#peer) when connectivity is restored. This is a core design philosophy of the Ditto platform. ### Online Playground The older term used in v4 for a type of [Identity](#identity) where peers do not need unique credentials to log in and everybody has read and write access to everything. **Development and testing only**—not secure for production use. Replaced by the `development` login provider in v5. ## P ### Peer An instance of the Ditto SDK running within an application. Each peer has a unique [identity](#identity) and participates in the [mesh network](#mesh-network) independently. A single [device](#device) can host multiple peers when running multiple Ditto-enabled databases. Peers synchronize data with other peers based on their [subscriptions](#subscription). See also: [Small Peer](#small-peer), [Ditto Server](#ditto-server) ### Peer Key A P-256 private key generated and persisted on every device that runs Ditto. This is the primary unique identifier for each peer and its ECDSA signatures are used to prove authenticity. It is unrelated to CRDT [actor](#actor) IDs. ### Peer-to-Peer Wi-Fi Any mechanism for establishing direct Wi-Fi connections between devices without needing a router in between. [AWDL](#awdl-apple-wireless-direct-link) is one such technology for Apple devices, and [Wi-Fi Aware](#wi-fi-aware) is another for Android devices. ### Permission A specification of which documents a given peer can read or write. This is presented as a list of specific collection names, and a sublist of query strings for each collection. Documents must match one of those [DQL](#dql-ditto-query-language) queries to be readable or writable. Permissions can only be specified on the immutable `_id` field. Permissions can be locked down when using an Authentication Provider for [identity](#identity) (`onlineWithAuthentication` in v4); other modes have no CA and let everybody access anything. ### Physical Connection A low-level network connection established through a specific [transport](#transports) mechanism (such as [Bluetooth LE](#bluetooth-le-ble), [LAN](#lan-local-area-network), or [WebSocket](#websocket)). Multiple Physical Connections can be combined by the [Multiplexer](#multiplexer) into a single [Virtual Connection](#virtual-connection) for improved reliability and throughput. ### Portal Self-service website ([https://portal.ditto.live/](https://portal.ditto.live/)) used to create and manage [Databases](#database) hosted on Ditto's cloud. ### Presence The awareness of other [peers](#peer) in the surrounding [mesh network](#mesh-network), including information about which peers are available and how they are connected. Presence data is used to determine optimal paths for [multi-hop sync](#multi-hop-sync). See also: [Presence Viewer](#presence-viewer) ### Presence Viewer The part of Ditto responsible for building a picture of all peers in the surrounding mesh, including rich peer info such as SDK version, device names, and which [transports](#transports) are active. This information is used as the basis for routing and can be visualized with the presence viewer. ## Q ### Query Overlap Groups A set of [peers](#peer) whose [subscriptions](#subscription) overlap, enabling them to relay documents to each other through [multi-hop sync](#multi-hop-sync). When peers share overlapping queries, they can act as intermediaries for data synchronization even if the source and destination peers are not directly connected. ### QueryResult The result returned from `ditto.store.execute()` containing a collection of [QueryResultItems](#queryresultitem). Treat QueryResults like database cursors that manage memory carefully. ### QueryResultItem An individual item within a [QueryResult](#queryresult). Uses lazy-loading for memory efficiency—items materialize into memory only when accessed. QueryResultItems should be treated like database cursors; extract needed data immediately and do not retain them between [Local Store Observer](#local-store-observer) callbacks. ## R ### REGISTER A [CRDT](#conflict-free-replicated-data-type-crdt) type that stores scalar values (strings, numbers, booleans) and arrays using a last-write-wins strategy: when multiple peers update the same REGISTER field concurrently, the most recent write (by [HLC](#hybrid-logical-clock-hlc) timestamp) wins. Arrays are REGISTERs, so the entire array is atomically replaced on update—prefer [MAP](#map) structures for data that multiple peers may modify concurrently. ### Replication The process of synchronizing data between [peers](#peer) in the Ditto [mesh network](#mesh-network). Replication is driven by [subscriptions](#subscription) and uses [Delta Sync](#delta-sync) to transmit only changed fields. The Replication [Service](#service) handles document sync over [Channels](#channel). ### Replication Query A query that runs on connected peers that results in changes being sent back to the initial peer when changes are made to the remote peers' local database. See [Subscription](#subscription). ## S ### Service Handles [Channels](#channel) to provide a particular functionality. The most important example is the Replication service, which performs document sync. ### Small Peer An instance of the Ditto SDK embedded in an application. Small Peers most commonly run on edge devices such as smartphones, tablets, and IoT devices, but the SDK is not limited to the edge — it also runs in server, desktop, and embedded environments (for example, the Go SDK supports Linux and macOS for server deployments). Small Peers synchronize directly with each other in a mesh and can also sync with [Ditto Server](#ditto-server) over a WebSocket connection. See [Customizing Transport Configurations](/sdk/latest/sync/customizing-transport-configurations) for how a Small Peer connects to Ditto Server. ### Store The local database component of the Ditto SDK, accessed via `ditto.store`. The Store provides methods for executing [DQL](#dql-ditto-query-language) queries, registering [Local Store Observers](#local-store-observer), and managing [attachments](#attachment). All data operations go through the Store, which maintains the local copy of synchronized data. ### Subscription A query from the [replication](#replication) perspective, whereby one [peer](#peer) requests any data that matches this query from other peers to synchronize. Created via `ditto.sync.registerSubscription()`. Subscriptions tell Ditto what to sync; without active subscriptions, you may only see locally cached data. ### Sync The process of exchanging and merging data between [peers](#peer) in the Ditto [mesh network](#mesh-network). Sync operates automatically when peers are connected via any available [transport](#transports), using [subscriptions](#subscription) to determine which data to exchange and [CRDTs](#conflict-free-replicated-data-type-crdt) to merge concurrent changes. Sync continues to work in [offline-first](#offline-first) scenarios, queuing changes until connectivity is restored. See also: [Replication](#replication), [Delta Sync](#delta-sync), [Multi-hop Sync](#multi-hop-sync) ## T ### Tombstone A deletion marker created when documents are deleted with [DELETE](#delete) DQL statements. Tombstones have a configurable TTL (Time To Live) and eventually expire. If a device reconnects after tombstone TTL expires, its data will be treated as new inserts, causing [zombie data](#zombie-data). ### Transaction A mechanism for grouping multiple [DQL](#dql-ditto-query-language) operations into a single atomic database commit. Transactions provide atomicity (all operations complete or none execute), consistency (all statements see identical data snapshots), and serializable isolation. Only one read-write transaction can execute at a time; long-running transactions block other read-write transactions. ### Transports The part of Ditto which involves the physical transport mechanisms such as Bluetooth LE ([GATT](#gatt-generic-attribute-profile)/[L2CAP](#l2cap-logical-link-control-and-adaptation-protocol)), WebSockets, [AWDL](#awdl-apple-wireless-direct-link), Wi-Fi Aware, and LAN. Transports are concerned with finding other Ditto peers and establishing secured connections. These lowest-level transports are then weaved together at a higher level to form a Ditto [mesh](#mesh-network). ## V ### Version Vector A tracking mechanism for document state across peers. Each change increments the document version, enabling peers to determine if incoming changes are new or already seen. Used by [Delta Sync](#delta-sync) to transmit only changed fields. ### Virtual Connection A logical connection between two [peers](#peer) that may be composed of multiple [Physical Connections](#physical-connection) across different [transports](#transports). The [Multiplexer](#multiplexer) combines Physical Connections into a Virtual Connection, providing improved reliability and throughput by utilizing all available network paths simultaneously. ## W ### WebSocket A network transport protocol that enables bidirectional communication between [peers](#peer) over the internet. In Ditto, WebSocket connections are primarily used to communicate with [Ditto Server](#ditto-server) for cloud-based [synchronization](#sync) when local [transports](#transports) (Bluetooth, LAN) are not available. ### Wi-Fi Aware A peer-to-peer Wi-Fi technology for Android devices that enables direct device-to-device connections without requiring a router or access point. Wi-Fi Aware serves a similar purpose to [AWDL](#awdl-apple-wireless-direct-link) on Apple devices and is one of the [transports](#transports) used to form the Ditto [mesh network](#mesh-network). ## Z ### Zombie Data Deleted data that reappears from previously disconnected devices after [tombstone](#tombstone) TTL has expired. When a device with old data reconnects after the tombstone has expired, its data is treated as new inserts rather than being suppressed by the deletion. Prevent this by using [logical deletion](#logical-deletion-soft-delete-pattern) or by ensuring the tombstone TTL exceeds the maximum expected offline duration. # Quickstart Source: https://docs.ditto.live/home/introduction Get started with Ditto's Edge Sync Platform, a mobile database with built-in edge device connectivity and resiliency SDK and cloud platform for real-time sync. Get started building your mobile application with the Ditto SDK. Manage and connect your devices and data. Follow our guide to migrate to Ditto from Atlas Device Sync. ## SDK Quickstart Guides Start using Ditto in no time with our step-by-step quickstart guides. # Connect AI Assistants Source: https://docs.ditto.live/home/mcp-integration Use Ditto's Model Context Protocol (MCP) server to access API documentation directly in Claude and other AI assistants Ditto provides a Model Context Protocol (MCP) server that allows Claude Desktop, Claude Code, and other AI assistants to search and reference API documentation directly during development. This integration helps you discover best practices, avoid common pitfalls, and get contextual help while coding. ## What is MCP? [Model Context Protocol (MCP)](https://modelcontextprotocol.io) is an open standard that enables AI assistants to access external data sources and tools. When you connect an MCP server to your AI assistant, it can search and reference documentation in real-time to provide more accurate and contextual responses. ## Accessing Ditto's MCP server Ditto's API documentation is accessible via MCP at: ``` https://docs.ditto.live/mcp ``` This endpoint provides the AI assistant with access to: * Complete API reference documentation * Code examples and usage patterns * Best practices and common anti-patterns * Configuration guides and troubleshooting tips ## Setting up with Claude Desktop To use Ditto's MCP server with [Claude Desktop](https://claude.ai/download): 1. Open your Claude Desktop configuration file: * **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json` * **Windows**: `%APPDATA%\Claude\claude_desktop_config.json` 2. Add the Ditto MCP server to your configuration: ```json theme={null} { "mcpServers": { "ditto-docs": { "command": "npx", "args": [ "-y", "mcp-remote", "https://docs.ditto.live/mcp" ] } } } ``` 3. Restart Claude Desktop for the changes to take effect. 4. Verify the connection by asking Claude about Ditto-specific topics. You should see a small icon indicating that Claude is accessing the Ditto documentation. Learn more about [configuring MCP servers in Claude Desktop](https://docs.anthropic.com/en/docs/build-with-claude/mcp). ## Setting up with Claude Code To use Ditto's MCP server with [Claude Code](https://claude.ai/download): 1. Add the Ditto MCP server using the command line: ```bash theme={null} claude mcp add --transport http Ditto https://docs.ditto.live/mcp ``` 2. Verify the server was added successfully: ```bash theme={null} claude mcp list ``` 3. Restart Claude Code for the changes to take effect. 4. Verify the connection by asking Claude about Ditto-specific topics while coding. Claude Code will automatically reference the Ditto documentation when relevant. Learn more about [configuring MCP servers in Claude Code](https://docs.anthropic.com/en/docs/build-with-claude/mcp). ## Using with ChatGPT To use Ditto's MCP server with [ChatGPT](https://chatgpt.com), you'll need to use a compatible MCP client that works with OpenAI's API. Several community tools are available: 1. Install an MCP client that supports OpenAI integration 2. Configure the client to connect to `https://docs.ditto.live/mcp` 3. Use the client to interact with ChatGPT while having access to Ditto documentation MCP support for ChatGPT is still evolving. Check the [Model Context Protocol documentation](https://modelcontextprotocol.io) and [OpenAI's documentation](https://platform.openai.com/docs) for the latest integration options. ## Example usage Once configured, you can ask your AI assistant questions like: * "How do I set up authentication with Ditto?" * "What's the best way to structure my Ditto queries?" * "Show me how to implement offline-first sync with Ditto" * "What are common mistakes when using Ditto's mesh networking?" The AI assistant will search the Ditto documentation and provide answers with direct references to the relevant documentation pages. ## Benefits Using Ditto's MCP integration provides several advantages: * **Faster development**: Get instant answers without leaving your development environment * **Contextual help**: The AI assistant can reference your specific use case against Ditto's documentation * **Best practices**: Discover recommended patterns and avoid common pitfalls * **Up-to-date information**: Always access the latest documentation without manual searching ## Troubleshooting If you're having issues connecting to the MCP server: 1. Verify your configuration file syntax is correct (valid JSON) 2. Ensure you have Node.js installed (required for the `npx` command) 3. Check that you have an active internet connection 4. Restart your AI assistant application after making configuration changes For additional help, refer to the [Model Context Protocol documentation](https://modelcontextprotocol.io) or contact Ditto support. # Accessing Data Source: https://docs.ditto.live/key-concepts/accessing-data Learn how to access data in Ditto, including creating, reading, updating, and removing data. Ditto is a local-first, embedded database designed for offline-first applications. It runs within your app (on mobile, web, IoT, etc.), allowing you to read and write data even without an internet connection. Each instance of the Ditto SDK (often called a "small peer" in Ditto terminology) maintains its own local datastore, so the app remains fully functional offline and can share data locally. You interact with data in Ditto using the Ditto Query Language (DQL). DQL is a SQL-like language that allows you to read and write data to the local database, but is specialized for use with JSON-like structures and CRDTs. DQL can be executed using the `ditto.store.execute()` method in each of the Ditto SDKs, or via the `/store/execute` endpoint in the Ditto HTTP API. You can read more about DQL in the [DQL documentation](/dql/dql). ## Creating Data Creating data in Ditto involves inserting new documents into a collection in the local database. A collection in Ditto is similar to a table, and a document is a JSON-like object representing one record. To add a document, you typically call an insert operation on Ditto's store. This is done using an `INSERT INTO` DQL statement. For example, you can execute a query like: ```sql theme={null} INSERT INTO cars DOCUMENTS ({ 'make': 'Ford', 'model': 'Mustang' }) ``` This DQL statement would insert a new document into the cars collection with the given field, as no ID has been assigned to this document one would be automatically generated. Once the document is inserted, it is immediately stored in the local Ditto database, and is immediately visible for querying in the application. At the next available point, the new document will also be synced to other connected devices, see [Syncing Data](/key-concepts/syncing-data) for more information. For more examples of creating new documents in your language of choice, please see [Creating Documents](/sdk/latest/crud/create). ## Reading Data Reading data from Ditto is done by querying the documents in the local store using a DQL `SELECT` statement. For example: ```sql theme={null} SELECT * FROM cars ``` This will retrieve all documents in the cars collection and return the results in a json object. Typically you will want to refine the query to get a subset of data, especially in cases where there are many documents in the collection. DQL's `WHERE` clause allows you to filter the results based on specific criteria. For example: ```sql theme={null} SELECT * FROM cars WHERE color = 'blue' ``` This will retrieve all documents in the cars collection where the color field is "blue" and return the results in a json object. These queries are executed against the local Ditto store and will return results very quickly from the device's database. Querying the local store is very fast and works offline. Note that the results are not live, so if the data is updated on another device, the results will not be updated until the data on the other device is synced to the local device. For more examples of reading data in your language of choice, please see [Reading Documents](/sdk/latest/crud/read). ### Observing Changes If new data arrives (via sync) or local data changes, Ditto can notify your app directly, without needing to periodically run a query, so you can update the UI in real-time. This is done using Ditto's store observers, which is a change listener to a query that will be notified when the results of the query are updated. This is called using the `ditto.store.registerObserver()` method in each of the Ditto SDKs. By specifying a DQL `SELECT` statement, Ditto will notify the observer when the results of the query change. It will provide these results as a callback containing the full dataset of the results of the query, which can then be passed directly to the UI framework of your choice, which will often handle efficient updates to the UI based on the changes. For more examples of reacting to data changes in your language of choice, please see [Observing Data Changes](/sdk/latest/crud/observing-data-changes). ## Updating Data Updating data in Ditto means modifying existing documents in a collection. You can change one or more fields of a document by executing an UPDATE statement through DQL. The syntax follows a familiar SQL pattern: you specify the target collection, set new values for one or more fields, and include a WHERE clause to select which document(s) to update. For example, suppose we have a cars collection and we want to change the color of the car with `_id` `123` to blue. We could run: ```sql theme={null} UPDATE cars SET color = 'blue' WHERE _id = '123' ``` This will find the document in the cars collection whose ID is "123" and update its color field to "blue". You can set multiple fields in one update query as well (for instance, updating both color and model in the same statement). The WHERE clause can target any condition; often you'll use the document's `_id` to update a specific record, but you could update multiple documents at once if they match a filter. Only the specified fields are modified — all other fields in the document remain unchanged. When you execute an update, the changes are applied to the local store immediately. Ditto tracks this change and will propagate it to other peers on the network during the next sync. This means your update is done offline-safe: you can update data with no internet, and Ditto will queue that change to send out when connectivity is available. Each update operation in Ditto is idempotent on the target documents (applying the same update again will have no effect if the data is already updated) and will be merged with any concurrent changes from other devices. In essence, updating documents with Ditto is straightforward - you specify what to change and let Ditto handle applying it locally and syncing it globally. For more examples of updating data in your language of choice, please see [Updating Documents](/sdk/latest/crud/update). ## Removing Data Removing data in Ditto is the process of removing documents from a collection. There are typically two reasons that you want to delete data in Ditto: * Logical Deletes * Local Eviction These need to be handled differently within Ditto, and so the operations you use to remove data are different depending on the reason you want to remove the data. ### Logical Deletes Logical deletes are a way to remove data from Ditto where the removal has a semantic meaning within your application. For example deleting a user's account from the app. In this scenario you want to remove a document from the local store, but you also want the device to tell all other devices that it's replicating with to remove the same document. In short, you need that delete to be propagated throughout the entire system. This can be achieved in one of two ways, depending on if you need to retain the previous value of the document for any reason. #### Soft-Delete Pattern If you wish to retain the previous value of the document then we recommend following a soft-delete pattern. This is where you add a field to the document to indicate that it has been deleted, so that it can be handled appropriately throughout the rest of your system. For example you can add an `isDeleted` field to the document to indicate that it has been deleted, and then when specifying your subscription and setting up local queries/observers you can filter out documents where `isDeleted` is true. For example: ```sql theme={null} SELECT * FROM cars WHERE isDeleted = false ``` You can then periodically perform a [local eviction](#local-eviction) to remove deleted documents from the local store that you no longer need. More details on how to implement a soft-delete pattern can be found in the [Removing Documents](/sdk/latest/crud/delete) documentation. #### Tombstones If you do not need to retain the previous value of the document then you can use a tombstone pattern. This is where you remove the document from the local store entirely. This can be done using the `.remove()` method in the Ditto SDK, and in Ditto Server using the `TOMBSTONE` DQL operation: ```sql theme={null} TOMBSTONE FROM cars WHERE _id = '123' ``` Through Ditto's replication protocol, the tombstone will be propagated to other devices that currently have a non-tombstoned copy of the document, and so the document will be deleted from those devices. However, the tombstone itself will not be automatically cleaned up from the local store. These two different mechanisms will be collapsed into a single `DELETE` operation in Ditto 4.10. Tombstones will also be cleaned up automatically in Ditto 4.10. ### Local Eviction There are many scenarios where you may want to remove data from the local store without it being propagated to other devices. For example, in point-of-sales systems, it is not necessary to keep more than a few days of transaction data on the device, but you still need to retain the data upstream for reporting purposes. This local purging is achieved using the `EVICT` DQL operation. For example: ```sql theme={null} EVICT FROM cars WHERE _id = '123' ``` This will remove the document from the local store, but this will not be propagated to any other devices. If other connected peers contain a copy of that document, and the document matches the local device's subscription query, then the document will be re-replicated to the local device. It's therefore important to ensure that the subscription query is correctly set up or adjusted to not re-replicate the documents that you want to evict. You may note that the soft-delete pattern is a specialized version of local eviction where a boolean flag is used to indicate that the document is safe to be evicted. However, you can also use local eviction to evict documents using an alternative condition, such as a time-based condition (e.g. documents older than 3 days). You can read more about local purging and combining this with the subscription query in the [Removing Documents](/sdk/latest/crud/delete) documentation. # Authentication and Authorization Source: https://docs.ditto.live/key-concepts/authentication-and-authorization Ditto provides a flexible identity system to control which devices can participate in data synchronization, who they identify as (authentication), and what they can do (authorization). Ditto provides 3 authentication mechanisms: Online Playground, Online with Authentication, and Offline Shared Key. ## Online Authentication Mechanisms The primary mechanisms that Ditto provides for authentication use Ditto Server as a central authentication server. This means that all new devices and users must first connect to Ditto Server to authenticate, prior to being able to join and sync data with the mesh. ### Development Mode (Online Playground) Development mode (used to be referred to as Online Playground) is Ditto's authentication-light environment intended for development and testing, or use cases that do not require per-user permissioning. This allows developers to get a Ditto-enabled application up and running quickly with minimal setup. In this mode, devices connect through Ditto Server using a shared database ID and a Playground token, but without unique user authentication. Essentially, it's a sandbox identity provided for convenience. Ditto Server automatically trusts any client that knows the correct database identifier and its corresponding Playground token. This token (obtainable from the Ditto portal for your database, see [Getting SDK Connection Details](/cloud/portal/getting-sdk-connection-details)) is used to authenticate your SDK to Ditto Server - i.e. it tells the cloud "I belong to database X and I can prove it as I know the password". Every instance of your application uses the same token. Once the token and database ID are presented, the client can join the cloud-backed mesh and start syncing. There are no user names or passwords; the authentication is a single shared token (hence "Playground"). This makes it extremely easy to connect multiple devices and see data sync in action. The development mode is meant for quick experimentation and prototyping. It lets teams explore Ditto platform features and functionality without the overhead of setting up a custom auth server or user management. Great use cases include proof-of-concept apps, hackathons, or early development stages where you want to focus on core application logic and test syncing, rather than dealing with authentication infrastructure. It's also useful for demos or tutorials - for instance, spinning up a sample app where everyone uses the same token to join a shared data set. Development mode deliberately offers **limited security** for easy development and is **not recommended for production**. As the token is shared and static, it functions more like an API key that is the same for all clients. Anyone in possession of the token can connect and fully access the data. There is no concept of user-level permissions in this mode; all connected clients can read and write all data in the collections for that database. For production or any sensitive data, you'll want to switch to a more secure authentication method. Development mode has no individual identities, authorization within the database is essentially all-or-nothing. Every connected device has the same capabilities. If your use case requires certain clients to have read-only access or other restrictions, development mode cannot enforce that, use Online with Authentication instead. ### Online with Authentication Online with Authentication is Ditto's recommended authentication mode for Production. Unlike development mode, this mode integrates with real user identities or device credentials. Each client must log in to the Ditto network, and only upon successful authentication is it allowed to sync data with the cloud or peers. This approach is suitable for apps in **real world situations** where not every device is implicitly trusted -- it enables you to verify who is connecting, and control what each client can do. In Online with Authentication, the Ditto Server acts as a gatekeeper and coordinates the auth process. To use the **"Online with Authentication"** system, your client application is expected to authenticate with your identity system and retrieve a secret token (it can be any arbitrary string) *prior* to syncing with Ditto. Often times this token is some sort of identity token, access token, commonly in the format of a JWT (JSON Web Token). You can use an existing identity provider (e.g. Auth0, Clerk) or implement your own custom authentication mechanism, and as expected, you are responsible for the security of this token generation/passing aspect. Once your client application successfully has retrieved this token, it should pass it to the Ditto `authenticator` which will pass it to an authentication webhook. As the developer, you are responsible for writing code and deploying this webhook to an accessible URL. The authentication webhook will validate and decode the token from the client side and return identity and access control information back to your Ditto instance. The full flow is detailed in the diagram below: ```mermaid theme={null} sequenceDiagram Client App->>Your Authentication Mechanism: Send Credentials Your Authentication Mechanism->>Client App: Return a token string (e.g. a JWT) Client App->>Ditto Server: token string Ditto Server->>Auth Webhook: token string Auth Webhook->>Ditto Server: Formatted Ditto Auth Response Ditto Server->>Client App: Ditto Credentials rect rgba(0, 0, 255, .1) Client App->Ditto Server: Ditto Sync end ``` You can follow the [Online with Authentication](/sdk/latest/auth-and-authorization/cloud-authentication) tutorial to learn how to use the Online with Authentication identity. #### User Permissions A major benefit of Online with Authentication is that each user or device is distinct, which allows for fine-grained authorization rules. Since the user permissions are centrally managed in this mode, your authentication server can decide what each authenticated identity is allowed to do. These permissions are expressed on each collection in the form of queries, for example: The following write permissions describe that `userID: "123abc"` has been authenticated (`"authenticated": true`) and has the following permissions: 1. `write` to documents in the `"books"` collection matching the query `"_id.locationId == 'abcedef123456'"`. 2. `write` to any document in the `"newspapers"` collection. This is done with the single-word query `"true"` 3. `read` to documents in the `"books"` collection matching the query `"_id.locationId == 'abcedef123456'"` ```json JSON {9-14, 20-22} theme={null} { "authenticated": true, "expirationSeconds": 28800, "userID": "123abc", "permissions": { "write": { "everything": false, "queriesByCollection": { "books": [ "_id.locationId == 'abcedef123456'" ], "newspapers": [ "true" ] } }, "read": { "everything": false, "queriesByCollection": { "books": [ "_id.locationId == 'abcedef123456'" ], } } } } ``` To prevent users being able to "hijack" documents they should not have access to when using peer-to-peer replication, Ditto enforces that permissions can only be specified on the immutable `_id` field of a document. You should ensure that you model your data so that all of the fields that you want to control access to are part of the `_id` field. This means you could have viewer roles that only sync down data but cannot make edits, while admin roles have full read-write capabilities. All such rules are enforced by both Ditto Server and all devices participating in sync in the mesh. If a client tries to synchronize a document it isn't authorized for, the document will not be synchronized. Moreover, because authentication is individual, you can set a single user's permissions without affecting others. This granular control is essential for multi-user applications and aligns with typical enterprise security requirements. You can read more about how to appropriately authorize users in [Authorizing Users](/sdk/latest/auth-and-authorization/data-authorization). ### Detailed Online Certificate Flow Both online mechanisms follow the same basic flow, though they differ in how the supplied credentials are validated. The peer's public key will be included in the certificates returned by the identity service. The identity service needs proof that the authenticating device running the Ditto SDK actually holds the corresponding private key. 1. Device running the Ditto SDK downloads a challenge token from `/_ditto/auth/challenge` - this is a time-limited JWT which the client treats as opaque data. 2. Device running the Ditto SDK uses their Peer Key to sign it. When a client attempts to authenticate, it will make an HTTPS request to the identity service containing the following payload: * Signed challenge * Database ID * Provider name * Credentials to be forwarded to the app's webhook handler Once the identity service has a response from the auth webhook, it will build and sign the required Ditto Credentials (including a JWT and an X.509 certificate) and send them back down to the client. The response will include the client's generated certificate and private key, a list of CA certificates the client should trust, and a DateTime for expiration. The client will persist the JWT, device private key, device certificate, and CA certificates on disk and only update them when they get near expiration. When two peers authenticate with each other, they can use either the JWT or the device certificate via MTLS. The decision depends on the client's capabilities and connection type. ## Offline Shared Key
Shared Key authentication in Ditto is a simple, pre-shared secret model. It offers an intermediate level of security for scenarios where all devices and users are inherently trusted. In this mode, every peer (device) in the Ditto network is configured with the same secret key. As long as a device knows the shared key, it is considered authenticated and can join the network. All participants share a single secret cryptographic key that identifies the group. If a device presents the correct key, Ditto trusts it as an authenticated peer. In effect, **any device is trusted provided they know the shared key**. There is no central server verifying identities - trust is entirely based on possession of the shared secret. This makes setup straightforward (no user accounts or token exchanges are needed). Communication is encrypted using TLS 1.3 and peer identities are verified using certificates. This is the same state-of-the-art technology used in web browsers. It applies across all transports, from Bluetooth to WiFi. Each device issues a self-signed TLS certificate using the supplied private key. Peers then only trust peers whose certificates are signed by the same key. In other words, Shared Key uses regular TLS security, except everybody is the CA. Shared Key mode is designed for closed, controlled environments. For example, an enterprise might use it on a fleet of devices that are centrally managed and not connected to the Internet. It's suitable for offline or air-gapped deployments - such as on airplanes or on ships. In such cases, the shared key provides a quick way for devices to recognize each other and sync data without any cloud service. This mode assumes a high level of pre-existing trust. It is only suitable for private apps where users and devices are both trusted to perform any actions. All devices effectively have the same access rights, because they authenticate with the same credentials. There is no user-level differentiation – if you have the key, you have full read/write access to the data. Therefore, protecting the shared key is critical. If it were leaked or stolen, an unauthorized device could join and gain equal access. There's also no way to revoke a single device's access (short of changing the key for all devices). It is recommended that you should only use Shared Key when key distribution can be tightly controlled via a mechanism like MDM, and when the convenience of offline operation outweighs the lack of granular security controls. In general, we recommend using online authentication for any internet-connected or user-centric application. If you have a use-case where you cannot use online authentication, but wish to use per-device permissions, then you can setup a self-managed authentication server. Please [get in touch with us](mailto:support@ditto.com) if you'd like assistance in setting up a self-managed authentication server. The recommended way to generate a shared key is to download Ditto's open-source, cross-platform utility [`ditto-authtool`](https://github.com/getditto/authtool), which provides an easy command to generate new shared keys from a terminal or command prompt: ```Text Text theme={null} ./ditto-authtool generate-shared-key // or .\ditto-authtool.exe generate-shared-key ``` Alternatively, if you have a Unix-like machine running an up-to-date version of OpenSSL then you can use the following command. ```Text Text theme={null} openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -outform pem | openssl pkcs8 -topk8 -nocrypt -outform der | base64 -w 0 ``` The SharedKey identity requires an offline-only license token, which can be requested by contacting [support@ditto.com](mailto:support@ditto.com). # Databases and Collections Source: https://docs.ditto.live/key-concepts/databases-and-collections Ditto stores data records as documents (specifically JSON-like documents) which are gathered together in collections. A database stores one or more collections of documents. ## Databases In Ditto, a database is a grouping of collections. All databases that embed the Ditto SDK and share the same database ID will automatically form a mesh network and synchronize data with each other, either directly or via Ditto Server. Devices configured with different database IDs never sync with each other. A database ID functions like a tenant: data, configurations, and peer-to-peer connections are isolated to peers that share that ID. To keep data separate between projects, customers, or environments, issue a distinct database ID for each one from the Ditto portal. See [Creating a New Database](/cloud/portal/creating-a-new-app) for how to create and manage database IDs. ## Collections Ditto stores documents in collections. Collections are analogous to tables in relational databases. Collections allow you to group similar documents together within the same namespace. ### Structuring Collections While it is good practice for documents within a collection to share a similar structure — for instance, all car-related documents stored in the `cars` collection contain fields `'make'`, `'model'`, and `'year'` — structural uniformity is not mandatory. There is no limit to the number of collections you can have in your data model, so create as many collections as you need. ### Managing Collections Every document must be associated with a collection, even if only one document exists within that collection. There are no explicit steps to manage collections; Ditto implicitly creates collections when you first store data for that collection. ### Querying Collections When querying, database interactions occur with collections rather than individual documents. For instance, the query below searches the entire `cars` collection once executed. ```sql theme={null} SELECT * FROM cars ``` You can read more about accessing data within collections in [Accessing Data](/key-concepts/accessing-data). # Document Model Source: https://docs.ditto.live/key-concepts/document-model Ditto stores data records as JSON-like documents. Internally these documents are CRDTs, which are a binary representation of JSON documents designed for automatic conflict resolution. ## Document Structure Ditto documents are composed of field-and-value pairs and have the following structure: ```json theme={null} { field1: value1, field2: value2, field3: value3, ... fieldN: valueN } ``` The value of a field can be any of the JSON data types, including other documents, arrays, and arrays of documents. For example, the following document contains values of varying types: ```json theme={null} { _id: "0016d749-9a9b-4ece-8794-7f3eb40bc82e", name: "John Doe", age: 30, email: "john.doe@example.com", address: { street: "123 Main St", city: "Anytown", state: "CA", zip: "12345" }, is_active: true, created_at: "2021-01-01T00:00:00Z" } ``` The above fields have the following data types: * `_id`: `STRING` * `name`: `STRING` * `age`: `NUMBER` * `email`: `STRING` * `address`: `OBJECT` * `is_active`: `BOOLEAN` * `created_at`: `DATE` ## Identifying Documents In Ditto, each document stored in a collection requires a unique `_id` field that acts as a primary key. If an inserted document omits the `_id` field, Ditto automatically generates a unique identifier for the `_id` field. Once set for a given document, the `_id` field cannot be changed. The same document contents inserted with a different `_id` will be treated as a new document within Ditto. The `_id` is required for all documents and can be any JSON data type. While generating a unique identifier is the default behavior, typically you will provide your own `_id` values represented as a more complex object (acting as a composite key). For example, the following document includes a `_id` field with a complex object: ```json theme={null} { _id: { orderId: "0016d749-9a9b-4ece-8794-7f3eb40bc82e" locationId: "5da42ab5-d00b-4377-8524-43e43abf9e01" }, ... } ``` You can then either query documents using the entire `_id` object or by breaking it down into its individual components. ```sql DQL theme={null} SELECT * FROM orders WHERE _id.locationId = '5da42ab5-d00b-4377-8524-43e43abf9e01' ``` ```sql DQL theme={null} SELECT * FROM orders WHERE _id = {'orderId': '0016d749-9a9b-4ece-8794-7f3eb40bc82e', 'locationId': '5da42ab5-d00b-4377-8524-43e43abf9e01'} ``` It is important to carefully consider the `_id` field when designing your data model, as this is used for authorization rules within Ditto. For more information, see [Authorization](/key-concepts/authentication-and-authorization). ## Document Fields Documents are composed of fields, which are key-value pairs. ### Field Names Similar to most document-oriented databases, you can only use `strings` to encode field names in documents. For complete naming rules, see [IDs, Paths, Strings, and Keywords](/dql/ids-paths-strings-keywords). ### Field Values Field values can be encoded using various *data types*, including scalar types, providing flexibility in representing a wide range of information. Avoid using `arrays` in Ditto. Due to potential merge conflicts when offline peers reconnect to the mesh and attempt to sync their updates, especially when multiple peers make concurrent updates to the same item within the` array`. Instead using a JSON object within a `MAP` allows you to automatically merge the contents of the `MAP` when offline peers reconnect to the mesh. Each value of a field is stored as a specific CRDT type, for example a `MAP` or `REGISTER`. You can read more about CRDTs in [Syncing Data](/key-concepts/syncing-data#crdts). ## Document Size Each Ditto document has soft and hard size limits: * A document larger than the **soft limit (256 KiB)** logs a `warn`-level message; the write succeeds. * A document larger than the **hard limit (5 MiB)** logs an `error`-level message; the write currently succeeds. **Future versions will reject writes that exceed the hard limit and skip such documents during replication** — treat the error log as a deprecation signal and remediate now. Document size does not drive steady-state sync — Ditto syncs only the fields that change between peers. It does affect: * **Local storage and memory** on every device that holds the document. * **Serialization and deserialization time** on read and write. * **Initial replication and bulk catch-up**, where the full payload travels over the wire. On a Bluetooth Low Energy (BLE) link the practical ceiling is roughly 20 KB/sec, so a 256 KiB document takes about 10 seconds to replicate the first time. Subsequent edits sync only the changed fields and are far smaller. * **CRDT merge cost**, which scales with document size rather than change size — a small edit to a large document still pays the cost of a large merge. For storing large binary blobs such as images or video, use the [`ATTACHMENT`](/sdk/latest/crud/working-with-attachments) data type rather than embedding raw bytes. For the rationale behind the limits, monitoring guidance, remediation patterns, and runtime configuration, see [Document Size Limits](/best-practices/document-size-limits). For application-level modeling guidance, see [Data Modeling Tips](/best-practices/data-modeling#document-size). ## Relationships The recommended default in Ditto is to **embed related data within a single document**, typically as a map keyed by ID. This gives you atomic single-document writes, full sync as a unit, and Ditto's add-wins map merge for concurrent edits to different sub-entities. Use a foreign-key relationship across collections only when sub-entities need independent permission scopes, are accessed independently at scale, or would push the parent past the [document size limits](#document-size). See [Data Modeling Tips](/best-practices/data-modeling#modeling-relationships) and [Denormalized Documents](/best-practices/conflict-resolution-patterns#denormalized-documents-one-document-atomic-sync) for the full trade-off. ### Embedded Relationships An *embedded relationship* keeps related sub-entities inside the parent document, typically as a map keyed by the sub-entity's ID. Each entry in the map merges independently, so concurrent edits to different sub-entities — or different fields within one sub-entity — resolve cleanly without custom logic. For example, a `team` document with members embedded as a map keyed by member ID: ```json theme={null} { "_id": "engineering", "name": "Engineering", "members": { "alice": { "role": "lead", "joined": "2024-01-15" }, "bob": { "role": "engineer", "joined": "2024-03-22" } } } ``` Two devices editing different members, or different fields on the same member, will merge automatically. ### Foreign-Key Relationships To create a *foreign-key relationship*, store the `_id` of one document as a field within another. This splits related data across collections, which is useful when sub-entities need their own permission scope, are accessed independently of the parent, or would push the parent past the [document size limits](#document-size). For example, if you have two collections — `cars` and `owners` — where each car has a corresponding owner, every document in `cars` includes a field containing the `_id` of a document in `owners`: ```json Car theme={null} { "_id": "0016d749-9a9b-4ece-8794-7f3eb40bc82e", "owner_id": "5da42ab5-d00b-4377-8524-43e43abf9e01" } ``` ```json Owner theme={null} { "_id": "5da42ab5-d00b-4377-8524-43e43abf9e01", "name": "John Doe" } ``` # Mesh Networking Source: https://docs.ditto.live/key-concepts/mesh-networking The _mesh_ is an underlay for data sync within Ditto, operating independently of your queries and sync subscriptions. Data updates propagate through the mesh automatically to devices with matching subscriptions. Upon initiating the sync process by invoking the `sync.start()` function from the top-most scope of your app, devices running the Ditto SDK with the same database ID immediately form a *mesh network* using a mixture of communication transports, each with advantages and disadvantages. For example, Ditto prioritizes Wi-Fi for its high bandwidth and only falls back to Bluetooth LE when needed, in case of poor connectivity. Unlike typical home networks — which represent a star topology where all devices connect directly to a central router, switch, or access point — a peer-to-peer mesh network offers multiple pathways for communication. Here's a quick video explaining the various network transports: