This isn't the runaway-loop problem where one workflow texts a person 40 times before anyone notices. This is quieter and harder to catch: two separate, healthy-looking workflows that each fire on the same trigger. Neither one is broken. They just both wake up when the same tag lands on a contact, and both decide to send a text. The contact gets two nearly identical messages inside the same minute, and nothing in either workflow's history looks wrong.

Full disclosure: I work for Ready, an SMS platform built to sit under GoHighLevel. I spend a lot of time reading agency send logs, and overlapping triggers across workflows are one of the most common "why did my client get this twice" tickets I see — precisely because each workflow passes its own individual audit.

How two clean workflows collide

Most GHL accounts accumulate workflows the way a garage accumulates boxes. Someone builds a "New Lead Nurture" workflow triggered on Tag Added: new-lead. Six months later someone else — maybe a different team member, maybe the client themselves inside a sub-account — builds a "Speed-to-Lead SMS" workflow, also triggered on Tag Added: new-lead, because that's the tag their form automation drops.

Now the tag lands once. GHL evaluates every workflow whose trigger matches. Both qualify. Both enroll the contact. Both hit their "Send SMS" step within seconds of each other.

The tell:

  • Workflow A sends: "Hey Jordan, thanks for reaching out — someone from our team will call you shortly."
  • Workflow B sends: "Hi Jordan! Thanks for your interest. We'll be in touch soon."

Two texts, seconds apart, saying the same thing in slightly different words. To the contact it reads like a system with the hiccups. To a carrier's spam filter, it reads like something worse.

Why carriers care about repeated near-identical texts

Carrier filtering (especially T-Mobile's) doesn't just look at content — it looks at pattern. A number that sends two near-duplicate messages to the same handset inside the same minute trips a couple of the signals that spam models weight heavily:

  • Repetition to a single recipient in a short window — a hallmark of misconfigured or abusive senders.
  • High similarity content on the same 10DLC campaign, which can nudge your campaign's overall reputation down over time.

You won't get a bounce notice. That's the frustrating part. The first message lands, the second gets silently filtered, and your log shows it as "sent." The contact only received one — but your reporting says two, your billing charged for two, and your campaign reputation took a small ding for the pattern. Do that across a few thousand contacts a week and the drift is real. (This is the same silent-filtering dynamic that makes shared link shorteners quietly tank your deliverability — carriers act on signals you never see.)

The CX cost is worse than the deliverability cost

Deliverability drift is slow. The customer experience hit is immediate.

A contact who opted in once, gave you one phone number, and gets two "welcome" texts inside 60 seconds does one of two things: ignores it (mildly annoyed) or replies STOP (gone forever). Ready honors that STOP automatically and propagates the opt-out across every campaign, so you can't re-message them anywhere — which is correct behavior, but it means a duplicate-send bug is quietly shrinking your list. Every double-text is a small tax on your opt-in base.

And it compounds with the SMS-plus-email-at-the-same-step problem: if one of those two workflows also fires an email, the contact now has two texts and an email in the same minute, and your unsub rate is climbing for reasons that never show up in a single workflow's view.

Why the standard guardrails miss this one

If you've read up on GHL duplicate sends, you've seen the usual advice: turn on "Allow Re-Entry: No" and set "Stop on Response." Those are good — I'll come back to them — but they solve the wrong problem here.

Re-entry settings only stop a contact from re-entering the same workflow. They do nothing about a different workflow firing on the same trigger. Each workflow thinks it's the only one in the room. This is exactly the gap that the runaway-loop and misfire guardrail guides don't fully cover, because those are about one workflow behaving badly, not two workflows behaving well independently.

The dedupe guardrails that actually stop it

Here's the order I'd fix it in, cheapest and most durable first.

1. One trigger, one owner

The cleanest fix is architectural: decide that a given tag has exactly one workflow allowed to fire the initial SMS. If new-lead should send a welcome text, one workflow owns that. Everything else that needs to run on new-lead either lives inside that workflow as later steps, or triggers on a different tag that the first workflow adds.

Concretely:

  • Tag Added: new-leadWorkflow A only sends the welcome SMS, then adds nurture-started.
  • Tag Added: nurture-started → Workflow B picks up the longer sequence.

Now the trigger space doesn't overlap. This is boring and it works.

2. A "message sent recently" gate

When you can't consolidate — different teams own different workflows, common in agency sub-accounts — add a guard step at the top of the second workflow:

  • If contact has tag sms-sent-24hexit (don't send).
  • Otherwise → send, then add sms-sent-24h with an auto-remove after 24 hours.

Every SMS-sending workflow checks and sets the same flag. It's a shared lock. Whichever workflow gets there first sends; the other one sees the flag and bows out.

3. A wait + condition at the send step

For a lighter touch, put a short Wait (1–2 min) before the send, then an If/Else checking whether a duplicate flag was set in that window. The wait costs you nothing (the message was never going to be more useful 90 seconds later) and gives a competing workflow time to claim the lock.

4. Keep the standard settings on, too

They still matter for the single-workflow cases:

SettingWhat it stopsWhat it doesn't stop
Allow Re-Entry: NoSame contact re-entering the same workflowA different workflow firing on the same trigger
Stop on ResponseContinuing to text someone who repliedThe initial duplicate from two workflows
Shared "sent-recently" tagTwo workflows both sending in a windowNothing — this is the cross-workflow fix

How to find the overlaps you already have

You can audit this in about 15 minutes:

  1. Open every active workflow and write down its trigger — the exact event and filter.
  2. Group by trigger. Any trigger claimed by more than one SMS-sending workflow is a suspect.
  3. Pull your send log and sort by contact + timestamp. Look for the same contact receiving two messages inside a 5-minute window. In Ready, because the GHL integration is native two-way, every outbound shows in the conversations inbox with its timestamp — so duplicates to one thread are easy to eyeball, versus a webhook setup where the two sends might not even thread together.
  4. For each confirmed overlap, apply guardrail #1 (consolidate) if you can, #2 (shared flag) if you can't.

The 20-minute trigger-pitfall audit covers the broader version of this if you want a fuller checklist.

The practical takeaway

Duplicate sends across two workflows aren't a bug in either workflow — they're a gap between them. Re-entry settings can't see across that gap. The fix is either to give each trigger a single owner, or to add a shared "sent-recently" flag that both workflows respect as a lock.

It's worth doing because the cost is real on three fronts: you pay for the extra segment, the carrier quietly filters the duplicate and dings your campaign reputation for the pattern, and the contact gets a reason to reply STOP — which permanently removes them from every list you have.

If you're mapping this out for a stack of client sub-accounts and want the sends, the timestamps, and the opt-out propagation all landing in one place so overlaps are visible instead of hidden, that's the kind of thing Ready's native GHL integration is built for. You can start on the free 2,500 credits and audit your own logs before you change a single workflow — sign up here and go look for the 5-minute duplicates first.