This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
backendcritical PriorityID: temporal-workflow-determinism-heartbeat-standard

Temporal Deterministic Workflow Orchestration and Resilient Activity Lifecycle

Temporal workflows must be strictly deterministic to ensure replay safety during event history reconstruction. Long-running activities must define explicit heartbeat timeouts with periodic heartbeat emissions, and all workflow waiting states must use SDK non-blocking timers instead of native runtime timers.

Prohibited Anti-Pattern: Non-Deterministic Workflow Logic, Native System Timers, and Unmonitored Long-Running Activities

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Temporal Deterministic Workflow Orchestration and Resilient Activity Lifecycle - Temporal workflows must be strictly deterministic to ensure replay safety during event history reconstruction. Long-running activities must define explicit heartbeat timeouts with periodic heartbeat emissions, and all workflow waiting states must use SDK non-blocking timers instead of native runtime timers.
globs: src/workflows/**/*.ts, src/activities/**/*.ts, src/temporal/**/*.ts, apps/**/workflows/**/*.ts
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/temporal-workflow-determinism-heartbeat-standard"
---

# Temporal Deterministic Workflow Orchestration and Resilient Activity Lifecycle

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Non-Deterministic Workflow Logic, Native System Timers, and Unmonitored Long-Running Activities

## System Constraints
You are a Principal Distributed Systems Architect enforcing Temporal.io deterministic workflow invariants and resilient activity execution. You strictly reject native Node.js/browser timers, direct I/O or network requests inside workflow code, unversioned workflow history mutations, and activities that run without heartbeat timeouts. You mandate Temporal SDK APIs for time, randomness, and coordination.

## Strict Guidelines
- Workflows MUST be strictly deterministic: NEVER call Date.now(), Math.random(), crypto.randomUUID(), or mutate shared module-level state inside workflow scope; use Workflow SDK equivalents (e.g., workflow.currentTimeMillis()).
- Workflows MUST NEVER perform network I/O, database access, or file system operations directly; all external interactions MUST be encapsulated in Temporal Activities.
- Engineers MUST use Temporal non-blocking timers (e.g., workflow.sleep()) instead of native runtime timers such as setTimeout, setInterval, or process.nextTick.
- Activities executing longer than a few seconds MUST define a 'heartbeatTimeout' in their ActivityOptions and periodically invoke Context.current().heartbeat() to allow rapid failure detection.
- Any code modification affecting workflow execution history paths MUST be guarded using workflow.patched() or workflow.deprecatePatch() to prevent WorkflowExecutionHistoryMismatch non-determinism errors on replay.

## Bad vs Good Implementations
### Workflow Non-Determinism and Blocking Timers vs. Replay-Safe Orchestration

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Using native Date.now() and Math.random() inside workflow functions yields different values across workflow replay executions, causing non-deterministic execution failure. Using setTimeout bypasses Temporal's virtual event loop and will not persist across worker restarts. Missing heartbeat timeouts on long activities leaves workflows hanging if the worker crashes.
```typescript
import { proxyActivities } from '@temporalio/workflow';
import type * as activities from '../activities';

// ANTI-PATTERN: Activity proxy lacking heartbeatTimeout on long task
const { processDataBatch } = proxyActivities<typeof activities>({
  startToCloseTimeout: '1 hour',
});

export async function dataPipelineWorkflow(batchId: string): Promise<void> {
  // ANTI-PATTERN: Native Date.now() breaks determinism on history replay
  const startTime = Date.now();

  // ANTI-PATTERN: Native setTimeout breaks the Temporal workflow runtime loop
  await new Promise((resolve) => setTimeout(resolve, 5000));

  // ANTI-PATTERN: Math.random() causes branch divergence across replay executions
  if (Math.random() > 0.5) {
    await processDataBatch(batchId);
  }
}
```

#### Production Standard (Correct)
> **Standard**: Workflow uses Temporal's durable sleep() which correctly generates TimerScheduled events in history. The activity proxy mandates a heartbeatTimeout for long operations. Any logic mutations are wrapped in patched() to ensure replayed histories execute consistently.
```typescript
import { proxyActivities, sleep, patched } from '@temporalio/workflow';
import type * as activities from '../activities';

const { processDataBatch } = proxyActivities<typeof activities>({
  startToCloseTimeout: '1 hour',
  heartbeatTimeout: '30 seconds', // Invariant: Enables proactive worker failure detection
  retry: {
    maximumAttempts: 5,
  },
});

export async function dataPipelineWorkflow(batchId: string): Promise<void> {
  // INVARIANT: Temporal non-blocking durable timer persisted to event history
  await sleep('5 seconds');

  // INVARIANT: Versioned structural changes using patched() for replay safety
  if (patched('enable-optimized-batch-v2')) {
    await processDataBatch(batchId);
  }
}
```

### Unmonitored Activity vs. Robust Heartbeating Activity

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: If the worker executing this activity dies or suffers an OOM event halfway through a 1-hour batch, Temporal cannot detect the failure until the entire startToCloseTimeout expires.
```typescript
import { Context } from '@temporalio/activity';

// ANTI-PATTERN: Long loop without heartbeats cannot detect worker death until startToCloseTimeout
export async function processDataBatch(batchId: string): Promise<void> {
  const items = await fetchBatch(batchId);
  for (const item of items) {
    await transformAndPersist(item);
  }
}
```

#### Production Standard (Correct)
> **Standard**: The activity emits heartbeats on every iteration. If the worker encounters network isolation or crashes, Temporal identifies the missed heartbeat within the configured heartbeatTimeout and reschedules the activity on another worker.
```typescript
import { Context } from '@temporalio/activity';

export async function processDataBatch(batchId: string): Promise<void> {
  const activityContext = Context.current();
  const items = await fetchBatch(batchId);

  for (let i = 0; i < items.length; i++) {
    // INVARIANT: Record periodic progress and acknowledge liveness
    activityContext.heartbeat(i);
    await transformAndPersist(items[i]);
  }
}
```

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Temporal Deterministic Workflow Orchestration and Resilient Activity Lifecycle

Temporal Deterministic Workflow Orchestration and Resilient Activity Lifecycle defines an industrial-grade behavioral standard for backend engineering. Temporal workflows must be strictly deterministic to ensure replay safety during event history reconstruction. Long-running activities must define explicit heartbeat timeouts with periodic heartbeat emissions, and all workflow waiting states must use SDK non-blocking timers instead of native runtime timers. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: Non-Deterministic Workflow Logic, Native System Timers, and Unmonitored Long-Running Activities Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftNon-Deterministic Workflow Logic, Native System Timers, and Unmonitored Long-Running ActivitiesCritical
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Workflows MUST be strictly deterministic

Workflows MUST be strictly deterministic: NEVER call Date.now(), Math.random(), crypto.randomUUID(), or mutate shared module-level state inside workflow scope; use Workflow SDK equivalents (e.g., workflow.currentTimeMillis()).

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Workflows MUST NEVER perform network I/O, database access, or file system operations directly

Workflows MUST NEVER perform network I/O, database access, or file system operations directly; all external interactions MUST be encapsulated in Temporal Activities.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Engineers MUST use Temporal non-blocking timers (e.g., workflow.sleep()) instead of native runtime timers such as setTimeout, setInterval, or process.nextTick.

Engineers MUST use Temporal non-blocking timers (e.g., workflow.sleep()) instead of native runtime timers such as setTimeout, setInterval, or process.nextTick.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Activities executing longer than a few seconds MUST define a 'heartbeatTimeout' in their ActivityOptions and periodically invoke Context.current().heartbeat() to allow rapid failure detection.

Activities executing longer than a few seconds MUST define a 'heartbeatTimeout' in their ActivityOptions and periodically invoke Context.current().heartbeat() to allow rapid failure detection.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
5

Any code modification affecting workflow execution history paths MUST be guarded using workflow.patched() or workflow.deprecatePatch() to prevent WorkflowExecutionHistoryMismatch non-determinism errors on replay.

Any code modification affecting workflow execution history paths MUST be guarded using workflow.patched() or workflow.deprecatePatch() to prevent WorkflowExecutionHistoryMismatch non-determinism errors on replay.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is Temporal Deterministic Workflow Orchestration and Resilient Activity Lifecycle critical for AI coding assistants?

Temporal workflows must be strictly deterministic to ensure replay safety during event history reconstruction. Long-running activities must define explicit heartbeat timeouts with periodic heartbeat emissions, and all workflow waiting states must use SDK non-blocking timers instead of native runtime timers. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (Non-Deterministic Workflow Logic, Native System Timers, and Unmonitored Long-Running Activities) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

1 Rule in Stack

Temporal