Temporal Interview Questions: Workflow Replay, Activity Retries, and Safe Changes

Practice Temporal interview questions on Workflow replay, Activity retries, idempotency, timeouts, and safe changes with tested Python patching examples.

Author: PracHub

Published: 9/8/2026

Temporal Interview Questions: Workflow Replay, Activity Retries, and Safe Changes

September 8, 2026

Quick Overview

Prepare for Temporal interviews with Workflow replay, Activity retries, payment idempotency, timeout boundaries, and safe code changes. Follow a payment failure timeline and tested Python SDK replay examples to distinguish durable orchestration from external effects and deployment compatibility.

Backend EngineerFree

A payment provider accepts a charge. Before your Worker records the result in Temporal, the response disappears. The Activity runs again. Does the customer get charged twice? Now deploy a Workflow change that inserts a delay before charging: can an execution started yesterday still make progress?

These Temporal interview questions connect three separate responsibilities: replay reconstructs Workflow state, idempotency protects external effects, and versioning keeps deployments compatible with existing histories. Being able to explain one does not establish the other two.

Evidence boundary: This is preparation for using the Temporal workflow engine, not a guide to interviewing at Temporal Technologies. Official facts come from documentation checked September 8, 2026. The questions, payment scenario, and recommendations are original PracHub practice; no candidate reports are used. Code and replay observations use the Temporal Python SDK 1.32.0, with a local time-skipping test server and a simulated payment provider.

Temporal interview preparation separates replay state, retry-safe side effects, and compatible code changes

What actually happens during Workflow replay?

Practice question: A Worker loses its in-memory state after an Activity completes. How does another Worker continue without charging the customer again?

Official fact: Temporal records Workflow progress in an Event History. A Worker can replay Workflow code against that history to reconstruct execution state. Commands produced by the code must be compatible with recorded events. This is not recovery of a frozen operating-system process or arbitrary heap snapshot. See Event History and Workflow Definition.

For the wider queue-and-worker design, compare PracHub’s job scheduler guide. The Temporal-specific follow-up is narrower: explain which recorded event satisfies the command that the new Worker emits.

Separate the orchestration from the external operation. The Workflow schedules charge; the Activity implementation contacts the provider. During replay, a recorded Activity completion supplies its result to Workflow code. Replay does not invoke that completed Activity’s implementation again merely because the Workflow function runs again.

That distinction also explains where nondeterminism belongs. Official fact: Activities can perform external operations and be nondeterministic; Temporal recommends making them idempotent. Workflow code must preserve replay compatibility. See Activities.

Preparation inference: Put the provider request in an Activity, pass its receipt back to the Workflow, and keep subsequent decisions based on recorded inputs and results. Use SDK-supported Workflow time, randomness, and waiting APIs where appropriate. Do not read a live feature flag or call a database directly inside replaying code and assume the answer will match yesterday’s.

Can an Activity retry duplicate a payment?

Practice question: The provider committed the charge, but Temporal has no completion result. What should the second attempt do?

The following is an original failure analysis. “Unknown” describes what the caller knows; it does not mean that no money moved.

StepProvider stateTemporal’s knowledgeRequired application behavior
Attempt 1 sends payment-42Request receivedActivity is runningReuse a stable business-operation key
Provider commitsOne charge existsCompletion not yet recordedPreserve the provider receipt
Response or Worker is lostCharge still existsOutcome is uncertainAvoid treating timeout as rejection
Attempt 2 sends payment-42Same logical requestRetry is runningProvider returns the original result
Completion is recordedStill one chargeReceipt is in historyWorkflow can advance

Design inference: Generate the payment operation ID before attempts diverge. Reuse it across retries, together with the same amount, currency, and destination. An attempt number is useful for observability but makes a poor idempotency key: a new key can authorize a new effect.

The provider must actually enforce the key. An in-memory set in your Worker is insufficient across crashes, and “check our database, then charge” leaves a race between the check and the remote operation. Ask about atomic key enforcement, conflicting payloads, retention, and lookup by operation ID. If the provider cannot establish the outcome, route the payment to reconciliation instead of issuing a fresh charge blindly.

This is why “Temporal gives exactly-once payments” is an incomplete answer. Durable orchestration cannot make an arbitrary external endpoint transactional. Likewise, exhausting retries does not prove the first attempt failed to commit.

Cancellation needs the same precision. A cancellation request is not a refund. If a charge already exists, reversing it is another business operation with its own identity, retry policy, and audit trail. Decide which state transitions allow cancellation before presenting compensation as a universal undo button.

Which timeout limits retries?

Practice question: Your Activity allows 10 seconds per attempt. Does it necessarily finish within 10 seconds overall?

Official fact: Start-To-Close bounds one attempt. Schedule-To-Close bounds the whole Activity Execution, including retries. Schedule-To-Start concerns waiting for a Worker to begin an attempt. Heartbeat timeouts detect a lack of progress reports from long-running Activities. These limits answer different questions; see Detecting Activity failures.

Official fact: Activities have a default Retry Policy; Workflow Executions do not. Workflow Task retries are a separate mechanism from retrying an entire Workflow Execution. See Retry Policies. A nondeterminism incident should not be described as “the payment Workflow starts over until it works.”

Preparation inference: For the payment exercise, define an end-to-end deadline first, then allocate attempt time and backoff inside it. Distinguish a transient network error from a durable business refusal. Do not repeatedly retry a declined payment as if the network were unavailable. Python’s error-handling guide explains retry policies and non-retryable application errors.

For a concrete design review, suppose the product allows 30 seconds to obtain an automatic outcome. You propose a 10-second Start-To-Close timeout, a 30-second Schedule-To-Close timeout, and at most three attempts. Explain that three full attempts are not guaranteed to fit: queueing and backoff consume the same overall budget. When that budget expires, the customer-facing state should reflect the evidence available. If the provider outcome remains unknown, “pending reconciliation” is more accurate than “not charged.” These numbers are an original discussion scenario, not recommended Temporal defaults. The acceptance check is that neither repeated delivery nor the deadline transition creates a second payment operation.

Also ask what happens to the original Activity code after a timeout. A timeout does not physically kill a remote request or guarantee the old attempt has stopped. Two attempts may overlap, which makes provider-side idempotency important even when attempts usually run sequentially.

For a long export or migration Activity, heartbeat details can support a resume checkpoint. The checkpoint must describe committed progress. Reporting “page 100 done” before its output is durable can skip work after a retry. Heartbeating helps recovery; it does not replace the destination’s correctness contract.

Which Workflow changes break old histories?

Practice question: Version A schedules charge immediately. Version B first starts a one-second timer. Both complete successfully when started fresh. Is deployment safe?

The original trace below omits Workflow Task bookkeeping and shows only the events relevant to this comparison:

History or codeFirst relevant operationReplay result against the old history
Existing historyActivityTaskScheduled: chargeThis is the compatibility constraint
Original codeSchedule chargeMatches
New unguarded delayStart timerConflicts with the recorded Activity scheduling
Patched code, old history without markerSkip the new delay; schedule chargeMatches
Patched code, fresh executionRecord patch choice; start timerCreates a different, internally consistent history

Official fact: Reordering, adding, or removing command-producing Workflow operations can cause nondeterminism. Some changes, such as certain Activity arguments or nonzero timer durations, can be replay-compatible, so “every code edit needs a patch” is also wrong. Consult the Workflow Definition constraints rather than judging compatibility by line count.

Design inference: Review both command compatibility and business meaning. Changing the amount supplied to an already-recorded charge does not retroactively change the provider’s earlier payment. A passing replay check cannot establish that the intended business migration happened.

An old history expects charge scheduling; an unguarded timer conflicts, while a patch preserves the old branch and adds the timer for fresh execution

How do you patch the delay safely in Python?

This tested Workflow definition assumes an Activity named charge is registered by the Worker. It illustrates the compatibility branch; it is not a complete payment application.

from datetime import timedelta
from temporalio import workflow

@workflow.defn(name="Payment")
class Patched:
    @workflow.run
    async def run(self, payment_id: str) -> str:
        if workflow.patched("delay-before-charge-v1"):
            await workflow.sleep(1)
        return await workflow.execute_activity(
            "charge",
            payment_id,
            start_to_close_timeout=timedelta(seconds=5),
        )

Official fact: Python’s patched() records a patch marker when taking the new path in non-replay execution. During replay without that marker, it can preserve the old path. Marker position matters; patching is not an ordinary remotely toggled feature flag. See Patching.

Be precise about “old Workflow.” An execution that already passed this decision point under the old code needs the compatible branch. An execution started earlier but reaching a genuinely new point after replay can behave differently. Inspect its history rather than classifying all executions solely by start date.

Official fact: Patch removal is staged: introduce the patch, later deprecate it, then remove the compatibility machinery when the relevant histories no longer require it. Follow the Python versioning lifecycle, including retention considerations. Do not delete the old branch immediately after a successful canary.

Official fact: Worker Versioning also provides Pinned and Auto-Upgrade behaviors. Pinned Workflows stay on a Worker Deployment Version unless explicitly moved; Auto-Upgrade Workflows require replay-safe changes as they move. See Worker Versioning.

Preparation inference: Explain whether you are keeping old Workers available or making the new code handle old histories. Routing and patching solve related deployment problems, but they are not interchangeable names for the same mechanism. Include capacity for pinned executions and a rollback plan that can handle histories already produced by the new release.

What did the replay test prove?

We ran an original local test using Python SDK 1.32.0 and its time-skipping test environment. A simulated provider stored one receipt per payment ID. The first Activity call stored a receipt and then raised a retryable error to model a lost response. The next attempt returned the stored receipt.

Observed results: two Activity attempts produced one simulated receipt. Replaying the completed history with the original definition passed. Replaying it with the patched definition passed. The unguarded timer failed with a nondeterminism error at event 5, where the history contained ActivityTaskScheduled. A fresh patched execution and replay of its new history also passed. Replay invoked no Activity implementation.

This is an SDK integration test, not evidence that a real provider honors idempotency or that a production Worker crash was reproduced. The test server also warned that it did not advertise a heartbeat-detail capability; this test did not exercise heartbeat persistence.

For your own exercise, export representative histories and use the SDK Replayer described in Python testing. Include executions before and after the changed decision, both patch branches, and relevant signal or cancellation paths. A fresh-run unit test alone misses the old-history compatibility problem.

Debugging inference: If an execution stalls after deployment, first identify whether it is waiting for an Activity, retrying a Workflow Task, or awaiting a timer or message. Compare the expected history event with the new command at the failure point. For uncertain payments, correlate the operation ID with provider records as well. History explains orchestration progress; provider evidence establishes the external effect.

Practice the surrounding backend decisions

These verified PracHub questions exercise adjacent skills, not reported Temporal-specific interview rounds. Add the indicated Temporal follow-up to make each answer concrete.

Practice questionTemporal follow-up
Design a Reliable Payment Processing SystemTrace a committed charge whose Activity completion is missing.
Design scheduled payments and cancellationSeparate cancellation intent from compensation after execution.
Design an API for pay computation with retriesDefine operation identity independently of attempt identity.
Design a CI/CD Task SchedulerExplain which deployment version receives existing executions.
Design a Task Scheduler and ExecutorDistinguish durable scheduling from exactly-once external effects.

Continue with the Backend Engineer question collection. Before moving on, explain the failure timeline aloud, predict the replay matrix, and state which evidence would justify retiring the old Worker or removing a patch.

Sources and Further Reading


Comments (0)