CRM & RevOps

Your Forecast Is Not Wrong. Your Deal Stages Are.

Phantom pipeline is a design problem, not a discipline one. Build deal stage exit criteria, stale-deal detection and disqualification in HubSpot.

In shortStale deals in HubSpot are a design problem, not a rep discipline problem. A deal only rots in a stage that has no exit. The fix is exit criteria for every stage, derived activity and stage-age clocks, live stale-deal views, guardrails for buyer signals, flag-for-review instead of auto-close, quarterly snapshots and a weekly stale report by reason.

Oriol SerraSep 4, 2026 · 13 min read

Every quarter, some version of this conversation happens. The board number says 4 million in open pipeline. The CRO presents it. Then the quarter closes at a third of the coverage anyone expected, and the post-mortem lands on the reps: they are not updating the CRM, they are too optimistic, they need better discipline, we should add a Monday pipeline review.

That diagnosis is wrong, and it is wrong in an expensive way. I have never seen a portal where stale deals were caused by lazy reps. I have seen dozens where stale deals were caused by a pipeline that gave nobody a rule for taking a deal out.

A deal only rots in a stage if that stage has no exit. That is a design decision, and somebody made it, usually by accident, usually two years ago, usually while doing a "quick HubSpot setup."

So this is the reframe: phantom pipeline is not a discipline problem you fix with meetings. It is an architecture problem you fix with rules, clocks, and a report. Below is the system we install, and the audit we run before we install it.

Phantom pipeline is the leak nobody prices

When we run a GTM audit, the same five revenue leaks show up in nearly every team doing 1 million to 30 million ARR. Leak number four is CRM and pipeline management: bloated property sets, inconsistent stages, stuck deals, and phantom pipeline counted in the board number.

Leak four is the one clients push back on hardest, because it does not look like a leak. Nothing is broken. Reports load. Dashboards render. Deals exist. The system is behaving exactly as built.

That is what makes it expensive. A dead deal does not throw an error. It sits in Demo Complete, keeps its amount, keeps its close date, and quietly gets counted every time somebody sums the pipeline. Vendors like to quote a share of pipeline that is dead, and the numbers float somewhere between a fifth and a third depending on whose benchmark you pick. I would not build a plan on any of them. The honest answer is that in most portals the number is simply unmeasured, which is a worse position than a bad estimate.

Do the arithmetic on your own portal instead. Take your open pipeline. Assume a quarter of it will never close and was never going to. If your board number is 4 million, you are setting quota, headcount, and cash plans against 1 million of fiction. Nobody lied. The system just had no way to say no.

And it compounds in three directions. Coverage ratios inflate, so leadership under-invests in new pipeline exactly when it is needed. Time in stage and velocity averages get dragged by deals that stopped moving in March, so every stage benchmark you report is a blend of live deals and corpses. And win rate becomes unreadable, because the denominator is full of opportunities that were never opportunities.

If your board number can be changed by a rep editing a field, it is not a board number. And if it can be inflated by a rep not editing a field, it is not a board number either.

What a stale deal actually is

Most teams cannot answer this question in one sentence, which is the actual root cause. "Stale" is not a rule. It is a feeling a sales manager has on a Friday.

Here is the definition we write into the data model. A deal is stale when at least two of these are true:

  1. No two-way activity in the window. Not a logged send, not a task the rep created for themselves. A real exchange, initiated or answered by the buyer. Our default cold threshold for contacts is 90 days with no two-way activity, and for deals in an active cycle we tighten it, usually 21 to 30 days depending on cycle length.
  2. Stage age exceeds the stage benchmark. Not deal age. Stage age. A deal that has been in Proposal Sent for four times the median time any deal spends in Proposal Sent is telling you something a total-age filter cannot.
  3. The close date has been pushed more than twice. One slip is a buyer. Three slips is a rep protecting a number.
  4. The stage exit criteria were never met. The deal is in Negotiation and there is no economic buyer identified, no pricing sent, no next step booked. It was moved on optimism.

Note what is not on that list: rep sentiment. "He says it is still alive" is not evidence, and "commit" is not a stage. If the burden of proof sits with the system, a deal stays until it earns its place. If the burden of proof sits with the rep to prove it is dead, the deal stays forever.

Write this down as one sentence with an owner and a threshold, the same way we write suppression rules for outbound. "Stale deals" is not a rule. "No two-way buyer activity in 30 days, plus stage age above 2x the stage median, owned by Sales, reviewed weekly, guardrailed on any inbound reply" is a rule.

Three design failures that create stale deals

The stages describe your process, not the buyer's

The most common one, and the least obvious. Stages get built off a spec document rather than a working session with the person who actually runs the process end to end.

We hit this on the Tech Barcelona migration. The visits pipeline stages in HubSpot did not match how the person owning visits actually ran one. The root cause was written into the fix ticket in plain language: the stages were built generically off the original property mapping spec, without a dedicated session with the process owner to confirm her real step by step. The fix was not automation. The fix was to rebuild the pipeline to the four stages she actually uses, confirmed against a second source before anyone touched HubSpot.

One detail from that fix is worth stealing: stage history cannot be backfilled. If you rebuild stages, everything before the rebuild is gone as a time series. So the cost of getting stages wrong is not just today's mess, it is the permanent loss of the history you would need to measure the fix. Build the stages before you build the reports.

The stages have entry criteria and no exit criteria

Almost every portal we audit has some notion of what gets a deal into a stage. Almost none has a written condition for what takes a deal out other than winning it.

Lifecycle governance is five rules, and exit criteria is the one everybody skips: entry criteria, exit criteria, reset logic, ownership rules, and automation. Exit criteria is the rule that says a record leaves a stage by being disqualified, converted, or lost. Without it you get zombies by construction, at every stage, forever.

The tells are consistent. MQLs with no next step. Deals sitting in Demo Complete for months. A win rate report that reads above 100 percent because closed-lost was never used properly. Duplicate contacts holding different lifecycle stages. If you see those, your lifecycle is not governed, it is guessed.

The stage values themselves are broken under the hood

This one is invisible from the UI, and it is the reason I do not trust a pipeline report until I have looked at the internal values.

On a HeyReach engagement, the Tier 2 pipeline had a Closed Won stage carrying the wrong internal value. Not the wrong label, the wrong internal value, which is what reporting and automation actually read. Fixing it meant creating the correct stage, migrating deals across, and deleting the old one, and it blocked everything downstream: 3,917 migrated deals with history going back to 2023 could not be segmented for historical revenue reporting until the stage itself was correct.

That is the shape of this class of bug. The chart still renders. The number is just wrong, and it has been wrong for years. Same failure mode as revenue held in a single line text property: HubSpot offers you COUNT instead of SUM and the dashboard looks fine.

The build: seven steps, in this order

The order matters more than any individual step. Skip step one and the rest is automation on top of an undefined process, which is how you get a workflow that closes live deals.

1. Write exit criteria for every stage, with the person who runs the process

Five to seven stages, no more. For each one, write two things: what must be true for a deal to enter, and what must be true for it to leave. Leaving has three doors, not one: won, lost, or disqualified. Disqualified is not lost, and collapsing them destroys your ability to tell a pricing problem from a targeting problem.

Get this in a room with the process owner and require a second source. On Tech Barcelona the agreed stage set was only settled by cross-referencing the process owner's answer against an independent contract status tracker. Two sources agreeing is a fact. One person's recollection is a hypothesis.

2. Instrument the clocks before you automate anything

You cannot branch on activity you have not derived. Build the properties first, then write logic against the properties. Never against raw activity.

The minimum set on the deal:

  • last_buyer_activity_date, populated only by two-way engagement, so a rep sending a fifth follow-up does not reset the clock
  • date_entered_current_stage, and a derived days_in_current_stage
  • close_date_push_count, incremented by a workflow that fires when close date is updated (HubSpot has no native counter for this, and the community threads asking for one go back years)
  • stale_flag and stale_reason, written by the detection logic, never by a human

This mirrors the audit trail we make non-negotiable on ownership changes: owner_assigned_date, owner_assignment_reason, previous_owner. The principle transfers exactly. Three properties turn a stale deal from an opinion into a report.

3. Detect with a live view, not a CSV

Materialise the stale set as a saved HubSpot view with real filters, not a monthly export somebody cleans by hand. A static CSV is a snapshot of a problem. A view is a system.

Start with these views and put them in front of managers, not in a folder:

  • Stuck 30 or more days in stage
  • No two-way buyer activity in 21 days
  • Close date pushed 3 or more times
  • Close date in the past, deal still open
  • Open deal, no next step task, no meeting booked

The fourth one alone usually finds a startling amount of pipeline. A deal with a close date three months in the past is not a forecast, it is a receipt.

4. Guardrail first, always

This is the step everyone skips, and skipping it is how you strip an owner off a live opportunity or auto-close a deal the day before signature.

The guardrail branch goes first in the workflow canvas, before any detection logic runs. Any real buyer signal freezes the deal: a reply, a booked meeting, a proposal viewed, a trial started, an invoice raised. Signal wins over every clock.

There is a hard constraint here that comes from our own CRM cleanup protocol. Our do-not-touch exclusions during any hygiene work are active customers, open deals, and anything revenue linked. Open deals are on that list on purpose. So a system that acts on open deals has to earn the exception, and it earns it by never closing anything automatically. Which brings us to step five.

5. Flag for review, do not auto-close

Automation flags. Humans close. That is not timidity, it is the same rule we apply to deduplication: flag unmatched records for review rather than force merge, because an unsafe merge overwriting first touch data is worse than a missed match. An auto-closed live deal is worse than a stale one that sat an extra week.

The mechanic that works: the flag creates a task on the deal owner with a 5 business day clock and a manager notification. The rep does one of three things. Provide evidence and the deal stays, with the evidence logged. Move it to a nurture or recycle state. Or close it out with a reason.

Then tag, do not delete. A closed-lost deal with a reason and an expiry is an asset. Set the expiry the way we set suppression expiries, for example closed-lost within 180 days is excluded from re-prospecting and then automatically comes back into play. Deleting the record just means it returns next quarter through a different route with no memory attached.

6. Snapshot the pipeline so history stops moving

A CRM overwrites history by default. Edit a record today and last quarter's number changes, which means your pipeline history is not a record, it is a rendering of the current state.

Take dated, immutable pipeline snapshots at quarter end, and store them in properties rather than trusting a report to reconstruct them. This is the same reason we store Initial MRR and Matured MRR as separate properties instead of one field that drifts. Without snapshots you can clean up the pipeline and then be unable to prove the cleanup worked, because the baseline moved with you.

7. Report the stale number weekly, by reason

One number on the same dashboard the rep performance report lives on: open deals flagged stale, in count and in amount, broken out by reason.

That breakdown is a diagnostic, not a scoreboard. If "no buyer activity" dominates, you have a follow-up and routing problem. If "stage age" dominates on one specific stage, that stage has no exit criteria or two stages have been collapsed into one. If "close date pushed" dominates, your reps are managing a forecast conversation, not a deal. And if the total keeps climbing, the detection is running and the disqualification is not.

Then freeze the reason labels. Once defined, never redefine a reason; add new ones under new labels. Redefine a label and you lose week over week comparability, which is the only thing that makes the report worth reading.

The 20 minute pipeline audit you can run today

Five checks. You can do these in a discovery call, and I do.

  1. Ask two reps to define the exit criteria for the same stage, separately. Different answers mean the stage does not exist as a concept, only as a dropdown value.
  2. Filter open deals for a close date in the past. Any count above a handful means nobody owns the forecast hygiene.
  3. Check the internal values behind your Closed Won and Closed Lost stages, not the labels. Verify against what your reports actually read.
  4. Sort open deals by days in current stage, descending, and look at the top twenty. Ask what would have to be true for each one to close this quarter.
  5. Ask for last quarter's pipeline snapshot. If nobody can produce one that has not changed since, you have no baseline and no way to measure any fix.

Fail two or more and the problem is your data model, not your reporting layer. Fail four and stop building dashboards until the stages are rebuilt, because you will just be rendering the same fiction faster.

Where this breaks

Two honest caveats, because I would rather you install this properly than enthusiastically.

Thresholds are cycle specific. A 21 day inactivity rule is right for a 45 day sales cycle and actively harmful in an enterprise motion with a 9 month cycle and long procurement gaps. Benchmark the thresholds against your own closed-won history before you set them. Do not copy mine.

And whenever we deploy something like this, we find edge cases in the following days. Renewals that legitimately sit dormant. Deals paused by a buyer's fiscal calendar. Multi-year contracts where the next real activity is eleven months out. Run the detection in flag-only mode for one full cycle before you attach any consequence to it, and put the whole thing inside a weekly health check, because a workflow that quietly stopped running looks identical to one that is working.

The part that is not a HubSpot problem

None of this is really about HubSpot. It is about whether your pipeline is a model of how buying happens at your company or a set of dropdown values somebody typed in once. Right architecture and the tool is a detail. Wrong architecture and no tool saves it.

A stale deal is not a bad record. It is a forecast you already presented to your board.

If you want to know how much of your pipeline is fiction before your next board meeting, our GTM Maturity and Revenue Leak Assessment is a 30 minute diagnostic across five areas, and it gives you a maturity level, your top three revenue leaks in dollars, and the one module that fixes the biggest one. Pipeline is usually leak number four, and it is usually the cheapest one to fix.

If you already know the stages are the problem, that work sits inside our Revenue Machine Analysis, where lifecycle architecture, stage definitions, exit criteria, and the dashboards that read them get designed as one system rather than five tickets.