Home Blog Contact
Home/Blog/Why Your Winback Flow Keeps Emailing Returned…
ArticleKlaviyoKlaviyoWinback FlowRetention

Why Your Winback Flow Keeps Emailing Returned Buyers

8 min readBy Miloš Mitrović

A winback flow that keeps emailing people who already came back is almost never a copy problem. It's a state problem. The flow is deciding who has lapsed by reading something that no longer reflects the customer's real order history, so a buyer you already recovered keeps getting "we miss you" mail. Every one of those sends erodes trust with a customer you just won back, and it quietly inflates the flow's revenue credit while hiding the leak. The fix is to make the exclusion read live purchase events, not a stored property or a segment the customer has already left.

Key takeaways

  • The reliable winback stop is a metric trigger on Placed Order with a profile filter of Placed Order zero times since starting this flow, which Klaviyo re-checks before every send.
  • Segment-triggered winbacks cannot use trigger filters, and a profile is not removed from an in-progress flow just because it leaves the triggering segment, so a returned buyer stays enrolled.
  • A profile property such as Last Purchase Date lags the actual order, because date-property flows run on a daily scan, so a message can queue before the property updates.
  • A returning customer who checks out as a guest or under a different email lands on a new profile, so the old profile's order count never increments and the winback keeps firing.
  • If your lapse window is shorter than the real repurchase interval, you are mailing customers who never lapsed at all.

Why does a winback flow keep emailing customers who already bought again?

Because the exclusion is reading a version of "has this person purchased" that trails the customer's actual behavior. A winback has to answer one question before each send: has this profile placed an order since we started trying to win them back. There are three ways to answer it, and two of them go stale.

The durable answer is the live event. Klaviyo records a Placed Order metric the moment the order syncs, and a filter that counts that event evaluates in real time. The fragile answers are a stored profile property (which updates on a delay) and segment membership (which the customer can leave without ever exiting the flow). Most over-mailing traces back to a flow that was built on one of the fragile answers.

What trigger and exclusion actually stops a returned buyer?

A metric trigger on the Placed Order event, paired with a profile filter of Placed Order zero times since starting this flow. Klaviyo documents exactly this structure in its guide to building a winback flow, and the "since starting this flow" phrasing is what makes it self-correcting: the moment the customer orders again, that count stops being zero.

The reason this works is timing. Klaviyo's own reference on flow triggers and filters states that profile filters are checked when someone first enters a flow and before each action takes place, while trigger filters are only checked when an individual first enters. So a profile filter keeps asking the question before every email; a trigger filter asks it once and never again. Your exclusion belongs in a profile filter for that reason.

Winback structureHow exclusion is enforcedRe-check behaviorFailure risk
Metric trigger (Placed Order) + profile filterCounts the live Placed Order event since flow entryRe-checked before every sendLow, provided identity resolves to one profile
Segment trigger (has not purchased in N days)Relies on segment membership, cannot use trigger filtersNot removed on segment exit unless a profile filter forces itHigh, returned buyers stay enrolled
Date-property trigger (Last Purchase Date)Reads a stored date propertyProperty refreshes on a delay, checked on a daily scanMedium, sends can precede the property update

Why does a segment-triggered winback never let returned buyers go?

Because segment triggers cannot carry a trigger filter, and leaving the segment does not pull a profile out of a flow it has already entered. Klaviyo notes that only metric-based, custom-object and price-drop flows can have trigger filters, which rules them out for a "customers who have not purchased in 90 days" segment. That leaves profile filters as your only enforcement.

Here is the part operators miss. A customer buys again, drops out of the lapsed segment, and you assume the flow lets them go. It does not. Segment membership governs entry, not continued progression, so the profile keeps advancing through the delays and messages. Unless you add an explicit profile filter of Placed Order zero times since starting this flow to the segment-triggered version, every recovered customer keeps receiving the sequence to its end.

Why does a profile property like Last Purchase Date lag behind the order?

Because a profile property is a stored value that something has to write, while the order is an event that lands immediately. If you build the winback as a date-property flow off Last Purchase Date, Klaviyo's documentation on date property-triggered flows explains that it checks profiles on a daily scan to queue anyone due to enter. A same-day repurchase can be recorded as a Placed Order event hours before the property that feeds the flow catches up.

The same gap shows up when a custom property is synced from Shopify, a subscription tool or a warehouse on a schedule. The event is real time; the property is a snapshot. Filter the winback on the event count, not on a date property that a downstream job updates whenever it next runs. If you already reconcile these numbers, you have seen the same lag in the gap between Klaviyo revenue and Shopify, and it is the same root cause: stored state trailing live events.

Why can a returning customer slip through as a brand-new profile?

Because Klaviyo keys profiles on email, and a returning buyer who checks out as a guest, uses a second address, or types their email in a different case can create a separate profile that carries none of the original order history. The old profile's Placed Order count stays at zero for the flow's purposes, so the exclusion evaluates as "still lapsed" and the winback keeps sending.

This is an identity-resolution problem, not a flow-logic problem, and no filter fixes it on its own. The winback is correct; it is looking at the wrong profile. The tell is a customer who insists they bought last week while your flow report shows them as never-recovered. When you see that pattern, the work moves upstream to merging duplicate customers and enforcing one identity per buyer before it ever reaches the flow.

Is your lapse window mailing people who never actually lapsed?

Often, yes. A winback that triggers at 60 days for a catalog whose average repurchase interval is 35 days is not recovering lapsed customers, it is interrupting active ones mid-cycle. The exclusion is working; the definition of "lapsed" is wrong. This is the same mistake as excluding "purchasers in the last 60 days" from a campaign when the real repurchase interval is 30 days, which suppresses exactly the people most likely to buy.

Derive the threshold from your own data rather than a template. The lapse point should sit past the tail of your repurchase distribution, not at a round number. The method for that is to size the window from your repurchase curve so the flow only ever wakes up customers who have genuinely stopped buying.

How do you find the returned buyers who still got the flow?

Pull the flow's recipients, then cross-check each against a Placed Order event dated after their flow entry. Anyone with a qualifying order who still received a later message is a leak, and the count tells you how bad it is. Do this before you rewrite anything, because it separates a broken exclusion from a lapse window that is simply too tight.

One nuance changes how you read the numbers. Klaviyo states that it does not remove someone from a flow completely if they fail the flow's filters at a single step, and that contacts continue to be scheduled for the next step. So a profile that buys, correctly gets one message skipped, then somehow qualifies again later is not a bug in the filter, it is the platform behaving as designed. The recipients that matter are the ones who ordered and still received subsequent sends with no skip, which is the signature the audit for flow double-sending is built to surface.

What should you watch before touching a live winback?

Put the exclusion on the messages, not on the trigger. Klaviyo warns that flow filters placed on the trigger can cause profiles to skip a profile-property-update action, and it recommends moving those filters onto the individual emails and SMS instead. Attaching Placed Order zero times since starting this flow at the message level keeps the exclusion honest without breaking any update steps that run earlier in the flow.

Coordinate across channels. If email and SMS winbacks run as separate flows, both need the same Placed Order exclusion, and both inherit the "not an exit at a single step" behavior, so a customer can be skipped on email yet still be scheduled on SMS if the SMS filter is weaker. Finally, back-test on a historical cohort before you enable, and keep an eye on the flow's revenue credit afterward: a winback that mails recovered customers will claim orders those customers were going to place regardless, which makes the flow look more effective than it is and hides the very leak you are trying to close.

Sources

M
Miloš Mitrović
Email Marketing for Ecommerce

Have a question or a project?

Whether it is about this post or a system you want built, I'm happy to talk.

Get in touch

404

Post not found. It may have been moved or the link is incorrect.

← Back to the blog
Summarize with AI
ChatGPT, Perplexity, and Grok open with the prompt ready to run. Claude, Gemini, and Copilot open a chat with the prompt copied; press Ctrl+V (Cmd+V on Mac) to paste. The full text is included, so it works even without web access.