> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ditto.live/llms.txt
> Use this file to discover all available pages before exploring further.

# Tracking Local Commits

> Use commit IDs to track when your local data modifications sync to other peers

<Note>
  This feature is available in SDK version 4.12.0 and later.
</Note>

Every data modification in Ditto returns a commit ID that you can use to track when that specific commit reaches other peers in your mesh network.

## What Are Commit IDs?

Commit IDs are unique, monotonically increasing identifiers assigned to each data modification on your device:

<CodeGroup>
  ```swift Swift theme={null}
  let result = try await ditto.store.execute(
    query: "UPDATE products SET price = 99.99 WHERE _id = 'product-123'"
  )
  print("Commit ID: \(result.commitID ?? -1)") // e.g., 1547
  ```

  ```kotlin Kotlin theme={null}
  ditto.store.execute(
    "UPDATE products SET price = 99.99 WHERE _id = 'product-123'"
  ).use { result ->
    println("Commit ID: ${result.commitId}") // e.g., 1547
  }
  ```

  ```javascript JavaScript theme={null}
  const result = await ditto.store.execute(
    "UPDATE products SET price = 99.99 WHERE _id = 'product-123'"
  );
  console.log('Commit ID:', result.commitID); // e.g., 1547
  ```

  ```typescript TypeScript theme={null}
  import { Ditto, QueryResult } from '@dittolive/ditto'

  const result: QueryResult = await ditto.store.execute(
    "UPDATE products SET price = 99.99 WHERE _id = 'product-123'"
  )
  const commitID: number | undefined = result.commitID
  console.log('Commit ID:', commitID) // e.g., 1547
  ```

  ```dart Dart theme={null}
  final result = await ditto.store.execute(
    "UPDATE products SET price = 99.99 WHERE _id = 'product-123'"
  );
  print("Commit ID: ${result.commitID}"); // e.g., 1547
  ```

  ```java Java theme={null}
  try (DittoQueryResult result = ditto.store.execute(
    "UPDATE products SET price = 99.99 WHERE _id = 'product-123'"
  )) {
    System.out.println("Commit ID: " + result.getCommitId()); // e.g., 1547
  }
  ```

  ```csharp C# theme={null}
  using var result = await ditto.Store.ExecuteAsync(
    "UPDATE products SET price = 99.99 WHERE _id = 'product-123'"
  );
  Console.WriteLine($"Commit ID: {result.CommitID}"); // e.g., 1547
  ```

  ```cpp C++ theme={null}
  auto result = store.execute(
    "UPDATE products SET price = 99.99 WHERE _id = 'product-123'"
  );
  std::cout << "Commit ID: " << result.commitID() << std::endl; // e.g., 1547
  ```

  ```rust Rust theme={null}
  let result = ditto.store().execute((
    "UPDATE products SET price = 99.99 WHERE _id = 'product-123'",
    serde_json::Value::Null
  )).await?;
  println!("Commit ID: {:?}", result.commit_id()); // e.g., Some(1547)
  ```

  ```go Go theme={null}
  result, err := dit.Store().Execute(
      "UPDATE products SET price = 99.99 WHERE _id = 'product-123'")
  if err != nil {
      return err
  }
  defer result.Close()  // cleanup
  if commitID, ok := result.CommitID(); ok {
      fmt.Printf("Commit ID: %s\n", commitID)  // e.g. 1547
  }
  ```
</CodeGroup>

## Key Properties

* **Monotonic** - Always increasing (1547, 1548, 1549...)
* **Device-specific** - Each device has its own sequence
* **Per-operation** - Every INSERT, UPDATE, DELETE gets a new ID
* **Trackable** - Use with `system:data_sync_info` to monitor sync progress

## Tracking Sync Progress

Compare your commit ID with `synced_up_to_local_commit_id` to see if peers have received your commit:

<CodeGroup>
  ```swift Swift theme={null}
  // Step 1: Execute statement and get commit ID
  let result = try await ditto.store.execute(
    query: "UPDATE orders SET status = 'shipped' WHERE _id = :id",
    arguments: ["id": "order-456"]
  )
  let commitId = result.commitID!

  // Step 2: Check if it synced to cloud
  let syncResult = try await ditto.store.execute(
    query: "SELECT * FROM system:data_sync_info WHERE is_ditto_server = true"
  )

  if let item = syncResult.items.first,
     let documents = item.value["documents"] as? [String: Any],
     let syncedUpTo = documents["synced_up_to_local_commit_id"] as? Int64 {

    if syncedUpTo >= commitId {
      print("Commit synced to cloud")
    } else {
      print("Syncing...")
    }
  }
  ```

  ```kotlin Kotlin theme={null}
  // Step 1: Execute statement and get commit ID
  ditto.store.execute(
    "UPDATE orders SET status = 'shipped' WHERE _id = :id",
    mapOf("id" to "order-456")
  ).use { result ->
    val commitId = result.commitId!!

    // Step 2: Check if it synced to cloud
    ditto.store.execute(
      "SELECT * FROM system:data_sync_info WHERE is_ditto_server = true"
    ).use { syncResult ->
      val item = syncResult.items.firstOrNull()
      val documents = item?.value?.get("documents") as? Map<String, Any>
      val syncedUpTo = documents?.get("synced_up_to_local_commit_id") as? Long ?: -1

      if (syncedUpTo >= commitId.longValue()) {
        println("Commit synced to cloud")
      } else {
        println("Syncing...")
      }
    }
  }
  ```

  ```javascript JavaScript theme={null}
  // Step 1: Execute statement and get commit ID
  const result = await ditto.store.execute(
    "UPDATE orders SET status = 'shipped' WHERE _id = :id",
    { id: "order-456" }
  );
  const commitId = result.commitID;

  // Step 2: Check if it synced to cloud
  const syncResult = await ditto.store.execute(
    "SELECT * FROM system:data_sync_info WHERE is_ditto_server = true"
  );

  if (syncResult.items.length > 0) {
    const syncedUpTo = syncResult.items[0].value.documents.synced_up_to_local_commit_id;

    if (syncedUpTo >= commitId) {
      console.log("Commit synced to cloud");
    } else {
      console.log("Syncing...");
    }
  }
  ```

  ```typescript TypeScript theme={null}
  import { Ditto, QueryResult } 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
  }

  // Step 1: Execute statement and get commit ID
  const result: QueryResult = await ditto.store.execute(
    "UPDATE orders SET status = 'shipped' WHERE _id = :id",
    { id: "order-456" }
  )
  const commitId: number = result.commitID!

  // Step 2: Check if it synced to cloud
  const syncResult: QueryResult = await ditto.store.execute(
    "SELECT * FROM system:data_sync_info WHERE is_ditto_server = true"
  )

  if (syncResult.items.length > 0) {
    const peer = syncResult.items[0].value as PeerSyncInfo
    const syncedUpTo: number = peer.documents.synced_up_to_local_commit_id

    if (syncedUpTo >= commitId) {
      console.log("Commit synced to cloud")
    } else {
      console.log("Syncing...")
    }
  }
  ```

  ```dart Dart theme={null}
  // Step 1: Execute statement and get commit ID
  final result = await ditto.store.execute(
    "UPDATE orders SET status = 'shipped' WHERE _id = :id",
    {"id": "order-456"}
  );
  final commitId = result.commitID!;

  // Step 2: Check if it synced to cloud
  final syncResult = await ditto.store.execute(
    "SELECT * FROM system:data_sync_info WHERE is_ditto_server = true"
  );

  if (syncResult.items.isNotEmpty) {
    final documents = syncResult.items[0].value["documents"] as Map<String, dynamic>;
    final syncedUpTo = documents["synced_up_to_local_commit_id"] as int;

    if (syncedUpTo >= commitId) {
      print("Commit synced to cloud");
    } else {
      print("Syncing...");
    }
  }
  ```

  ```java Java theme={null}
  // Step 1: Execute statement and get commit ID
  try (DittoQueryResult result = ditto.store.execute(
    "UPDATE orders SET status = 'shipped' WHERE _id = :id",
    Collections.singletonMap("id", "order-456")
  )) {
    long commitId = result.getCommitId();

    // Step 2: Check if it synced to cloud
    try (DittoQueryResult syncResult = ditto.store.execute(
      "SELECT * FROM system:data_sync_info WHERE is_ditto_server = true"
    )) {
      if (!syncResult.getItems().isEmpty()) {
        Map<String, Object> value = syncResult.getItems().get(0).getValue();
        Map<String, Object> documents = (Map<String, Object>) value.get("documents");
        long syncedUpTo = (Long) documents.get("synced_up_to_local_commit_id");

        if (syncedUpTo >= commitId) {
          System.out.println("Commit synced to cloud");
        } else {
          System.out.println("Syncing...");
        }
      }
    }
  }
  ```

  ```csharp C# theme={null}
  // Step 1: Execute statement and get commit ID
  using var result = await ditto.Store.ExecuteAsync(
    "UPDATE orders SET status = 'shipped' WHERE _id = :id",
    new Dictionary<string, object> { { "id", "order-456" } }
  );
  var commitId = result.CommitID;

  // Step 2: Check if it synced to cloud
  using var syncResult = await ditto.Store.ExecuteAsync(
    "SELECT * FROM system:data_sync_info WHERE is_ditto_server = true"
  );

  if (syncResult.Items.Count > 0) {
    var value = (Dictionary<string, object>)syncResult.Items[0].Value;
    var documents = (Dictionary<string, object>)value["documents"];
    var syncedUpTo = (long)documents["synced_up_to_local_commit_id"];

    if (syncedUpTo >= commitId) {
      Console.WriteLine("Commit synced to cloud");
    } else {
      Console.WriteLine("Syncing...");
    }
  }
  ```

  ```cpp C++ theme={null}
  // Step 1: Execute statement and get commit ID
  auto result = store.execute(
    "UPDATE orders SET status = 'shipped' WHERE _id = :id",
    {{"id", "order-456"}}
  );
  auto commitId = result.commitID();

  // Step 2: Check if it synced to cloud
  auto syncResult = store.execute(
    "SELECT * FROM system:data_sync_info WHERE is_ditto_server = true"
  );

  if (!syncResult.items().empty()) {
    const auto& value = syncResult.items()[0].value();
    const auto& documents = value.at("documents").get<std::map<std::string, std::any>>();
    auto syncedUpTo = std::any_cast<int64_t>(documents.at("synced_up_to_local_commit_id"));

    if (syncedUpTo >= commitId) {
      std::cout << "Commit synced to cloud" << std::endl;
    } else {
      std::cout << "Syncing..." << std::endl;
    }
  }
  ```

  ```rust Rust theme={null}
  // Step 1: Execute statement and get commit ID
  let result = ditto.store().execute((
    "UPDATE orders SET status = 'shipped' WHERE _id = :id",
    serde_json::json!({"id": "order-456"})
  )).await?;
  let commit_id = result.commit_id().unwrap();

  // Step 2: Check if it synced to cloud
  let sync_result = ditto.store().execute((
    "SELECT * FROM system:data_sync_info WHERE is_ditto_server = true",
    serde_json::Value::Null
  )).await?;

  if let Some(item) = sync_result.get_item(0) {
    if let Some(value) = item.value().as_object() {
      if let Some(documents) = value.get("documents").and_then(|d| d.as_object()) {
        if let Some(synced_up_to) = documents.get("synced_up_to_local_commit_id").and_then(|s| s.as_i64()) {
          if synced_up_to >= commit_id as i64 {
            println!("Commit synced to cloud");
          } else {
            println!("Syncing...");
          }
        }
      }
    }
  }
  ```

  ```go Go theme={null}
  // Step 1: Execute statement and get commit ID
  result, err := dit.Store().Execute(
      "UPDATE orders SET status = 'shipped' WHERE _id = :id",
      ditto.QueryArguments{"id" : "order-456"})
  if err != nil {
      return err
  }
  defer result.Close()  // cleanup
  commitID, _ := result.CommitID()

  // Step 2: Check if it synced to cloud
  syncResult, err := dit.Store().Execute(
      "SELECT * FROM system:data_sync_info WHERE is_ditto_server = true")
  if err != nil {
      return err
  }

  if result.ItemCount() > 0 {
      item := result.Item(0)
      defer item.Close()  // cleanup
      if documents, ok := item.Value()["documents"].(map[string]any); ok; {
          if syncedUpTo, ok := documents["synced_up_to_local_commit_id].(int64); ok {
              if syncedUpTo > commitID {
                  fmt.Println("Commit synced to cloud")
              } else {
                  fmt.Println("Syncing...)
              }
          }
      }
  }
  ```
</CodeGroup>

## Monitoring Multiple Commits

<Note>
  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.
</Note>

Track several commits and watch them sync in order:

<CodeGroup>
  ```swift Swift theme={null}
  var pendingCommits: [Int64] = []

  // Make several commits
  let result1 = try await ditto.store.execute(
    query: "UPDATE inventory SET quantity = quantity - 1 WHERE _id = 'item-1'"
  )
  if let commitId1 = result1.commitID {
    pendingCommits.append(commitId1)
  }

  let result2 = try await ditto.store.execute(
    query: "INSERT INTO orders DOCUMENTS (:order)",
    arguments: ["order": ["_id": "order-789", "status": "pending"]]
  )
  if let commitId2 = result2.commitID {
    pendingCommits.append(commitId2)
  }

  // Watch them sync
  let observer = ditto.store.registerObserver(
    query: "SELECT * FROM system:data_sync_info WHERE is_ditto_server = true"
  ) { result in
    guard let item = result.items.first,
          let documents = item.value["documents"] as? [String: Any],
          let syncedUpTo = documents["synced_up_to_local_commit_id"] as? Int64 else { return }

    // Check which commits have synced
    var syncedCount = 0
    for commitId in pendingCommits {
      if syncedUpTo >= commitId {
        print("Commit \(commitId) synced")
        syncedCount += 1
      } else {
        break
      }
    }

    // Remove synced commits
    if syncedCount > 0 {
      pendingCommits.removeFirst(syncedCount)
      print("\(pendingCommits.count) commits remaining")
    }
  }
  ```

  ```kotlin Kotlin theme={null}
  val pendingCommits = mutableListOf<BigInteger>()

  // Make several commits
  ditto.store.execute(
    "UPDATE inventory SET quantity = quantity - 1 WHERE _id = 'item-1'"
  ).use { result1 ->
    result1.commitId?.let { pendingCommits.add(it) }
  }

  ditto.store.execute(
    "INSERT INTO orders DOCUMENTS (:order)",
    mapOf("order" to mapOf("_id" to "order-789", "status" to "pending"))
  ).use { result2 ->
    result2.commitId?.let { pendingCommits.add(it) }
  }

  // Watch them sync
  ditto.store.registerObserver(
    "SELECT * FROM system:data_sync_info WHERE is_ditto_server = true"
  ) { queryResult ->
    queryResult.use { result ->
      val item = result.items.firstOrNull() ?: return@registerObserver
      val documents = item.value["documents"] as? Map<String, Any> ?: return@registerObserver
      val syncedUpTo = documents["synced_up_to_local_commit_id"] as? Long ?: return@registerObserver

      // Check which commits have synced
      var syncedCount = 0
      for (commitId in pendingCommits) {
        if (syncedUpTo >= commitId.longValue()) {
          println("✅Commit $commitId synced")
          syncedCount++
        } else {
          break
        }
      }

      // Remove synced commits
      if (syncedCount > 0) {
        repeat(syncedCount) { pendingCommits.removeAt(0) }
        println("${pendingCommits.size} commits remaining")
      }
    }
  }
  ```

  ```javascript JavaScript theme={null}
  const pendingCommits = [];

  // Make several commits
  const result1 = await ditto.store.execute(
    "UPDATE inventory SET quantity = quantity - 1 WHERE _id = 'item-1'"
  );
  pendingCommits.push(result1.commitID);

  const result2 = await ditto.store.execute(
    "INSERT INTO orders DOCUMENTS (:order)",
    { order: { _id: "order-789", status: "pending" } }
  );
  pendingCommits.push(result2.commitID);

  // Watch them sync
  const observer = ditto.store.registerObserver(
    "SELECT * FROM system:data_sync_info WHERE is_ditto_server = true",
    (result) => {
      if (!result.items.length) return;

      const syncedUpTo = result.items[0].value.documents.synced_up_to_local_commit_id;

      // Check which commits have synced
      let syncedCount = 0;
      for (const commitId of pendingCommits) {
        if (syncedUpTo >= commitId) {
          console.log(`Commit ${commitId} synced`);
          syncedCount++;
        } else {
          break;
        }
      }

      // Remove synced commits
      if (syncedCount > 0) {
        pendingCommits.splice(0, syncedCount);
        console.log(`${pendingCommits.length} commits remaining`);
      }
    }
  );
  ```

  ```typescript TypeScript theme={null}
  import { Ditto, QueryResult, StoreObserver } 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 pendingCommits: number[] = []

  // Make several commits
  const result1: QueryResult = await ditto.store.execute(
    "UPDATE inventory SET quantity = quantity - 1 WHERE _id = 'item-1'"
  )
  if (result1.commitID !== undefined) {
    pendingCommits.push(result1.commitID)
  }

  const result2: QueryResult = await ditto.store.execute(
    "INSERT INTO orders DOCUMENTS (:order)",
    { order: { _id: "order-789", status: "pending" } }
  )
  if (result2.commitID !== undefined) {
    pendingCommits.push(result2.commitID)
  }

  // Watch them sync
  const observer: StoreObserver = ditto.store.registerObserver(
    "SELECT * FROM system:data_sync_info WHERE is_ditto_server = true",
    (result: QueryResult) => {
      if (!result.items.length) return

      const peer = result.items[0].value as PeerSyncInfo
      const syncedUpTo: number = peer.documents.synced_up_to_local_commit_id

      // Check which commits have synced
      let syncedCount: number = 0
      for (const commitId of pendingCommits) {
        if (syncedUpTo >= commitId) {
          console.log(`Commit ${commitId} synced`)
          syncedCount++
        } else {
          break
        }
      }

      // Remove synced commits
      if (syncedCount > 0) {
        pendingCommits.splice(0, syncedCount)
        console.log(`${pendingCommits.length} commits remaining`)
      }
    }
  )
  ```

  ```dart Dart theme={null}
  final pendingCommits = <int>[];

  // Make several commits
  final result1 = await ditto.store.execute(
    "UPDATE inventory SET quantity = quantity - 1 WHERE _id = 'item-1'"
  );
  if (result1.commitID != null) {
    pendingCommits.add(result1.commitID!);
  }

  final result2 = await ditto.store.execute(
    "INSERT INTO orders DOCUMENTS (:order)",
    {"order": {"_id": "order-789", "status": "pending"}}
  );
  if (result2.commitID != null) {
    pendingCommits.add(result2.commitID!);
  }

  // Watch them sync
  final observer = ditto.store.registerObserver(
    "SELECT * FROM system:data_sync_info WHERE is_ditto_server = true",
    (result) {
      if (result.items.isEmpty) return;

      final documents = result.items[0].value["documents"] as Map<String, dynamic>;
      final syncedUpTo = documents["synced_up_to_local_commit_id"] as int;

      // Check which commits have synced
      int syncedCount = 0;
      for (final commitId in pendingCommits) {
        if (syncedUpTo >= commitId) {
          print("Commit $commitId synced");
          syncedCount++;
        } else {
          break;
        }
      }

      // Remove synced commits
      if (syncedCount > 0) {
        pendingCommits.removeRange(0, syncedCount);
        print("${pendingCommits.length} commits remaining");
      }
    }
  );
  ```

  ```java Java theme={null}
  List<BigInteger> pendingCommits = new ArrayList<>();

  // Make several commits
  try (DittoQueryResult result1 = ditto.store.execute(
    "UPDATE inventory SET quantity = quantity - 1 WHERE _id = 'item-1'"
  )){
      if (result1.getCommitId() != null) {
          pendingCommits.add(result1.getCommitId());
      }
  }

  try (DittoQueryResult result2 = ditto.store.execute(
    "INSERT INTO orders DOCUMENTS (:order)",
    Collections.singletonMap("order", Map.of("_id", "order-789", "status", "pending"))
  )){
      if (result2.getCommitId() != null) {
          pendingCommits.add(result2.getCommitId());
      }
  }

  // Watch them sync
  ditto.store.registerObserver(
    "SELECT * FROM system:data_sync_info WHERE is_ditto_server = true",
    (result) -> {
        try (result)
        {
          if (result.getItems().isEmpty()) return;

          Map<String, Object> value = result.getItems().get(0).getValue();
          Map<String, Object> documents = (Map<String, Object>) value.get("documents");
          long syncedUpTo = (Long) documents.get("synced_up_to_local_commit_id");

          // Check which commits have synced
          int syncedCount = 0;
          for (BigInteger commitId : pendingCommits) {
            if (syncedUpTo >= commitId.longValue()) {
                System.out.println("Commit " + commitId + " synced");
                syncedCount++;
            } else {
                break;
            }
          }

          // Remove synced commits
          if (syncedCount > 0) {
            pendingCommits.subList(0, syncedCount).clear();
            System.out.println(pendingCommits.size() + " commits remaining");
          }
        }
    }
  );
  ```

  ```csharp C# theme={null}
  var pendingCommits = new List<long>();

  // Make several commits
  using var result1 = await ditto.Store.ExecuteAsync(
    "UPDATE inventory SET quantity = quantity - 1 WHERE _id = 'item-1'"
  );
  if (result1.CommitID.HasValue) {
    pendingCommits.Add(result1.CommitID.Value);
  }

  using var result2 = await ditto.Store.ExecuteAsync(
    "INSERT INTO orders DOCUMENTS (:order)",
    new Dictionary<string, object> {
      { "order", new Dictionary<string, object> {
        { "_id", "order-789" },
        { "status", "pending" }
      }}
    }
  );
  if (result2.CommitID.HasValue) {
    pendingCommits.Add(result2.CommitID.Value);
  }

  // Watch them sync
  var observer = ditto.Store.RegisterObserver(
    "SELECT * FROM system:data_sync_info WHERE is_ditto_server = true",
    (result) => {
      using (result)
      {
        if (result.Items.Count == 0) return;

        var value = (Dictionary<string, object>)result.Items[0].Value;
        var documents = (Dictionary<string, object>)value["documents"];
        var syncedUpTo = (long)documents["synced_up_to_local_commit_id"];

        // Check which commits have synced
        int syncedCount = 0;
        foreach (var commitId in pendingCommits) {
          if (syncedUpTo >= commitId) {
            Console.WriteLine($"Commit {commitId} synced");
            syncedCount++;
          } else {
            break;
          }
        }

        // Remove synced commits
        if (syncedCount > 0) {
          pendingCommits.RemoveRange(0, syncedCount);
          Console.WriteLine($"{pendingCommits.Count} commits remaining");
        }
      }
    }
  );
  ```

  ```cpp C++ theme={null}
  std::vector<int64_t> pendingCommits;

  // Make several commits
  auto result1 = store.execute(
    "UPDATE inventory SET quantity = quantity - 1 WHERE _id = 'item-1'"
  );
  if (result1.commitID().has_value()) {
    pendingCommits.push_back(result1.commitID().value());
  }

  auto result2 = store.execute(
    "INSERT INTO orders DOCUMENTS (:order)",
    {{"order", std::map<std::string, std::any>{
      {"_id", std::string("order-789")},
      {"status", std::string("pending")}
    }}}
  );
  if (result2.commitID().has_value()) {
    pendingCommits.push_back(result2.commitID().value());
  }

  // Watch them sync
  auto observer = store.register_observer(
    "SELECT * FROM system:data_sync_info WHERE is_ditto_server = true",
    [&pendingCommits](const auto& result) {
      if (result.items().empty()) return;

      const auto& value = result.items()[0].value();
      const auto& documents = value.at("documents").get<std::map<std::string, std::any>>();
      auto syncedUpTo = std::any_cast<int64_t>(documents.at("synced_up_to_local_commit_id"));

      // Check which commits have synced
      size_t syncedCount = 0;
      for (const auto& commitId : pendingCommits) {
        if (syncedUpTo >= commitId) {
          std::cout << "Commit " << commitId << " synced" << std::endl;
          syncedCount++;
        } else {
          break;
        }
      }

      // Remove synced commits
      if (syncedCount > 0) {
        pendingCommits.erase(pendingCommits.begin(), pendingCommits.begin() + syncedCount);
        std::cout << pendingCommits.size() << " commits remaining" << std::endl;
      }
    }
  );
  ```

  ```rust Rust theme={null}
  let mut pending_commits: Vec<u64> = Vec::new();

  // Make several commits
  let result1 = ditto.store().execute((
    "UPDATE inventory SET quantity = quantity - 1 WHERE _id = 'item-1'",
    serde_json::Value::Null
  )).await?;
  if let Some(commit_id) = result1.commit_id() {
    pending_commits.push(commit_id);
  }

  let result2 = ditto.store().execute((
    "INSERT INTO orders DOCUMENTS (:order)",
    serde_json::json!({"order": {"_id": "order-789", "status": "pending"}})
  )).await?;
  if let Some(commit_id) = result2.commit_id() {
    pending_commits.push(commit_id);
  }

  // Watch them sync
  let observer = ditto.store().register_observer(
    "SELECT * FROM system:data_sync_info WHERE is_ditto_server = true",
    move |result| {
      if result.item_count() == 0 { return; }

      if let Some(item) = result.get_item(0) {
        if let Some(value) = item.value().as_object() {
          if let Some(documents) = value.get("documents").and_then(|d| d.as_object()) {
            if let Some(synced_up_to) = documents.get("synced_up_to_local_commit_id").and_then(|s| s.as_u64()) {

              // Check which commits have synced
              let mut synced_count = 0;
              for &commit_id in &pending_commits {
                if synced_up_to >= commit_id {
                  println!("Commit {} synced", commit_id);
                  synced_count += 1;
                } else {
                  break;
                }
              }

              // Remove synced commits
              if synced_count > 0 {
                pending_commits.drain(0..synced_count);
                println!("{} commits remaining", pending_commits.len());
              }
            }
          }
        }
      }
    }
  )?;
  ```

  ```go Go theme={null}
  var pendingCommits []uint64

  // Make several Commits
  result1, err := dit.Store().Execute(
      "UPDATE inventory SET quantity = quantity - 1 WHERE _id = 'item-1'"))
  if err != nil {
      return err
  }
  defer result1.Close()  // cleanup
  if commitID, ok := result1.CommitID(); ok {
      pendingCommits = append(pendingCommits, commitID)
  }

  // Make several Commits
  result2, err := dit.Store().Execute(
      "INSERT INTO orders DOCUMENTS (:order)",
      ditto.QueryArguments{"order" : ditto.Document{"_id" : "order-789", "status" : "pending}})
  if err != nil {
      return err
  }
  defer result2.Close()  // cleanup
  if commitID, ok := result2.CommitID(); ok {
      pendingCommits = append(pendingCommits, commitID)
  }

  // Watch them sync
  observer, err := dit.Store().RegisterObserver(
      "SELECT * FROM system:data_sync_info WHERE is_ditto_server = true",
      nil, // no query arguments
      func(result *ditto.QueryResult) {
          defer result.Close()  // cleanup

          if result.ItemCount() == 0 {
              return
          }

          item := result.Item(0)
          defer item.Close()  // cleanup
          if documents, ok := item.Value()["documents"].(map[string]any); ok {
              if syncedUpTo, ok := documents["synced_up_to_local_commit_id"].(uint64); ok {
                  // Check which commits have synced
                  var syncedCount int
                  for _, commitID := range pendingCommits {
                      if syncedUpTo > commitID {
                          fmt.Printf("Commit %u synced\n", commitID)
                          syncedCount++
                      } else {
                          break
                      }
                  }

                  // Remove synced commits
                  if syncedCount > 0 {
                      pendingCommits = pendingCommits[syncedCount:]
                      fmt.Printf("%d commits remaining\n", len(pendingCommits))
                  }
              }
          }
      }
  )
  if err != nil {
      return err
  }
  ```
</CodeGroup>

## Transaction Behavior

Commit IDs are only assigned after transactions complete:

<CodeGroup>
  ```swift Swift theme={null}
  var queryResult: DittoQueryResult?

  try await ditto.store.transaction { transaction in
    queryResult = try await transaction.execute(
      query: "INSERT INTO orders DOCUMENTS ({ _id: 'order-123', total: 99.99 })"
    )

    print(queryResult?.commitID ?? "nil") // nil - not committed yet

    return try await transaction.commit()
  }

  print(queryResult?.commitID ?? "nil") // 1548 - now has commit ID
  ```

  ```kotlin Kotlin theme={null}
  var queryResult: DittoQueryResult? = null

  ditto.store.transaction { transaction ->
    queryResult = transaction.execute(
      "INSERT INTO orders DOCUMENTS ({ _id: 'order-123', total: 99.99 })"
    )

    println(queryResult?.commitId ?: "null") // null - not committed yet

    transaction.commit()
  }

  queryResult.close()
  println(queryResult?.commitId ?: "null") // 1548 - now has commit ID
  ```

  ```javascript JavaScript theme={null}
  let queryResult;

  await ditto.store.transaction(async (transaction) => {
    queryResult = await transaction.execute(
      "INSERT INTO orders DOCUMENTS ({ _id: 'order-123', total: 99.99 })"
    );

    console.log(queryResult.commitID); // null - not committed yet

    return transaction.commit();
  });

  console.log(queryResult.commitID); // 1548 - now has commit ID
  ```

  ```typescript TypeScript theme={null}
  import { Ditto, QueryResult } from '@dittolive/ditto'

  let queryResult: QueryResult | undefined

  await ditto.store.transaction(async (transaction) => {
    queryResult = await transaction.execute(
      "INSERT INTO orders DOCUMENTS ({ _id: 'order-123', total: 99.99 })"
    )

    console.log(queryResult.commitID) // undefined - not committed yet

    return transaction.commit()
  })

  console.log(queryResult?.commitID) // 1548 - now has commit ID
  ```

  ```dart Dart theme={null}
  late QueryResult queryResult;

  await ditto.store.transaction((transaction) async {
    queryResult = await transaction.execute(
      "INSERT INTO orders DOCUMENTS ({ _id: 'order-123', total: 99.99 })"
    );

    print(queryResult.commitID); // null - not committed yet

    return TransactionCompletionAction.commit;
  });

  print(queryResult.commitID); // 1548 - now has commit ID
  ```

  ```java Java theme={null}
  DittoQueryResult queryResult = null;

  ditto.store.transaction((transaction) -> {
    queryResult = transaction.execute(
      "INSERT INTO orders DOCUMENTS ({ _id: 'order-123', total: 99.99 })"
    );

    System.out.println(queryResult.getCommitId() != null ? queryResult.getCommitId() : "null"); // null - not committed yet

    return transaction.commit();
  });

  queryResult.close();
  System.out.println(queryResult.getCommitId() != null ? queryResult.getCommitId() : "null"); // 1548 - now has commit ID
  ```

  ```csharp C# theme={null}
  DittoQueryResult queryResult = null;

  await ditto.Store.TransactionAsync(async (transaction) => {
    queryResult = await transaction.ExecuteAsync(
      "INSERT INTO orders DOCUMENTS ({ _id: 'order-123', total: 99.99 })"
    );

    Console.WriteLine(queryResult.CommitID?.ToString() ?? "null"); // null - not committed yet

    return await transaction.CommitAsync();
  });

  Console.WriteLine(queryResult.CommitID?.ToString() ?? "null"); // 1548 - now has commit ID
  queryResult.Dispose();
  ```

  ```cpp C++ theme={null}
  std::optional<DittoQueryResult> queryResult;

  ditto.get_store().transaction([&](auto& transaction) {
    queryResult = transaction.execute(
      "INSERT INTO orders DOCUMENTS ({ _id: 'order-123', total: 99.99 })"
    );

    std::cout << (queryResult->commitID().has_value() ?
      std::to_string(queryResult->commitID().value()) : "null") << std::endl; // null - not committed yet

    return transaction.commit();
  });

  std::cout << (queryResult->commitID().has_value() ?
    std::to_string(queryResult->commitID().value()) : "null") << std::endl; // 1548 - now has commit ID
  ```

  ```rust Rust theme={null}
  let mut query_result: Option<DittoQueryResult> = None;

  ditto.store().transaction(|transaction| async move {
    query_result = Some(transaction.execute((
      "INSERT INTO orders DOCUMENTS ({ _id: 'order-123', total: 99.99 })",
      serde_json::Value::Null
    )).await?);

    println!("{:?}", query_result.as_ref().and_then(|r| r.commit_id())); // None - not committed yet

    transaction.commit().await
  }).await?;

  println!("{:?}", query_result.as_ref().and_then(|r| r.commit_id())); // Some(1548) - now has commit ID
  ```

  ```go Go theme={null}
  var queryResult *ditto.queryResult

  _, err := dit.Store().Transaction(
      nil, // default operations
      func(transaction *ditto.Transaction) (ditto.TransactionCompletionAction, err) {
          var err error
          queryResult, err = transaction.Execute(
              "INSERT INTO orders DOCUMENTS ({ _id: 'order-123', total: 99.99 })")
          if err != nil {
              return ditto.TransactionCompletionActionRollback, err
          }

          if commitID, ok := queryResult.CommitID(); ok {
              // This branch won't be taken, as commit ID is not set yet
              fmt.Printf("%d\n", commitID)
          } else {
              fmt.Println("No commit ID")
          }

          return ditto.TransactionCallbackActionCommit, nil
      }
  )
  if err != nil {
      return err
  }
  defer queryResult.Close()  // cleanup

  if commitID, ok := queryResult.CommitID(); ok {
      // Now has commit ID
      fmt.Printf("%d\n", commitID)
  } else {
      // This branch won't be taken
      fmt.Println("No commit ID")
  }
  ```
</CodeGroup>

## Checking Specific Peers

Track sync progress to any peer (not just cloud servers):

<CodeGroup>
  ```swift Swift theme={null}
  // Check sync to a specific peer device
  let syncResult = try await ditto.store.execute(
    query: "SELECT * FROM system:data_sync_info WHERE _id = 'peer-device-456'"
  )

  if let item = syncResult.items.first,
     let documents = item.value["documents"] as? [String: Any],
     let peerSyncedUpTo = documents["synced_up_to_local_commit_id"] as? Int64 {
    print("Peer has synced up to commit \(peerSyncedUpTo)")
  }
  ```

  ```kotlin Kotlin theme={null}
  // Check sync to a specific peer device
  ditto.store.execute(
    "SELECT * FROM system:data_sync_info WHERE _id = 'peer-device-456'"
  ).use { syncResult ->
    if (syncResult.items.isNotEmpty()) {
      val item = syncResult.items.first()
      val documents = item.value["documents"] as? Map<String, Any>
      val peerSyncedUpTo = documents?.get("synced_up_to_local_commit_id") as? Long
      println("Peer has synced up to commit $peerSyncedUpTo")
    }
  }
  ```

  ```javascript JavaScript theme={null}
  // Check sync to a specific peer device
  const syncResult = await ditto.store.execute(
    "SELECT * FROM system:data_sync_info WHERE _id = 'peer-device-456'"
  );

  if (syncResult.items.length > 0) {
    const peerSyncedUpTo = syncResult.items[0].value.documents.synced_up_to_local_commit_id;
    console.log(`Peer has synced up to commit ${peerSyncedUpTo}`);
  }
  ```

  ```typescript TypeScript theme={null}
  import { Ditto, QueryResult } 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
  }

  // Check sync to a specific peer device
  const syncResult: QueryResult = await ditto.store.execute(
    "SELECT * FROM system:data_sync_info WHERE _id = 'peer-device-456'"
  )

  if (syncResult.items.length > 0) {
    const peer = syncResult.items[0].value as PeerSyncInfo
    const peerSyncedUpTo: number = peer.documents.synced_up_to_local_commit_id
    console.log(`Peer has synced up to commit ${peerSyncedUpTo}`)
  }
  ```

  ```dart Dart theme={null}
  // Check sync to a specific peer device
  final syncResult = await ditto.store.execute(
    "SELECT * FROM system:data_sync_info WHERE _id = 'peer-device-456'"
  );

  if (syncResult.items.isNotEmpty) {
    final documents = syncResult.items[0].value["documents"] as Map<String, dynamic>;
    final peerSyncedUpTo = documents["synced_up_to_local_commit_id"] as int;
    print("Peer has synced up to commit $peerSyncedUpTo");
  }
  ```

  ```java Java theme={null}
  // Check sync to a specific peer device
  try (DittoQueryResult syncResult = ditto.store.execute(
    "SELECT * FROM system:data_sync_info WHERE _id = 'peer-device-456'"
  )) {
    if (!syncResult.getItems().isEmpty()) {
      Map<String, Object> value = syncResult.getItems().get(0).getValue();
      Map<String, Object> documents = (Map<String, Object>) value.get("documents");
      long peerSyncedUpTo = (Long) documents.get("synced_up_to_local_commit_id");
      System.out.println("Peer has synced up to commit " + peerSyncedUpTo);
    }
  }
  ```

  ```csharp C# theme={null}
  // Check sync to a specific peer device
  using var syncResult = await ditto.Store.ExecuteAsync(
    "SELECT * FROM system:data_sync_info WHERE _id = 'peer-device-456'"
  );

  if (syncResult.Items.Count > 0) {
    var value = (Dictionary<string, object>)syncResult.Items[0].Value;
    var documents = (Dictionary<string, object>)value["documents"];
    var peerSyncedUpTo = (long)documents["synced_up_to_local_commit_id"];
    Console.WriteLine($"Peer has synced up to commit {peerSyncedUpTo}");
  }
  ```

  ```cpp C++ theme={null}
  // Check sync to a specific peer device
  auto syncResult = store.execute(
    "SELECT * FROM system:data_sync_info WHERE _id = 'peer-device-456'"
  );

  if (!syncResult.items().empty()) {
    const auto& value = syncResult.items()[0].value();
    const auto& documents = value.at("documents").get<std::map<std::string, std::any>>();
    auto peerSyncedUpTo = std::any_cast<int64_t>(documents.at("synced_up_to_local_commit_id"));
    std::cout << "Peer has synced up to commit " << peerSyncedUpTo << std::endl;
  }
  ```

  ```rust Rust theme={null}
  // Check sync to a specific peer device
  let sync_result = ditto.store().execute((
    "SELECT * FROM system:data_sync_info WHERE _id = 'peer-device-456'",
    serde_json::Value::Null
  )).await?;

  if let Some(item) = sync_result.get_item(0) {
    if let Some(value) = item.value().as_object() {
      if let Some(documents) = value.get("documents").and_then(|d| d.as_object()) {
        if let Some(peer_synced_up_to) = documents.get("synced_up_to_local_commit_id").and_then(|s| s.as_u64()) {
          println!("Peer has synced up to commit {}", peer_synced_up_to);
        }
      }
    }
  }
  ```

  ```go Go theme={null}
  // Check sync to a specific peer device
  syncResult, err := dit.Store().Execute(
      "SELECT * FROM system:data_sync_info WHERE _id = 'peer-device-456'")
  if err != nil {
      return err
  }
  defer syncResult.Close()  // cleanup

  if syncResult.ItemCount() > 0 {
      item := syncResult.Item(0)
      defer item.Close()  // cleanup
      if documents, ok := item.Value()["documents"].(map[string]any); ok {
          if peerSyncedUpTo, ok := documents["synced_up_to_local_commit_id"].(uint64); ok {
              fmt.Printf("Peer has synced up to commit %u\n", peerSyncedUpTo)
          }
      }
  }
  ```
</CodeGroup>

## Best Practices

<Info>
  Remember that Ditto is offline-first. Use commit ID tracking to enhance user experience, not to block operations.
</Info>

* **Don't block operations** - Let users continue working while tracking sync in background
* **Show progress indicators** - Use commit tracking to display sync status in your UI
* **Handle concurrency gracefully** - Tracking should enhance the experience, not block it
* **Monitor critical data** - Focus tracking on important operations like payments or submissions
* **Clean up tracking** - Remove old commit IDs from your tracking lists to avoid memory issues

## Related Topics

* [Monitoring Sync Status](/sdk/latest/sync/monitoring-sync-status) - Overview of the system:data\_sync\_info collection
* [Track Ditto Cloud Sync Status](/sdk/latest/sync/cloud-sync-status) - Cloud-specific sync monitoring patterns
