A plain deploy rebuilds all derived values at once. A staged deploy builds the new version in the background while the old one keeps serving, then switches when you say so. Nothing activates automatically.
Staged deployment API
| API | Contract |
|---|---|
StagedDeploymentState | {requestId, phase, baseRevision, baseBundleHash: string|null, bundleHash, cursor: string|null, scannedRows, builtEntries, generation: string|null, graphCursor: string|null, rebuiltRoots, error?: string|null, cleanupCursor: string|null}. Survives restarts and partition moves. Counters show work done, not a percentage. |
StagedDeploymentAction | {operation: "advance"|"collect", requestId, maxBytes?: number} or {operation: "activate"|"cancel", requestId}. Use the job's original request ID. maxBytes caps the work per call; raise it if a single row doesn't fit. |
client.stageDeployment(bundle, options?) | Start a staged job (admin token). Returns QueryResult<StagedDeploymentState>. One unfinished job per database. Keep the requestId for retries. |
client.stagedDeploymentStatus(options?) | Current job state, or null if none. Check it after a restart or an uncertain response before your next step. |
client.controlStagedDeployment(action, options?) | advance does the next page of work. activate switches bundle, indexes, aliases, authorization, keys and derived values at once. cancel abandons the job. collect deletes leftover state in pages. Aborting the HTTP request doesn't undo committed work. |
Phases, resume and failure
backfill:advancefills new indexes page by page. Code-only changes skip torebuilding.rebuilding:advancerecomputes derived values in a hidden copy. Public calls still use the old version.ready: the new version is complete and kept up to date by normal writes.active:activateswitched everything at once.canceled/collected: cancel keeps the old version.collectcleans up. Collect before starting another job. To undo an activation, deploy again.
- Only advance
backfill/rebuilding, activateready, and collectactive/canceled. - After an uncertain response, check status and confirm
requestIdandbundleHashbefore resuming. A repeatedadvancemay do the next page rather than repeat the last one. - A failed page or activation keeps earlier progress. Fix the budget and retry, or cancel and collect.
- If the new code fails while handling a normal write, the job becomes
failedwith anerror; the write itself still commits. Cancel and collect, then stage fixed code. - While a cross-group transaction is prepared, controls return
TRANSACTION_PREPARED. - After cleanup, status shows the last
collectedjob instead ofnull. - Don't retire the job's retry epoch or session before activating it; see retry retention.
Example: restart-aware lifecycle.
Page size and limits
FLOWER_DEPLOYMENT_PAGE_MS: target time per page. Default 200, at mostFLOWER_EVALUATION_TIMEOUT_MS. Set at startup. Smaller pages mean shorter write stalls; larger pages finish sooner.- Each page blocks writes to that database while it runs; reads continue. A page can overrun the target by up to one full evaluation.
maxBytesseparately caps the work per call.- Each derived value, with its dependencies, must fit in one evaluation.
- The staged copy uses extra storage and adds work to each write until you collect.
Measure rebuild time and write latency on your own workload. See the tuning guide.
Migrate stored records
Deploys never rewrite stored records. To change their shape, write migration mutations:
- Deploy code that reads both old and new shapes, and make writers emit the new shape.
- Migrate in batches with
ctx.scan(rows, {gt: afterKey, limit: 100})(omitgtat first). Save the converted rows and the next cursor in the same mutation. - Reuse the batch's request ID if a response is lost. Record completion when a page is empty.
- Check that no old records remain before deploying code that drops the old shape.
- Avoid unbounded scans and growing offsets. Index ranges (
ctx.range) can skip or repeat rows that change during the migration. - Renaming a collection or derived value doesn't move its data. Copy it explicitly.
- Protect migration methods with application authorization. The admin token doesn't protect public mutations.
- Moving a partition doesn't change record shapes.
See the migration workflow, range contracts and mutation context.