Skip to main content

Runbooks

Operational procedures for running the engine.

Dispatcher pressure

Symptoms: dispatcher_errors_total rising, dispatcher_events_dispatched_total stalled, or events accumulating in dispatch_outbox.

Diagnose

What normal looks like

The dispatcher backs off exponentially on consecutive errors β€” poll_ms * 2^n, capped at 30 seconds β€” and resets to poll_ms on the first successful iteration.

DLQ remediation

Tuning

Worker scaling

Health server on WORKER_HEALTH_PORT (default 9090): Check task queue depth:
If pending tasks grow while workers are healthy, scale up replicas.
RLS session variables. When the worker queries the database directly, the control plane sets SET app.tenant_id = '<uuid>' for row-level security. If RLS is enabled and the session variable is not set, queries return empty results rather than erroring β€” which reads like missing data, not a misconfiguration. Confirm CONTROL_PLANE_AUTH_MODE=required in production.

Worker rollback

Rolling the worker image back is not unconditionally safe. The worker has no build-id versioning, so old and new workflow code cannot serve histories side by side. CI never rolls the worker back automatically for this reason.

Decision tree

1. Has the new worker taken any workflow tasks?
  • No β†’ kubectl rollout undo is safe. Done.
  • Yes β†’ continue.
2. Did the new code add or remove ctx.patched() markers, or change any workflow command sequence? Check the deploy diff for _PATCH_ID, ctx.patched, start_activity, ctx.timer.
  • No β€” activity-internals only β†’ undo is safe. Histories recorded under the new image replay identically on the old one.
  • Yes β†’ any in-flight execution that advanced past a new marker will fail replay on the old code. Choose one:
Do not pick β€œaccept failures” silently. Every stuck run pins a ticket.
For the pause-then-undo path, find affected runs:
Runs that fail with NonDeterminismError after the undo must be terminated and re-submitted from the API. They are idempotent to re-run up to their last committed mutation, thanks to the ledger. 3. Afterwards, always: confirm kubectl rollout status is healthy, check worker :9090/readyz, and watch that temporal workflow count --query 'ExecutionStatus="Running"' returns to baseline.
The proper fix is build-id pinning via WorkerVersioningStrategy, which would make undo safe by construction. It is not yet implemented.

Migrations

Migrations run via the migrate binary with baseline detection. Follow expand/contract for rolling deploys β€” add the new column or table first, deploy code that writes both, backfill, then remove the old shape in a later migration. A migration that drops or renames in one step will break the pods still running the previous image. Concurrent index migrations are marked -- migrate:no-transaction, since CREATE INDEX CONCURRENTLY cannot run inside a transaction. A failed concurrent-index migration leaves an invalid index that must be dropped before retrying.

Other procedures

The repo’s runbooks also cover brand secret rotation (including rotation without restart and verifying secret resolvability), rate limiting (global and per-tenant, with monitoring and adjustment), circuit breaker and connector recovery (health checks, failure states, recovery steps), and brand onboarding (validate a manifest, onboard into shadow, activate after validation).