Fix: How to Terminate Temporal Workflows Using tctl Command
The Problem
You have open Temporal workflows that are stuck, runaway, or need cleaning up — and you need to terminate them fast without clicking through the UI one by one.
Maybe your staging namespace is flooded with test runs, or a bad deploy triggered
hundreds of ScheduledAdExecutionWorkflow instances that won't stop.
What You'll See

Here, the temporal-admintools pod is the one we will shell into in order to
execute the tctl commands for listing and terminating workflows.
Root Cause
Temporal workflows stay open indefinitely until they:
- Complete naturally
- Are cancelled by the application
- Are terminated manually
If your worker crashed mid-execution, a deploy went wrong, or schedule logic had a bug — workflows can pile up with no way out except manual termination.
The Fix
You can change the grep filter based on your requirement. The following commands terminate 10 or 100 open workflows matching the specified workflow type, and the limit can be modified as needed.
# Terminate exactly 10 workflows
tctl --namespace default workflow list --open --pagesize 10 | \
grep "ScheduledAdExecutionWorkflow" | \
awk -F'|' '{print $2}' | \
tr -d ' ' | \
grep -v "^$" | \
head -10 | \
while read wid; do
echo "Terminating: $wid"
tctl --namespace default workflow terminate \
--workflow_id "$wid" \
--reason "Cleanup test"
done
# Terminate exactly 100 workflows
tctl --namespace default workflow list --open --pagesize 100 | \
grep "ScheduledAdExecutionWorkflow" | \
awk -F'|' '{print $2}' | \
tr -d ' ' | \
grep -v "^$" | \
head -100 | \
while read wid; do
echo "Terminating: $wid"
tctl --namespace default workflow terminate \
--workflow_id "$wid" \
--reason "Cleanup test"
done
Variations
Terminate ALL matching workflows (no limit):
tctl --namespace default workflow list --open --pagesize 100 | \
grep "ScheduledAdExecutionWorkflow" | \
awk -F'|' '{print $2}' | \
tr -d ' ' | \
grep -v "^$" | \
while read wid; do
echo "Terminating: $wid"
tctl --namespace default workflow terminate \
--workflow_id "$wid" \
--reason "Bulk cleanup"
done
Dry run first — just print IDs without terminating:
tctl --namespace default workflow list --open --pagesize 50 | \
grep "ScheduledAdExecutionWorkflow" | \
awk -F'|' '{print $2}' | \
tr -d ' ' | \
grep -v "^$"
Always do this first to confirm you're targeting the right workflows.
Target a specific namespace (not default):
tctl --namespace your-namespace-here workflow list --open --pagesize 10 | \
grep "YourWorkflowType" | \
awk -F'|' '{print $2}' | \
tr -d ' ' | \
grep -v "^$" | \
while read wid; do
tctl --namespace your-namespace-here workflow terminate \
--workflow_id "$wid" \
--reason "Cleanup"
done
Pro Tips
Always dry run first — pipe to echo before using terminate in production
Use terminate when the workflow is stuck and cancel isn't responding.
Comments
0Got the same issue? Fixed it differently? Share below.
Leave a comment