---
title: "Instant sync and document state on Android | Nutrient SDK"
canonical_url: "https://www.nutrient.io/guides/android/pspdfkit-instant/instant-document-state/"
md_url: "https://www.nutrient.io/guides/android/pspdfkit-instant/instant-document-state.md"
last_updated: "2026-05-15T19:10:04.908Z"
description: "Over the course of its lifetime, any InstantPdfDocument will go through several states. This article covers those states and their transitions in detail."
---

# Instant sync and document state on Android

Over the course of its lifetime, any [`InstantPdfDocument`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.instant.document/-instant-pdf-document/index.html) will go through several states. This article covers those states and their transitions in detail.

## Lifecycle of an Instant document

Each document descriptor is initially created with a document state of [`CLEAN`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.instant.document/-instant-document-state/-c-l-e-a-n/index.html), meaning the document data is up to date. You can create, read, update, and delete (CRUD) annotations in this document. Making changes to annotations will result in the document descriptor being [`DIRTY`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.instant.document/-instant-document-state/-d-i-r-t-y/index.html), which begets a sync.

As written elsewhere, all syncing is two-way: You cannot decide to _just fetch_ or _just push_ data! Instead, syncing _always_ means that _any local changes_ are sent to the server, which then _decides a new truth_. The server replies with the necessary changes for your local copy to know this new truth, which is then applied locally. For details about the state transitions this entails, refer to the section on [the sync cycle](#the-sync-cycle) below.

When you are no longer interested in the local data backing a document, you can tell it to [`removeLocalStorage`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.instant.document/-instant-pdf-document/remove-local-storage.html). As the name implies, this will delete all local data. In addition, any ongoing network activity will be canceled immediately. Calling this method while the document is pushing changes to the server is possible, but it’s generally not recommended. When [`removeLocalStorage`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.instant.document/-instant-pdf-document/remove-local-storage.html) returns, the document will be in an [`INVALID`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.instant.document/-instant-document-state/-i-n-v-a-l-i-d/index.html) state and all future interactions will fail.

Because every document is managed by the [`InstantClient`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.instant.client/-instant-client/index.html) that created it, it cannot be used without a client. So when a client is invalidated, all documents managed by this client become [`INVALID`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.instant.document/-instant-document-state/-i-n-v-a-l-i-d/index.html). The other — albeit unlikely — case where a document can enter this state is when Instant detects that its backing data has become corrupted. In this dire situation, there is little you can do apart from calling [`removeLocalStorage`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.instant.document/-instant-pdf-document/remove-local-storage.html).

## The sync cycle

When a document descriptor starts syncing, it notifies all registered document listeners by calling [`onSyncStarted`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.instant.listeners/-instant-document-listener/on-sync-started.html). It then begins to _cycle_ through several states until all local changes have been synced and the newest server truth has been applied, or until an error occurs. Depending upon the initial document state, this is accompanied by a change to either [`SENDING_CHANGES`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.instant.document/-instant-document-state/-s-e-n-d-i-n-g_-c-h-a-n-g-e-s/index.html) if there were local changes, or [`RECEIVING_CHANGES`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.instant.document/-instant-document-state/-r-e-c-e-i-v-i-n-g_-c-h-a-n-g-e-s/index.html) if there were not. When it begins receiving the new server truth, [`onDocumentStateChanged`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.instant.listeners/-instant-document-listener/on-document-state-changed.html) is called and the document state switches to [`RECEIVING_CHANGES`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.instant.document/-instant-document-state/-r-e-c-e-i-v-i-n-g_-c-h-a-n-g-e-s/index.html) until this truth has been applied to the local database.

Depending on various factors, this can take any amount of time. It is therefore possible that new local changes will have been made when Instant applies the newest server truth. If there are no local changes after applying the new server truth, the sync cycle completes by calling [`onSyncFinished`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.instant.listeners/-instant-document-listener/on-sync-finished.html) and updating the document state to [`CLEAN`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.instant.document/-instant-document-state/-c-l-e-a-n/index.html). If, on the other hand, there are unsynced local changes, the sync cycle will continue, [`onDocumentStateChanged`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.instant.listeners/-instant-document-listener/on-document-state-changed.html) will be called, and the document state will be updated to [`SENDING_CHANGES`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.instant.document/-instant-document-state/-s-e-n-d-i-n-g_-c-h-a-n-g-e-s/index.html).

### Errors during sync

If an error occurs while a sync cycle is running, the cycle terminates immediately, and an [`onSyncError`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.instant.listeners/-instant-document-listener/on-sync-error.html) is called. If the local database contains changes that have not yet been confirmed by the server, the document state is updated to [`DIRTY`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.instant.document/-instant-document-state/-d-i-r-t-y/index.html). Otherwise, the state is updated to [`CLEAN`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.instant.document/-instant-document-state/-c-l-e-a-n/index.html).

In the case of network errors, Instant will retry the sync operation using an exponential, jittered, backoff strategy. In case of authentication failures — such as when the authentication token expires — no such reattempts will be made. Instead, a sync will be started after you make a successful call to `reauthenticateWithJwt`.
---

## Related pages

- [Efficient PDF annotation syncing on Android](/guides/android/pspdfkit-instant/syncing.md)
- [Adding Instant comments to PDFs on Android](/guides/android/comments/introduction-to-instant-comments.md)
- [Authenticate your Android app with JWT](/guides/android/instant-synchronization/authentication.md)
- [Frequently asked questions](/guides/android/instant-synchronization/faq.md)
- [Instant usage on Android](/guides/android/pspdfkit-instant/usage.md)
- [PDF collaboration library for Android](/guides/android/instant-synchronization.md)
- [Create and manage PDF annotation layers on Android](/guides/android/pspdfkit-instant/instant-layers.md)
- [Integrating real-time collaboration into your Android application](/guides/android/pspdfkit-instant/getting-started.md)
- [Effortless offline PDF annotation and sync](/guides/android/pspdfkit-instant/offline-support.md)

