Skip to content
Strata Sync

AI agents: fetch the documentation index at llms.txt. Markdown versions are available by appending .md to any page URL, including this page's markdown.

Load strategies

Control when and how model data is fetched from the server with instant, lazy, partial, and other strategies.

Set per model via @ClientModel. Controls bootstrap timing, transfer volume, and offline availability.

Decision tree

flowchart TD
    A[Does this model need to sync with the server?]
    A -->|No| B["local"]
    A -->|Yes| C[Is the data needed on every page load?]
    C -->|Yes| D[Is the total dataset small?]
    D -->|Yes| E["instant"]
    D -->|No| F["partial"]
    C -->|No| G[Should it load automatically when accessed?]
    G -->|Yes| H["lazy"]
    G -->|No| I["explicitlyRequested"]

Strategy reference

StrategyBehaviorBest forTrade-off
instantBootstrap includes all instances; data available from first renderSmall, always-needed models (users, teams, labels)Adds to bootstrap payload size
lazyNot included in bootstrap; fetched on first access via hooks or relationship traversalModels needed only on some pages (attachments, activity feeds)First access has network latency; only accessed instances available offline
partialLoads a relevant subset at bootstrap; fetches remaining instances on demandHigh-volume models where only a slice matters (comments, notifications)Requires partial index tracking in IndexedDB
explicitlyRequestedNever auto-loaded; fetched only via client.get() or client.query()Large or sensitive models loaded on specific pages (audit logs, analytics)No data present until you request it
localNever synced; stored only in IndexedDB and the in-memory identity mapClient-only state (drafts, UI preferences, unsent messages)No server backup or cross-device access

Code examples

Set the strategy in the @ClientModel decorator.

instant

@ClientModel("User", { loadStrategy: "instant" })
export class User extends Model {
  /* ... */
}

lazy

@ClientModel("Attachment", { loadStrategy: "lazy" })
export class Attachment extends Model {
  /* ... */
}

partial

@ClientModel("Comment", {
  loadStrategy: "partial",
  partialLoadMode: "regular",
})
export class Comment extends Model {
  /* ... */
}

Partial load modes control bootstrap priority:

ModeBehavior
fullLoad the complete subset during bootstrap (highest priority)
regularLoad the subset at normal priority
lowPriorityLoad the subset after higher-priority models

explicitlyRequested

@ClientModel("AuditLog", { loadStrategy: "explicitlyRequested" })
export class AuditLog extends Model {
  /* ... */
}

local

@ClientModel("DraftMessage", { loadStrategy: "local" })
export class DraftMessage extends Model {
  /* ... */
}

Quick reference table

Model typeExampleStrategyReasoning
Core entitiesUser, Team, ProjectinstantAlways needed, small dataset
Primary work itemsTaskinstant or partialDepends on volume
Secondary contentComment, Attachmentpartial or lazyOnly needed in context
Large datasetsAuditLog, AnalyticsexplicitlyRequestedLoaded on specific pages
Sensitive dataAdminSettingsexplicitlyRequestedAccess-controlled
Client-only stateDraft, UIPreferencelocalNever synced

Performance implications

  • Bootstrap payload size: Includes all instant models and partial subsets. If slow, move large models to partial/lazy, limit via prefetchBootstrap, or enable compression.
  • Identity map memory: Every loaded instance stays in memory. Use partial for high-volume models.
  • Delta stream filtering: Deltas arrive for all accessible models but apply only for loaded instances. local models never receive deltas.

Complete example

All five strategies in a task management app:

// Always loaded -- small dataset
@ClientModel("User", { loadStrategy: "instant" })
export class User extends Model {
  /* ... */
}

// Always loaded -- core work items
@ClientModel("Task", { loadStrategy: "instant" })
export class Task extends Model {
  /* ... */
}

// Partially loaded -- fetch comments for viewed tasks
@ClientModel("Comment", {
  loadStrategy: "partial",
  partialLoadMode: "regular",
  usedForPartialIndexes: true,
})
export class Comment extends Model {
  /* ... */
}

// Only loaded when explicitly requested
@ClientModel("AuditLog", { loadStrategy: "explicitlyRequested" })
export class AuditLog extends Model {
  /* ... */
}

// Local-only draft state
@ClientModel("CommentDraft", { loadStrategy: "local" })
export class CommentDraft extends Model {
  /* ... */
}

Bootstrap flow for mixed strategies

The server streams instant models first, then partial subsets, skipping explicitlyRequested and local. The client then opens a delta stream and fetches more on demand.

sequenceDiagram
    participant Client
    participant Server

    Client->>Server: Bootstrap request
    Note over Server: Stream instant models
    Server-->>Client: All User rows
    Server-->>Client: All Task rows
    Note over Server: Stream partial models
    Server-->>Client: Comment rows (for user's sync groups)
    Note over Server: Skip explicitlyRequested and local
    Server-->>Client: Metadata (lastSyncId, groups)

    Note over Client: Seed IndexedDB + identity map
    Client->>Server: Open delta stream from lastSyncId

    Note over Client: Later, user views a task
    Client->>Server: Batch load: Comments where taskId = X
    Server-->>Client: Comment rows for task X
    Note over Client: Update partial index coverage