Revenue operations · Reference design
Reliable lead intake
The form said thank you. The CRM never heard of them.
Separate accepting a submission from delivering it, so a CRM outage or a lost response can delay a lead but never lose or duplicate it.
Company Northwind is a hypothetical company. Every figure is illustrative.
About Company Northwind
Company Northwind is a hypothetical company, written for this reference design; the details below are its constraints. Every figure is illustrative, computed from stated assumptions. No client work or measured result is claimed.
- Industry
- B2B software: fleet-telematics add-ons for mid-market logistics firms
- Size
- About 120 people; a revenue team of 22
- Systems
- Website demo form, partner-referral form, trade-fair badge scans, a SaaS CRM, an enrichment API, a no-code automation tool
- Team
- One RevOps manager, a part-time marketing-ops contractor, six SDRs across three territories
- Volume
- About 900 submissions a month, a few hundred more after trade fairs
- Constraints
- GDPR consent before outreach; the CRM stays the system of record; a few hundred euros a month for new infrastructure
In brief
How the work ran before
Company Northwind is a 120-person software company that sells fleet-telematics add-ons to logistics firms. Demand arrives through three doors: the demo form on the website, a partner-referral form, and spreadsheets of badge scans after each trade fair. Around 900 submissions a month, with a spike of a few hundred in the week after an event.
A no-code automation connects everything. When someone submits the form, one automation run does all of it in sequence: look the company up in an enrichment service, ask a model what the person wants, pick an owner from a territory spreadsheet, create the lead in the CRM, and post a message to the sales channel. Six sales development reps work the leads from a CRM view called "New today". A marketing-ops contractor built the chain two years ago and now looks after it a few hours a week.
On a normal day this works, which is why nobody questions it.
Where it broke
The failure that starts Company Northwind's project is quiet. A prospect from a large carrier fills in the demo form, hears nothing, and two weeks later writes to the CEO. The RevOps manager goes looking and finds the submission in the automation tool's list of failed runs. The CRM had returned a rate-limit error during a busy hour. The run stopped. Nothing else happened, because a failed run in that tool is a line in a list that nobody is paid to read.
The same week, another prospect appears twice in the CRM. The CRM had created the lead, the response timed out, and the tool's automatic retry created it again.
Both problems have one cause. The form, the enrichment call, the model call, the CRM write and the notification are one chain, so the moment the visitor sees "Thanks, we'll be in touch" means nothing. The system has promised something it has no record of keeping.
What I would build
The core change is to separate accepting a submission from delivering it.
- Accept. The form handler checks the source, checks consent, validates the few fields that must exist, and writes one row to a database: the submission, a stable event key, and a job to process it. Both rows commit in the same transaction. Only then does the visitor see the thank-you page.
- Process. A worker picks up the job. Enrichment, intent classification and owner routing run here, each with a timeout and a fallback. None of them can make the visitor's submission disappear.
- Deliver. The worker writes to the CRM using the event key, then reads the record back. The submission is delivered only when the CRM confirms it.
- Hold what code can't decide. An unclear identity ("is this the parent company or the subsidiary we already sell to?"), two territory rules that both match, or a withdrawn consent becomes an item in a review queue with a named owner and a deadline.
The model has one job: read the free-text message and propose an intent category, quoting the words it based that on. It does not decide who owns the lead, whether to contact the person, or whether two records are the same company.
Following one submission through
Here is the lost-response case from above, run through the new design at Company Northwind. All identifiers are sample data.
A visitor submits the demo form at 10:14. The handler writes submission lead_evt_28491 and its job in one transaction and returns the thank-you page. At 10:14:03 the worker enriches the domain, the model tags the message "fleet pilot, 40 vehicles", and the territory rules pick the DACH team. The worker sends a CRM create request carrying the event key. The CRM creates the record, but the response is lost in a network timeout.
The old chain would retry blindly and create a duplicate. The worker does not know whether the write happened, so it records the attempt as unknown and does the one safe thing: it searches the CRM for a record carrying lead_evt_28491. It finds one, links it, and marks the submission delivered. The rep sees one lead.
| Submission | Intake | CRM result | State | Next action |
|---|---|---|---|---|
| lead_evt_28491 | Accepted | Response lost | Reconciling, then delivered | Read back by event key before any retry |
| lead_evt_28492 | Accepted | No record found | Retry scheduled | Retry from the CRM step only |
| lead_evt_28493 | Accepted | Record confirmed | Delivered | Owner assigned |
| lead_evt_28494 | Accepted | Not attempted | Rejected: consent withdrawn | Delivery cancelled, no retries |
Sample data. Four submissions from one simulated morning.
Lead
lead_evt_28491 · sample lead
- Lead owner
- Waiting for read-back
- Accepted
- 10:14 · submission and job committed
- Source
- Demo form · event key lead_evt_28491
- Status
- Reconciling
Attempts Event key · lead_evt_28491
-
Create lead
Timeout after send
Unknown
10:14:03 · no response body
-
Read back by event key
One record found
Linked
submission marked delivered · no retry needed
When things go wrong
The CRM is down for an hour. Submissions keep being accepted, because acceptance only needs the local database. Jobs wait with backoff. When the CRM returns, they drain in order. The team sees a queue with an age instead of silence.
Enrichment times out. The worker routes with what it has. If the territory can't be decided from the submitted country alone, the lead goes to the review queue with the reason "no enrichment, territory ambiguous" instead of a guessed owner.
The model returns nonsense or nothing. The intent field stays empty and the lead is delivered without it. Intent helps prioritize; it is never required for delivery.
A person withdraws consent before delivery. The pending job is cancelled and the reason is recorded. Retrying a delivery the law no longer allows is not a recovery.
What changes for the team
Northwind's reps keep their workflow: they still work from the CRM. What changes is what the RevOps manager can see and trust.
| Question | Before | After |
|---|---|---|
| Did every submission reach the CRM? | Unknown without checking the failed-runs list | One query: accepted minus delivered minus held |
| Why is this lead not assigned? | Ask in chat | Hold reason and owner on the item |
| Why are there two records? | Guess | Attempt log with the event key |
| Who fixes a stuck lead? | Whoever notices | The queue owner, within a deadline |
Illustrative figures for one month, computed from assumptions I state in the technical design (900 submissions, 3% of CRM calls rate-limited, 1% of responses lost). They are not measurements.
| Illustrative outcome (per month) | Chained automation | Durable intake |
|---|---|---|
| Submissions lost after acceptance | about 27 | 0 by design, if the database commit succeeds |
| Duplicate CRM records from blind retries | about 9 | about 0, if read-back by event key works |
| Leads waiting for a person | not tracked | about 40, each with a reason and owner |
The third row is the honest cost: durable intake turns ambiguity into work someone has to do.
What this does not solve
It does not make the CRM faster or more reliable. It does not fix a territory spreadsheet that contradicts itself; it only makes the contradiction visible. And if the CRM offers neither idempotency keys nor a searchable field for the event key, the duplicate protection weakens to "search by email and company and ask a person when unsure".
How I would prove it
A two-week shadow run is enough. The new intake writes to its own database while the old chain keeps running. Every day, compare three lists: submissions the form received, leads the old chain delivered, and leads the new pipeline would have delivered. The differences are the evidence, and every one should have a reason.
The technical design
The same system for engineers: architecture, records, failure handling, evaluation, the options I rejected, and the stack. About 5 minutes.
Losing leads between tools?
Bring a week of form submissions.
A submission log and the matching CRM records are enough to find where delivery breaks. Please don't send personal data; counts and IDs will do.