Skip to main content
Ditto uses a query-based sync model: each peer declares the data it wants to receive through a subscription query, and the mesh delivers matching documents — incrementally, at the field level, even across intermittent connections. Because subscription queries define what flows through the mesh, how you design and operate them is the primary lever for sync efficiency. This page covers operational best practices for subscriptions. For the conceptual model, see Syncing Data; for the SDK API, see Managing Subscriptions.

Syncing Data

The conceptual model: subscription queries, delta sync, and CRDT-based conflict resolution.

Managing Subscriptions

SDK reference for registering, retrieving, and canceling subscriptions in each language.

Stateful Subscription Performance Guidelines

How LIMIT and ORDER BY clauses affect sync performance, and how to write subscription queries that scale.

Mesh Networking

How peers discover each other and propagate updates across multiple transports.

Scope subscriptions to the data each peer needs

In a query-based sync model, a peer only receives documents that match the queries it has subscribed to. A well-scoped subscription reduces bandwidth, storage, and CPU on every device in the mesh, and lets the sync engine prioritize the data that matters to the user in front of the device. Subscribe to the narrowest set of documents the device actually needs — filter by tenant, region, role, or whatever dimensions partition your data — rather than syncing entire collections. When peers run the same subscription, Ditto’s flood-fill propagation works at full efficiency: any peer with matching documents can serve any other peer that wants them, regardless of who originally produced the data. Where practical, align subscription shapes across peers in the same role.

Keep subscriptions stable

Each time a subscription is registered, canceled, or changed, peers across the mesh re-evaluate what they owe the local device and the sync engine reconciles state. Doing this frequently degrades sync throughput and can interrupt in-flight transfers. As a general guideline, avoid changing subscriptions more often than every fifteen minutes or so. Register subscriptions when the relevant data first becomes needed — at app start, after login, or when the user enters a workspace — and cancel them when that data is no longer relevant. To filter the data a user sees within a stable subscription, run a local query against the result set rather than re-registering the subscription with new arguments.
When subscriptions are created dynamically, cancel those that are no longer needed as new ones are registered. Subscriptions remain active until explicitly canceled, so unreleased subscriptions can accumulate over time and affect sync performance.

Avoid stateful subscription patterns

Subscription queries that use LIMIT, or LIMIT combined with ORDER BY, maintain state about which documents currently fall within the limit boundary. When a document inside the boundary changes — is deleted, no longer matches the WHERE clause, or moves position under the ORDER BY — Ditto must invalidate its cache and re-evaluate the query. This is manageable when the relevant fields rarely change, but expensive when they change often.
Key rule: avoid filtering (WHERE) or sorting (ORDER BY) on mutable fields when LIMIT is used.
For the full guide — query examples, cache-invalidation rules, and migration strategies — see Stateful Subscription Performance Guidelines.

Use multiple transports

Ditto’s multiplexer chooses among Wi-Fi, Bluetooth Low Energy, and WebSocket connections automatically based on availability and conditions. Leave all relevant transports enabled in your transport configuration so the runtime can switch as devices move between environments. See Customizing Transport Configurations.

Rely on built-in conflict resolution

Concurrent edits across peers resolve deterministically through Ditto’s CRDT merge rules — applications do not need locking, write-time conflict callbacks, or custom merge code. Designing data models that work with these rules (rather than against them) is the main contributor to predictable behavior under concurrent writes. See Conflict Resolution Patterns.

Design for offline-first operation

Ditto stores subscribed data locally and continues to read, write, and resolve conflicts while disconnected. When connectivity returns, peers reconcile their changes through delta sync — only the modified fields transit the network. Build flows that assume the local database is always available and treat connectivity as opportunistic.