Skip to main content
This feature is available in SDK version 4.12.0 and later.
This feature works fully with DQL Strict Mode disabled. DQL_STRICT_MODE=falseRead more about STRICT MODE and upcoming v5 behavior
The system:data_sync_info collection provides real-time information about synchronization status between your device and other peers in the Ditto mesh network.

What You Can Monitor

  • Connection status with peers and cloud servers
  • Sync progress using commit IDs
  • Last update timing from each peer

Document Structure

Each document in system:data_sync_info represents one peer connection:
{
  "_id": "peer-123",
  "is_ditto_server": true,
  "documents": {
    "sync_session_status": "Connected",
    "synced_up_to_local_commit_id": 1500,
    "last_update_received_time": 1703123456
  }
}

Key Fields

  • _id - Unique peer identifier
  • is_ditto_server - true for cloud servers, false for other devices
  • sync_session_status - "Connected", "Not Connected", or "Disabled"
  • synced_up_to_local_commit_id - Latest commit ID synced to this peer
  • last_update_received_time - Unix timestamp of last data received

Basic Queries

The examples in this document assume DQL Strict Mode is disabled.If DQL Strict Mode is enabled the collection definition must be provided.COLLECTION system:data_sync_info (documents MAP)Read more about STRICT MODE and upcoming v5 behavior

Get All Peers

SELECT * FROM system:data_sync_info
SELECT * FROM COLLECTION system:data_sync_info (documents MAP)

Get Only Cloud Servers

SELECT * FROM system:data_sync_info WHERE is_ditto_server = true

Get Connected Peers Only

SELECT * FROM system:data_sync_info WHERE documents.sync_session_status = 'Connected'

Get Specific Fields

SELECT _id, documents.sync_session_status, documents.synced_up_to_local_commit_id
FROM system:data_sync_info

Example in Code

// Get all sync info
let result = try await ditto.store.execute(
  query: "SELECT * FROM system:data_sync_info"
)

result.items.forEach { item in
  let peer = item.value
  let status = (peer["documents"] as? [String: Any])?["sync_session_status"] as? String ?? "Unknown"
  print("Peer \(peer["_id"] ?? ""): \(status)")
}
// Get all sync info.
ditto.store.execute("SELECT * FROM system:data_sync_info") { result ->
    result.items.forEach { item ->
        val peerId = item.value["_id"].stringOrNull ?: "unknown"
        val status = item.value["documents"].dictionaryOrNull
            ?.let { it["sync_session_status"].stringOrNull }
            ?: "Unknown"
        println("Peer $peerId: $status")
    }
}
// Get all sync info
const result = await ditto.store.execute(
  "SELECT * FROM system:data_sync_info"
);

result.items.forEach(item => {
  const peer = item.value;
  console.log(`Peer ${peer._id}: ${peer.documents.sync_session_status}`);
});
import { Ditto, QueryResult, QueryResultItem } from '@dittolive/ditto'

interface SyncDocuments {
  sync_session_status: string
  synced_up_to_local_commit_id: number
  last_update_received_time: number
}

interface PeerSyncInfo {
  _id: string
  is_ditto_server: boolean
  documents: SyncDocuments
}

// Get all sync info
const result: QueryResult = await ditto.store.execute(
  "SELECT * FROM system:data_sync_info"
)

result.items.forEach((item: QueryResultItem) => {
  const peer = item.value as PeerSyncInfo
  console.log(`Peer ${peer._id}: ${peer.documents.sync_session_status}`)
})
// Get all sync info
final result = await ditto.store.execute(
  "SELECT * FROM system:data_sync_info"
);

for (final item in result.items) {
  final peer = item.value as Map<String, dynamic>;
  final documents = peer["documents"] as Map<String, dynamic>;
  print("Peer ${peer["_id"]}: ${documents["sync_session_status"]}");
}
// Get all sync info
try (DittoQueryResult result = ditto.store.execute(
  "SELECT * FROM system:data_sync_info"
)) {
  for (DittoQueryResultItem item : result.getItems()) {
    Map<String, Object> peer = item.getValue();
    Map<String, Object> documents = (Map<String, Object>) peer.get("documents");
    String status = (String) documents.get("sync_session_status");
    System.out.println("Peer " + peer.get("_id") + ": " + status);
  }
}
// Get all sync info
using var result = await ditto.Store.ExecuteAsync(
  "SELECT * FROM system:data_sync_info"
);

foreach (var item in result.Items) {
  var peer = (Dictionary<string, object>)item.Value;
  var documents = (Dictionary<string, object>)peer["documents"];
  var status = (string)documents["sync_session_status"];
  Console.WriteLine($"Peer {peer["_id"]}: {status}");
}
// Get all sync info
auto result = ditto.get_store().execute("SELECT * FROM system:data_sync_info");

for (const auto& item : result.items()) {
  const auto& peer = item.value();
  const auto& documents = peer.at("documents").get<std::map<std::string, std::any>>();
  const auto& status = std::any_cast<std::string>(documents.at("sync_session_status"));
  std::cout << "Peer " << std::any_cast<std::string>(peer.at("_id")) << ": " << status << std::endl;
}
// Get all sync info
let result = ditto.store().execute((
  "SELECT * FROM system:data_sync_info",
  serde_json::Value::Null
)).await?;

for item in result.iter() {
  if let Some(peer) = item.value().as_object() {
    if let Some(documents) = peer.get("documents").and_then(|d| d.as_object()) {
      let status = documents.get("sync_session_status")
        .and_then(|s| s.as_str())
        .unwrap_or("Unknown");
      let peer_id = peer.get("_id")
        .and_then(|id| id.as_str())
        .unwrap_or("");
      println!("Peer {}: {}", peer_id, status);
    }
  }
}
// Get all sync info
result, err := dit.Store().Execute("SELECT * FROM system:data_sync_info")
if err != nil {
    return err
}
defer result.Close()  // cleanup

for _, item := range result.Items() {
    peer := item.Value()
    if documents, ok := peer["documents"].(map[string]any); ok {
        if status, ok := documents["sync_session_status"].(string); ok {
            if peerID, ok := peer["_id"].(string); ok {
                fmt.Printf("Peer %s: %s\n", peerID, status)
            }
        }
    }
}

Observing Changes

Observers on system:data_sync_info result in the callback triggering every 500ms even when the result remains the same. This frequency can be configured using the live_query_system_collection_refresh_interval system parameter.
Use registerObserver to monitor sync status changes in real-time:
let observer = ditto.store.registerObserver(
  query: "SELECT * FROM system:data_sync_info"
) { result in
  result.items.forEach { item in
    let peer = item.value
    let status = (peer["documents"] as? [String: Any])?["sync_session_status"] as? String ?? "Unknown"
    print("Peer \(peer["_id"] ?? ""): \(status)")
  }
}
// The DittoQueryResult is owned by the observer — don't wrap it in `use { }`.
// Use typed accessors on item.value (DittoCborSerializable.Dictionary); do not
// cast to Map<String, Any>.
val observer = ditto.store.registerObserver(
    "SELECT * FROM system:data_sync_info",
) { result ->
    result.items.forEach { item ->
        val peerId = item.value["_id"].stringOrNull ?: "unknown"
        val status = item.value["documents"].dictionaryOrNull
            ?.let { it["sync_session_status"].stringOrNull }
            ?: "Unknown"
        println("Peer $peerId: $status")
    }
}
const observer = ditto.store.registerObserver(
  "SELECT * FROM system:data_sync_info",
  (result) => {
    result.items.forEach(item => {
      const peer = item.value;
      console.log(`Peer ${peer._id}: ${peer.documents.sync_session_status}`);
    });
  }
);
import { Ditto, StoreObserver, QueryResult, QueryResultItem } from '@dittolive/ditto'

interface SyncDocuments {
  sync_session_status: string
  synced_up_to_local_commit_id: number
  last_update_received_time: number
}

interface PeerSyncInfo {
  _id: string
  is_ditto_server: boolean
  documents: SyncDocuments
}

const observer: StoreObserver = ditto.store.registerObserver(
  "SELECT * FROM system:data_sync_info",
  (result: QueryResult) => {
    result.items.forEach((item: QueryResultItem) => {
      const peer = item.value as PeerSyncInfo
      console.log(`Peer ${peer._id}: ${peer.documents.sync_session_status}`)
    })
  }
)
final observer = ditto.store.registerObserver(
  "SELECT * FROM system:data_sync_info",
  (result) {
    for (final item in result.items) {
      final peer = item.value as Map<String, dynamic>;
      final documents = peer["documents"] as Map<String, dynamic>;
      print("Peer ${peer["_id"]}: ${documents["sync_session_status"]}");
    }
  }
);
DittoObserver observer = ditto.store.registerObserver(
  "SELECT * FROM system:data_sync_info",
  (result) -> {
    try (result) {
      for (DittoQueryResultItem item : result.getItems()) {
        Map<String, Object> peer = item.getValue();
        Map<String, Object> documents = (Map<String, Object>) peer.get("documents");
        String status = (String) documents.get("sync_session_status");
        System.out.println("Peer " + peer.get("_id") + ": " + status);
      }
    }
  }
);
var observer = ditto.Store.RegisterObserver(
  "SELECT * FROM system:data_sync_info",
  (result) => {
    using(result)
    {
      foreach (var item in result.Items) {
        var peer = (Dictionary<string, object>)item.Value;
        var documents = (Dictionary<string, object>)peer["documents"];
        var status = (string)documents["sync_session_status"];
        Console.WriteLine($"Peer {peer["_id"]}: {status}");
      }
    }
  }
);
auto observer = store.register_observer(
  "SELECT * FROM system:data_sync_info",
  [](const auto& result) {
    for (const auto& item : result.items()) {
      const auto& peer = item.value();
      const auto& documents = peer.at("documents").get<std::map<std::string, std::any>>();
      const auto& status = std::any_cast<std::string>(documents.at("sync_session_status"));
      std::cout << "Peer " << std::any_cast<std::string>(peer.at("_id")) << ": " << status << std::endl;
    }
  }
);
let observer = ditto.store().register_observer(
  "SELECT * FROM system:data_sync_info",
  move |result| {
    for item in result.iter() {
      if let Some(peer) = item.value().as_object() {
        if let Some(documents) = peer.get("documents").and_then(|d| d.as_object()) {
          let status = documents.get("sync_session_status")
            .and_then(|s| s.as_str())
            .unwrap_or("Unknown");
          let peer_id = peer.get("_id")
            .and_then(|id| id.as_str())
            .unwrap_or("");
          println!("Peer {}: {}", peer_id, status);
        }
      }
    }
  }
)?;
observer, err := dit.Store().RegisterObserver(
    "SELECT * FROM system:data_sync_info",
    nil,  // no query arguments
    func(result *ditto.QueryResult) {
        defer result.Close()  // cleanup

        for _, item := range result.Items() {
            peer := item.Value()
            if documents, ok := peer["documents"].(map[string]any); ok {
                if status, ok := documents["sync_session_status"].(string); ok {
                    if peerID, ok := peer["_id"].(string); ok {
                        fmt.Printf("Peer %s: %s\n", peerID, status)
                    }
                }
            }
        }
    }
)
if err != nil {
    return err
}

Using Commit IDs

Every data modification returns a commit ID that you can use to track sync progress:
// Every mutation returns a commit ID
let result = try await ditto.store.execute(
  query: "UPDATE cars SET color = 'blue' WHERE _id = '123'"
)
print("Commit ID: \(result.commitID ?? -1)")
// Every mutation returns a commit ID — use the handler form of execute.
ditto.store.execute(
    "UPDATE cars SET color = 'blue' WHERE _id = '123'",
) { result ->
    println("Commit ID: ${result.commitId}")
}
// Every mutation returns a commit ID
const result = await ditto.store.execute(
  "UPDATE cars SET color = 'blue' WHERE _id = '123'"
);
console.log('Commit ID:', result.commitID);
import { Ditto, QueryResult } from '@dittolive/ditto'

// Every mutation returns a commit ID
const result: QueryResult = await ditto.store.execute(
  "UPDATE cars SET color = 'blue' WHERE _id = '123'"
)
const commitID: number | undefined = result.commitID
console.log('Commit ID:', commitID)
// Every mutation returns a commit ID
final result = await ditto.store.execute(
  "UPDATE cars SET color = 'blue' WHERE _id = '123'"
);
print("Commit ID: ${result.commitID}");
// Every mutation returns a commit ID
try (DittoQueryResult result = ditto.store.execute(
  "UPDATE cars SET color = 'blue' WHERE _id = '123'"
)) {
  System.out.println("Commit ID: " + result.getCommitID());
}
// Every mutation returns a commit ID
using var result = await ditto.Store.ExecuteAsync(
  "UPDATE cars SET color = 'blue' WHERE _id = '123'"
);
Console.WriteLine($"Commit ID: {result.CommitID}");
// Every mutation returns a commit ID
auto result = store.execute(
  "UPDATE cars SET color = 'blue' WHERE _id = '123'"
);
std::cout << "Commit ID: " << result.commitID() << std::endl;
// Every mutation returns a commit ID
let result = ditto.store().execute((
  "UPDATE cars SET color = 'blue' WHERE _id = '123'",
  serde_json::Value::Null
)).await?;
println!("Commit ID: {:?}", result.commit_id());
// Every mutation returns a commit ID
result, err := dit.Store().Execute(
    "UPDATE cars SET color = 'blue' WHERE _id = '123'")
if err != nil {
    return err
}
defer result.Close()  // cleanup
if commitID, ok := result.CommitID(); ok {
    fmt.Printf("Commit ID: %v\n", commitID)
}
Compare this commit ID with synced_up_to_local_commit_id to see if a peer has received your change.

Important Notes

Sync status information is local-only and never synchronizes between peers. Each peer maintains its own view of sync status.
  • Commit IDs are monotonic (always increasing) but not necessarily sequential
  • Multiple cloud servers may appear due to load balancing or failover
  • Local-only data - this collection exists only on your device
  • Minimal performance impact - observing sync status is lightweight

Supported APIs

API/FeatureIndex Support
execute SDK API✅ Supported
registerObserver SDK API✅ Supported
registerSubscription SDK API❌ Not Supported
Big Peer HTTP API❌ Not Supported
SDKs with in-memory storage (e.g. web browser)❌ Not Supported