Skip to content
Thyme Docs

Persist State Across Runs

Persistent state belongs in ctx.storage. Each executable gets its own JSON object, separate from your local storage.json and from other executables using the same release.

Record an observation without a transaction

import { defineTask, z } from '@thyme-labs/sdk'
 
export default defineTask({
  schema: z.object({}),
  async run(ctx) {
    const block = await ctx.client.getBlockNumber()
    ctx.storage.lastObservedBlock = block.toString()
    ctx.storage.checks = Number(ctx.storage.checks ?? 0) + 1
    return { canExec: false, message: `Observed block ${block}` }
  },
})

The block number is stored as a decimal string because JSON does not support BigInt. With a successful skipped cloud run, the updated state is persisted.

Record confirmed work in onSuccess

For a task returning a transaction, use onSuccess for a checkpoint that means the action confirmed:

onSuccess(ctx, tx) {
  ctx.storage.lastConfirmedTransaction = tx.txHash
  ctx.storage.lastConfirmedBlock = String(tx.blockNumber)
}

A skipped run, a failed submission, and an unresolved receipt are different outcomes. onFail starts from the pre-run stored snapshot; task mutations from a failed submission are not a reliable confirmed checkpoint.

Read on-chain state before deciding to repeat an asset-moving action. Storage can fail to commit after a transaction has confirmed, so a stored checkpoint alone is not proof that nothing happened.

Inspect local behavior

thyme run my-task --persist
thyme run my-task --persist

Inspect storage.json between runs. --simulate-callbacks helps exercise callback branches locally; cloud simulation deliberately discards all storage changes.

Operate cloud state

Read and edit the executable's storage from its detail page or authenticated management operations. Fetch the current version before writes. If another run changed it, reconcile the new state instead of forcing an old snapshot over it.

Keep cursors and counters small. The runtime cap is 100 MiB, while management storage transport is limited to 16 MiB. Never put credentials in state. See storage semantics and management commands.