Handling Write / Validation Errors

The general approach is that transient errors (e.g. server or database unavailable), the changes are kept in the client-side queue, and retried at 5 second intervals, keeping the original order. In the future it will be possible to control the retry behavior.

For validation errors or write conflicts (see the definition of this below in Technical Details), changes are automatically rolled back on the client.

Custom logic can be implemented to propagate validation failures back to clients asynchronously. For additional details on how to do that, see the section on Custom Conflict Resolution.

Additional Technical Details

For each change (or batch of changes), some possible scenarios are:

  1. Change failed, for example due to network or temporary server error. The change is kept in the queue.

  2. Change acknowledged and applied on the server. The client syncs back the change, which would match what the client already had.

  3. Change acknowledged but rejected (e.g. validation error). The client rolls back the change.

  4. Change acknowledged and partially applied or otherwise alternated. The client syncs back the state as applied on the server.

In all cases, PowerSync ensures that the client state is fully consistent with the server state, once the queue is empty.

Backend implementation recommendations

The backend should respond with “success” (HTTP 2xx) even in the case of write conflicts or validation failures, unless developer intervention is desired.

Error responses should be reserved for:

  1. Network errors.

  2. Temporary server errors (e.g. high load, or database unavailable).

  3. Unexpected bugs or schema mismatches, where the change should stay in the client-side queue.

If a bug triggers an error, it has to be fixed before the changes from the client can be processed. It is recommended to use an error reporting service on both the server and the client to be alerted of cases like this.

To propagate validation failures or write conflicts back to the client, either:

  1. Include error details the body of a success response (HTTP 2xx).

  2. Write the details to a different table, asynchronously synchronized back to the client.

For more details on strategies, see:

pageCustom Conflict Resolution

Dead-letter queue

Optionally, the server can implement a “dead-letter queue”:

  • If a change cannot be processed due to a conflict, schema mismatch and/or bug, the change can be persisted in a separate queue on the backend.

  • This can then be manually inspected and processed by the developer or administrator, instead of blocking the client.

  • Note that this could result in out-of-order updates if the client continues sending updates, despite earlier updates being persisted in the dead-letter queue.

While the client could implement a dead-letter queue, this is not recommended, since this cannot easily be inspected by the developer. The information is also often not sufficient to present to the user in a friendly way or to allow manual conflict resolution.

How changes are rolled back

There is no explicit "roll-back" operation on the client - but a similar effect is achieved by the internals of PowerSync. The core principle is that when the client completes a sync with an empty upload queue, the local database will be consistent with the server-side database.

This is achieved by:

  1. The client keeps a copy of the data as synced from the server, and continuously updates this.

  2. Once all the changes from the client are uploaded, and the local “server state” is up to date, it updates the local database with the local server state.

  3. If the local change was applied by the server, it will be synced back and included in the local server state.

  4. If the local change was discarded by the server, the server state will not change, and the client will revert to the last known state.

  5. If another conflicting write “won”, that write will be present in the server state, and will overwrite the local changes.

Last updated