DataFn
Sync

Hydration

Configure startup data loading strategy.

Hydration controls how the client loads data on startup. By default, the sync engine clones all resources before the application is ready. For large schemas, you can use a hydration plan to prioritize critical resources and defer others.

Hydration States

Each resource tracks its own hydration state:

StateDescription
notStartedResource has not been cloned yet
hydratingClone is in progress
readyResource is fully hydrated and available for local queries
failedBackground clone failed (resource can be retried)

State transitions are validated. For example, a resource cannot transition from ready back to notStarted.

Hydration Plan

A hydration plan splits resources into two groups:

  • bootResources -- Cloned before the application is considered ready. Blocks startup until complete.
  • backgroundResources -- Cloned asynchronously after boot resources are ready. Does not block startup.
const client = createDatafnClient({
  schema,
  sync: {
    remote: "https://api.example.com",
    hydration: {
      bootResources: ["users", "settings"],
      backgroundResources: ["auditLog", "analytics"],
      clonePageSize: 5000,
    },
  },
});

Startup Sequence

  1. Check hydration state for each boot resource.
  2. Clone any boot resources that are not yet "ready".
  3. If all boot resources were already "ready", perform an incremental pull instead.
  4. Schedule background resources for async clone (non-blocking).

Page Size Configuration

The clonePageSize option controls pagination during clone. It can be a global number or a per-resource map:

hydration: {
  bootResources: ["todos"],
  clonePageSize: {
    todos: 10000,      // Large resource: bigger pages
    settings: 100,     // Small resource: smaller pages
  },
}

Query Routing by Hydration State

The hydration state of a resource determines whether queries run locally or are forwarded to the remote server:

// "users" is a boot resource -- guaranteed to be hydrated before this runs
const currentUser = await client.table("users").query({
  filters: { id: userId },
});

// "auditLog" may still be loading in background
// If not yet hydrated, this query falls back to the remote server
const logs = await client.table("auditLog").query({
  sort: ["createdAt:desc"],
  limit: 20,
});

Per-Resource State Tracking

You can observe hydration progress through the storage adapter:

const state = await storage.getHydrationState("todos");
// "notStarted" | "hydrating" | "ready" | "failed"

Background Clone Failures

If a background resource fails to clone, its state is set to "failed" and a sync_failed event is emitted. The resource remains unavailable for local queries and falls back to remote. You can trigger a re-clone by restarting the sync engine or calling clone manually.

client.events.on("sync_failed", (event) => {
  if (event.context.operation === "background") {
    console.warn("Background clone failed for:", event.context.tables);
  }
});