Skip to main content
Public Preview - This version is in public preview and subject to changes. For production use, please use SDK v4.
You can react to changes in your local store by setting up a store observer. You can read more about store observers in Accessing Data. Store observers are useful when you want to monitor changes from your local Ditto store and react to them immediately. For instance, when your end user updates their profile, asynchronously display changes in realtime.

Understanding Observer Backpressure

When using store observers, callbacks fire every time matching data changes in your local store. In high-frequency scenarios—such as IoT sensors publishing multiple times per second or real-time position tracking—callbacks can fire faster than your application can process them. This leads to a backlog of pending callbacks, excessive memory consumption, and potential crashes. To handle this, Ditto provides registerObserverWithSignalNext, which gives you explicit control over when the observer can deliver the next update. Instead of automatic callback delivery, you call a signalNext function when your application is ready for the next batch of changes.
Without backpressure control, observer callbacks in high-frequency scenarios can overwhelm your application. Always use registerObserverWithSignalNext when updates may arrive faster than your app can process them.To determine if you need back pressure control see Choosing the Right Observer Method below.

Setting Up Store Observers

Use registerObserverWithSignalNext to control when your observer receives updates. The callback includes a signalNext function that you call when ready for the next update.
let observer = ditto.store.registerObserverWithSignalNext(
  query: "SELECT * FROM cars WHERE color = :color",
  arguments: ["color": "blue"]
) { result, signalNext in
  // Process the current result
  self.updateUI(with: result.items)

  // Signal readiness for next update
  signalNext()
}
For UI updates, consider calling signalNext() after your render cycle completes—for example, inside requestAnimationFrame in JavaScript or after DispatchQueue.main.async completes in Swift.

Basic Store Observer

For low-frequency updates where backpressure is not a concern, use the simpler registerObserver method.
This approach does not provide backpressure control. If updates arrive faster than your callback can process them, callbacks will queue up and may cause memory issues. For high-frequency scenarios, use registerObserverWithSignalNext instead.
To associate arguments with your query, add them as a parameter.

let observer = ditto.store.registerObserver(
  query: "SELECT * FROM cars WHERE color = :color",
  arguments: [ "color": "blue" ]){ result in /* handle change */ };

Choosing the Right Observer Method

ScenarioRecommended Method
High-frequency updates (sensors, real-time tracking)registerObserverWithSignalNext
UI updates that need render-cycle synchronizationregisterObserverWithSignalNext
Async processing that may take timeregisterObserverWithSignalNext
Low-frequency updates (user profile changes)registerObserver
Simple use cases with infrequent changesregisterObserver
For more information on memory management with observers, see the Diffing Results section which covers QueryResult lifecycle and proper cleanup patterns.

Canceling a Store Observer

To cancel a store observer, call cancel on the observer object. Once canceled, the store observer will stop processing in the background and will no longer call the provided callback.

observer.cancel()

Accessing Store Observers

To access store observers from the local Ditto store:

ditto.store.observers