Article
Routing as Code: Building a Lead Assignment Regression Suite with Claude Code
Routing rules are the central nervous system of a GTM engine. When they work, leads flow to the right reps and the revenue machine hums. When they break, they break silently. A lead that should have gone to an Enterprise AE in New York ends up in a general SMB queue because a new rule for 'Northeast' was added at the top of the stack without checking for segment overlaps.
Most RevOps teams manage this through 'vibes and verification.' They make a change in a Salesforce sandbox or HubSpot portal, manually create three test leads, and if the owner field looks correct, they deploy. But manual spot-checks fail to catch the edge cases—leads with null employee counts, malformed country codes, or accounts that happen to match three different criteria simultaneously.
If we treated our routing logic like software, we would never deploy a change without running a regression suite. Using Claude Code, we can scaffold a local test harness that simulates our CRM routing engine. This allows us to run hundreds of synthetic leads through our logic in seconds to ensure the 'New York Enterprise' lead still lands where it should, even after we tweak the 'Global Finance' rule.
The Fragility of Sequential Engines
Salesforce Lead Assignment Rules (LAR) are deceptively simple. They operate on a strict top-to-bottom, first-match-wins basis. The engine evaluates Rule Entry 1; if it matches, it assigns the lead and stops. It does not care if Rule Entry 50 is a more specific or 'better' match. This creates a massive risk for 'silent failures' where a broad rule higher in the sort order swallows leads intended for more targeted rules further down.
HubSpot handles routing through workflow enrollment and if/then branching. While more visual, the underlying mechanic is the same: the engine follows the first path it successfully validates. If you have competing branches—say, one for 'Industry: FinTech' and one for 'Territory: West'—a FinTech lead in California will only ever see the first branch it hits.
Without a way to visualize the entire matrix and test it against a diverse set of inputs, adding a rule to the middle of the stack is essentially playing Jenga with your pipeline.
Scaffolding the Test Harness
To build a regression suite, we need a structured representation of our routing rules, a generator for synthetic lead data, and a runner that simulates the CRM logic.
I used the Claude Code CLI to scaffold a Node.js utility designed to test this logic in isolation. The goal isn't to connect to the CRM API—which is slow and introduces state issues—but to test the logic of our routing matrix offline.
First, define the routing matrix in a rules.json file. This acts as our source of truth.
[
{
"step": 1,
"criteria": { "industry": "Finance", "employees": { "min": 5000 } },
"target": "GLOBAL_FINANCE_QUEUE"
},
{
"step": 2,
"criteria": { "state": "NY", "employees": { "min": 1000 } },
"target": "NY_ENTERPRISE_TEAM"
},
{
"step": 3,
"criteria": { "country": "US" },
"target": "US_GENERAL_QUEUE"
}
]
I then initiated claude in the terminal to build the simulator logic. My prompt focused on creating a deterministic runner:
"Create a script that matches a
leads.jsonarray againstrules.json. It must follow sequential 'step' order. If a lead matches multiple rules, output the first match but log the subsequent matches as 'Shadow Hits' for conflict detection."
Claude Code generated a compact runner using a simple predicate engine. Because I was working directly in the terminal, I had it refine the logic to handle the messy reality of CRM data: case-insensitivity for picklist values (e.g., 'NY' vs 'New York') and handling null values in numeric fields.
Generating Boundary-Case Fixtures
Testing with five leads is performative. To find where the logic breaks, we need to test the boundaries. I used Claude Code to generate a fixtures.json file containing 100 synthetic leads.
I instructed the agent to include specific 'poison' leads:
- Leads with missing
employee_count(to test null-handling). - Leads that qualify for both a high-priority industry rule and a low-priority geography rule.
- Leads with ambiguous territory markers (e.g., a country of 'USA' vs 'US').
- Leads that match no rules at all to ensure they hit the catch-all 'Default' queue.
This produces a structured dataset that would take a RevOps manager hours to build manually in a sandbox. By running these locally, we can validate our entire territory model in sub-second time.
The 'Shadow Match' and Tie-Breakers
The most valuable part of this harness isn't just seeing where a lead went, but where else it could have gone.
In the test execution trace, I implemented a 'Shadow Match' report. If a lead for a bank in Manhattan is assigned to 'Global Finance' (Step 1), but the report shows it also would have matched 'NY Enterprise' (Step 2), we now have a documented overlap. If the VP of Sales later decides to prioritize geography over industry, we can swap the rule order and instantly see exactly how many leads shift between teams.
Buy vs. Build: The LeanData Factor
There is a legitimate argument for using enterprise routing engines like LeanData or Distribution Engine. These tools provide native visual graphs and audit logs that are superior for massive organizations with 1,000+ rules and complex account-based matching. If you have the budget and the scale, buy them.
However, for the mid-market operator using standard Salesforce or HubSpot tools, these platforms offer no 'dry run' button. You either build a test harness or you test in production.
One potential pitfall is 'drift.' If you change a rule in the Salesforce UI but forget to update your rules.json, your tests are worthless. To mitigate this, abstract your targets. Don't route to specific User IDs in your tests; route to functional queue names (e.g., EMEA_DR_TEAM). This keeps the test focused on logic rather than individual rep roster changes.
RevOps as GTM Engineering
Building a local test suite is a move away from being a 'CRM Administrator' who clicks buttons and toward being a GTM Engineer who builds systems.
When a sales leader asks, "What happens to our lead flow if we split the California territory?" you shouldn't have to guess or run manual imports. You should be able to update your local matrix, run your fixtures, and provide a structured report showing the delta.
Deterministic testing turns routing from a source of anxiety into a manageable piece of technical infrastructure.
— C.B.