The Routing Logic Was Right. The Lead Still Went to the Wrong Rep.

A booked lead routed to the wrong rep even though every routing rule was correct. The culprit was a race condition between the router and an async field write — and the fix was a single wait node.

The Routing Logic Was Right. The Lead Still Went to the Wrong Rep.

A prospect books a meeting with one rep. Minutes later, a second rep reaches out to the same prospect. Two reps, one confused prospect, and a routing flow that — on paper — did everything right.

This is the story of a race condition in lead routing, why line-by-line logic review couldn’t find it, and the one-node fix.

The symptom

The sequence looked like this:

  1. Prospect books a meeting through the scheduling tool — the meeting owner is a specific rep
  2. The lead’s status flips to MQL, which triggers the routing flow
  3. Round robin assigns the lead to a different rep
  4. Both reps now believe they own the lead

The routing flow had a rule designed to prevent exactly this: if the booking ID field is not null, route to the meeting owner. Skip round robin entirely for booked leads.

We reviewed that rule line by line. The field reference was right, the operator was right, the branch order was right. The logic was correct. So why did the not-null check evaluate false for a lead that had a booking?

The real culprit: timing

The answer wasn’t in the routing logic at all. It was in when the routing logic ran.

The flow fires the instant the MQL status change hits the CRM. But the booking ID is written by a separate asynchronous process — the scheduling tool’s integration writes it seconds later, on its own clock.

So at evaluation time:

Without a wait:
  Trigger:      fires instantly on MQL
  Booking ID:   still being written by the async integration
  At check:     null → falls through to round robin

The flow read the field before the field existed. Both things were true at once: the lead had a booking, and the booking ID was null at the moment the router looked. A race condition — the check and the write racing each other, and the check usually losing by a few seconds.

The fix: one hold node

With a 5-minute hold:
  Trigger:      fires on MQL
  Hold:         5-minute wait node
  Async write:  completes during the hold
  At check:     booking ID populated → routes to meeting owner

We added a single wait node in front of the booking check — hold five minutes, then evaluate. That’s the entire fix:

  • The hold gives the async write time to finish
  • The check reads a real value instead of a mid-write null
  • No routing logic changed — the rules were always right
  • Booked leads now land with the rep they booked with

Five minutes is deliberate margin, not measured precision. The async write usually lands in seconds, but the hold costs nothing meaningful at MQL stage — a lead waiting five minutes to route is invisible; a lead routed to the wrong rep is not.

How to diagnose a misroute like this

The debugging pattern matters more than this specific bug, because most routing bugs are timing bugs in disguise:

  1. Pull the routing audit log — most routing tools record exactly what each node evaluated and what every field contained at decision time
  2. Compare the two timestamps — when did the flow evaluate the field, and when was the field actually written? If evaluation precedes the write, you’ve found it
  3. Only then review the logic — evidence beats guessing; the log tells you whether you have a logic problem or a timing problem before you spend an afternoon re-reading rules

In our audit log, the misrouted leads all showed the booking field empty at evaluation time — and the CRM field history showed the same field populated seconds after. The whole diagnosis was two timestamps.

What the simulator can’t tell you

One more lesson from this incident: a passing simulator test isn’t the whole story.

Routing simulators validate the wiring — given this input, the graph takes this path. But simulators can’t fast-forward wait nodes, so both test paths stop at the hold. That’s expected behavior, not a failure. The simulator proves the flow reaches the hold correctly; only live routing proves the timer does its job.

Know what your test can and can’t prove. We validated the wiring in the simulator, shipped, and confirmed with live booked leads over the following week: every one landed with the rep they booked with.

The takeaway

When routing logic that reads correctly produces wrong results, check the clock before the code. The question isn’t only “is this rule right?” — it’s “was the data this rule reads actually there when the rule ran?”

One wait node. Every booked lead routed right.