There are two separate compatibility problems. The workflow engine has to replay or resume the old run under code that understands its history. And the business has to know whether a person approved the action that will actually happen. Passing the first test does not pass the second.

For the workflow code, I would inventory active runs by version and waiting step. New runs start on a new version. Old runs stay on code that can replay their histories, using worker versioning or an explicit version branch. Temporal's Java documentation is a concrete example: changing the command sequence seen during replay can cause a nondeterminism error. Its current Worker Versioning guidance recommends versioned deployments and allows pinned workflow executions to stay on the version where they started. That is a useful mechanism, but we still own the migration and the operational life of those old workers.

I would not deploy new code over all workers and hope sleeping workflows wake up cleanly. Before traffic moves, replay representative histories from every active state, including runs with an approval request sent but no response, runs with a tool attempt whose result is unknown, and runs with old serialized payloads. Keep the old tool and data contracts available for those histories or provide an explicit adapter. Version the action schema as well as the workflow code.

Now the approval. Suppose version one asked a person to approve a refund of 500 for payment P9831. Version two changes the step to a credit of 500 against an account balance. The word “approve” still appears in the history, but it authorized a different effect. I would bind approval to a versioned action fingerprint: subject, action type, target, amount, currency, constraints, and any policy facts the approver saw. At execution time, compare the proposed effect to that fingerprint and check current authorization. If it changed materially, request a new approval. Do not migrate the approval flag and infer consent.

Keeping old workers forever is not free. I would set a retirement plan: count old runs, track the longest waiting age, keep compatible dependencies alive, and migrate only at a safe boundary. A migration may create a new workflow with a linked run ID and versioned state, or continue from an explicit transition. It must carry the durable operation ledger for actions already attempted. Otherwise the new run can repeat a side effect because it no longer sees the old step as complete. The migration event should record exactly how old state mapped to new state and which approvals became invalid.

The first rollout is small. Start new workflows on version two, run the same scenario set against both versions, and canary a small set of resumptions where no effect has yet been attempted. Compare legal state transitions, approval handling, tool behavior, and recovery after worker failure. I would have a control that can pause the affected action across both versions. A rollback of routing new runs to version one does not automatically undo a version two action already executed.

The interviewer then says version one contains a security bug. “You cannot keep old workers alive.” That overrides the comfortable pinning plan. I would block the unsafe action in a shared tool or policy boundary immediately so sleeping runs cannot trigger it when they wake. Then patch old behavior compatibly or migrate the affected runs in batches with explicit state conversion and replay tests. If I cannot prove an old approval still applies, the run returns to approval. Availability for these runs may temporarily fall. Silent action under a changed meaning is worse.

They push again: “Why not update the approval message in place?” Because the person approved the facts shown at that time. Updating a display string later cannot change the historical decision. The new action can be presented as a new proposal with the old approval and reason attached as context. It still needs a current decision if the effect changed.

The number 200,000 changes the operating plan, not the invariant. We need a version inventory, worker capacity for old and new populations, alerts for stuck versions, a way to pause or resume cohorts, and a deadline for support of each version. But the core rule is small: old history is interpreted by compatible code, and an old approval is used only for the exact action it authorized.

Temporal's Worker Versioning and Java workflow versioning document the replay and deployment mechanisms. Approval fingerprints and migration policy here are the proposed application design.