Skip to content
FIX/DIYAI

Field notes

How to Kill a Runaway Zapier or Make Loop Before It Drains Your Card

Oct 7, 2026 · Alan Woodyard · 6 min

Turn the Zap off, open a circuit breaker, move polling from 1 minute to 15, and dedupe on a stable key before the next retry hits your card.

A one-minute poll that writes back into the same record is a billing loop with a CRM attached. Zapier counts the trigger as a task even when a later filter stops the Zap. Make will cheerfully retry every incomplete execution the moment you switch the scenario back on. Do the shutoff in this order. Skipping to “tweak the filter” while the schedule is still live is how the card keeps declining.

1. Freeze the live run before you edit anything

  1. Zapier: open the Zap and turn it Off. Off is the switch on the Zap list and in the editor. Pause is not enough if a replay queue is still draining.
  2. Open Zap history and note the timestamp of the first spike. That timestamp is your corruption window.
  3. If Autoreplay is enabled on the Zap, turn it off. Failed runs will otherwise re-enter the same records after you think you stopped it.
  4. Make: open the scenario and turn scheduling off. Then open the incomplete-executions queue and delete or resolve those runs. Turning the scenario on later replays that queue.
  5. If another app is still calling your webhook, disable that subscription too. Otherwise the queue refills the moment the Zap comes back.

Export the CRM records modified after the spike timestamp before you change a single field. You want a snapshot, not a mass delete. Mass delete is how a loop becomes unrecoverable.

2. Name the loop before you rebuild it

There are two different fires, and they need different fixes.

  • Write-back loop. The Zap updates a contact, the CRM emits “contact updated,” and the same Zap runs again. Task count climbs even when no human touched the record.
  • Polling flood. The trigger is not instant. On a Team or Company plan Zapier polls as fast as every minute. Every poll is a task, including polls that find nothing new. A filter after the trigger does not refund that task.

If mail is part of the blast radius, pause the send step now. Do not “warm” the domain by sending more. Pull bounce and complaint counts from the ESP before you restart anything. A loop that mailed hundreds of people is a reputation incident, not a formatting tweak.

3. Put a circuit breaker in front of the write

The breaker does not make polling free. It stops the downstream write, caps the damage, and pages you when the ceiling trips.

Zapier, using Storage by Zapier:

  1. After the trigger, add Storage by Zapier → Increment Value. Key: breaker:<zap-name>:count.
  2. Add Paths.
  3. Path A, if the stored count is greater than 25: send yourself email or Slack that says the breaker is open. Do not update the CRM, do not send customer mail, do not call the other app.
  4. Path B, if the count is 25 or less: your existing write steps, and nothing else.
  5. Reset is manual. After the logic is fixed, set that storage value back to 0, or run a separate daily Zap whose only job is to zero the key. Do not reset it inside the same path that does the write, or a loop will zero itself and keep going.

Make, using a Data store:

  1. First module: get the record breaker:<scenario-id>.
  2. If windowStart is older than 60 minutes, set count to 0 and windowStart to now.
  3. If count is already at 25, stop the scenario and send the alert. Use a Break directive or simply end the route. Do not add an error handler that restarts the scenario.
  4. Only increment count after the downstream write succeeds.
  5. In scenario settings, cap max cycles. An uncapped cycle plus a router that feeds itself is the Make version of this same fire.

Pick a ceiling you can survive, not a ceiling that matches your hopes. Twenty-five writes an hour is enough to do real work and small enough to notice.

4. Move the poll from 1 minute to 15 minutes

You usually cannot type “15” into a Zapier polling trigger. The interval is the plan: free is about 15 minutes, professional about 2, team and company about 1. Fighting the plan with a filter still spends the trigger task.

Do this instead:

  1. Prefer an instant trigger (a webhook or the app’s native “new event” hook) when the source has one. Instant triggers do not poll.
  2. If you must poll on a schedule you control, replace the fast app trigger with Schedule by Zapier set to every 15 minutes, then a Search step for records changed since the last run. You spend one scheduled task plus the search, not 1,440 empty polls a day.
  3. Make: open the scenario clock and set the interval to 15 minutes. This one is a real dropdown. Also set a limit on how many bundles one cycle may process so a single wake-up cannot pull ten thousand rows.
  4. Store the last successful watermark (last_seen_updated_at) and search strictly after it. Without a watermark, every 15-minute run re-reads the same page.

Fifteen minutes is the right latency for CRM hygiene. It is the wrong latency for a fraud lock or a payment failure. If the workflow is actually time-critical, keep it instant and spend the effort on the breaker and the dedupe key instead of slowing it down.

5. Deduplicate on a key you do not rewrite

“The newest row” is not an identity. Build a key the automation does not change:

source : record_id : event_id

Example: hubspot:contact:184292:evt_9f3. If the source has no event id, use record_id plus the updated_at value from before your write. Never put a field you yourself update inside the key. The Zap will change it, miss the match, and loop.

Zapier:

  1. Build the key in a formatter step or a template.
  2. Storage by Zapier → Get Value for that key.
  3. Filter: continue only if the stored value is empty (or, if you are comparing a payload fingerprint, only if it differs).
  4. Do the write.
  5. Set Value to the key and a timestamp. That set must be the last step, so a failed write does not burn the key and hide a retry you still need.

Also add the write-back filter that stops most CRM loops in one line:

  • Last modified by (text) does not contain the integration user. That is usually the word Zapier, or the exact email of the Make connection.
  • If the CRM has a custom field, write sync_origin=automation and filter out any record that already has it.

Make: use a Data store record whose key is that same string. Get it, and if it exists with the same fingerprint, end the route. Set it only after the write commits.

A fingerprint is just the fields you care about joined together (stage|amount|email). You do not need a code step to start. Equality is enough.

6. Turn it back on against five records

  1. Leave the schedule off.
  2. Replay five known records by hand, including one record your user just edited and one record the automation itself last touched.
  3. Confirm the self-edited record is filtered out, the breaker counter moved by one, and the storage key was written.
  4. Watch task history for half an hour after you enable the 15-minute schedule.
  5. If the counter jumps by more than the five records, turn it off again. The loop is still closed.