pgTable/API Reference/Persistence config
API ReferenceOptions

persist

The full surface of the persist option on usePgTable. Mode plus optional knobs for versioning, TTL, lifecycle callbacks, and restore control. All of it is mount-time configuration — pgTable captures the resolved config when it creates the store entry.

Shape

One required field (mode); the rest are optional. Schema versioning and the lifecycle callbacks come together — versioning gives you the signal, onPersistSchemaMismatch gives you the handler.

TSshape.ts
type PgTablePersistConfig = {
mode:           'none' | 'memory' | 'session' | 'local'    // required
expireAfter?:   number                                     // ms; payload expires this long after the last write
schemaVersion?: number                                     // default: 1
autoRestore?:   boolean                                    // default: true (only meaningful for 'session' | 'local')

// Lifecycle hooks — fired during persist / restore.
onPersist?:               (payload, ctx) => void
onPersistError?:          (error, ctx) => void
onBeforeRestore?:         (payload, ctx) => { shouldRestore: boolean }
onPersistSchemaMismatch?: (args) => { shouldRestore: boolean; payload?: PgTableSerialisedPayload }
}

Mode

Four modes. 'none' is the default — explicit opt-in keeps the contract small. 'memory' survives unmount without touching webstorage. 'session' and 'local' are write-through to sessionStorage / localStorage on every commit.

TSXcharacters-table.tsx
// 'none'    (default) — no persistence; store entry is dropped on hook unmount.
// 'memory'            — entry survives unmount; nothing is written to webstorage.
// 'session'           — write-through to sessionStorage on every commit.
// 'local'             — write-through to localStorage   on every commit.

usePgTable(charactersColumns, charactersState, {
pgTableId: 'characters',
persist:   { mode: 'local' },
})

schemaVersion + onPersistSchemaMismatch

Bump schemaVersion whenever you change the shape of columns or state in an incompatible way. On restore, pgTable compares against the persisted version and — if they differ — calls your handler. Return { shouldRestore: true, payload } to migrate; return { shouldRestore: false } (or omit the handler) to drop the old payload.

TSXcharacters-table.tsx
// Bump schemaVersion whenever the shape of data/state changes in an
// incompatible way. Persisted payloads carry the version they were written
// under; on restore, mismatches go through onPersistSchemaMismatch.

usePgTable(charactersColumns, charactersState, {
pgTableId: 'characters',
persist: {
  mode: 'local',
  schemaVersion: 3,
  onPersistSchemaMismatch: ({ persistedVersion, persistedPayload }) => {
    if (persistedVersion === 2) {
      return { shouldRestore: true, payload: migrateV2toV3(persistedPayload) }
    }
    return { shouldRestore: false }      // default behaviour: drop the old payload
  },
},
})

expireAfter

Time-to-live, in milliseconds, measured from the last successful write. The serialised payload carries an expiresAt timestamp; restores past that timestamp delete the payload before any subscriber sees it.

TSXcharacters-table.tsx
// expireAfter is milliseconds from the last write. Expired payloads are
// deleted on the next restore attempt, before any subscriber sees them.

usePgTable(charactersColumns, charactersState, {
pgTableId: 'characters',
persist: {
  mode: 'local',
  expireAfter: 1000 * 60 * 60 * 24 * 7,   // 7 days
},
})

onPersist / onPersistError

onPersist fires after every successful serialise, with the full payload and { pgTableId }. onPersistError fires when webstorage throws (quota, disabled, denied) — pgTable surfaces the error but does not retry.

TSXcharacters-table.tsx
// onPersist fires after a successful write. ctx is { pgTableId }.
// onPersistError fires when the webstorage write throws (quota exceeded,
// disabled storage, etc.) — pgTable surfaces it but does not retry.

usePgTable(charactersColumns, charactersState, {
pgTableId: 'characters',
persist: {
  mode: 'local',
  onPersist:      (payload, ctx) => analytics.track('table.persist', { id: ctx.pgTableId, at: payload.lastUpdatedAt }),
  onPersistError: (error,   ctx) => console.warn('persist failed', ctx.pgTableId, error),
},
})

onBeforeRestore

A per-mount veto. The handler receives the persisted payload and returns { shouldRestore: boolean }. Use it to gate restore on user/tenant identity, feature flags, or staleness checks beyond the simple expireAfter rule. A cancelled restore drops the payload before any subscriber sees it.

TSXcharacters-table.tsx
// onBeforeRestore lets you veto a restore before it lands. Use it for
// per-user predicates (e.g. discard another user's data after a session
// switch). Returning { shouldRestore: false } drops the payload.

usePgTable(charactersColumns, charactersState, {
pgTableId: 'characters',
persist: {
  mode: 'local',
  onBeforeRestore: (payload) => ({
    shouldRestore: payload.state.userId === currentUserId,
  }),
},
})

autoRestore

Defaults to true when mode is 'session' or 'local'. Set it to false to disable the on-mount restore without disabling writes — useful when restore should be deferred until you have fetched a remote source of truth and confirmed the local payload is the right baseline.

TSXcharacters-table.tsx
// autoRestore defaults to true for 'session'/'local'. Set it to false when
// you want to control restore timing manually — pgTable will write but not
// auto-read on mount, and you can decide how to reconcile with a remote
// source of truth yourself.

usePgTable(charactersColumns, charactersState, {
pgTableId: 'characters',
persist:   { mode: 'local', autoRestore: false },
})