Work · 01Integration and state
Bridging two CRMs that offered no way to be told when something changed.
A field-services company ran its sales operation across two CRMs and a work-management board. Leads arrived through six channels — a website form, a phone agent, a booking tool, a shared mailbox, ad-platform alert emails and a field sales app — and each one had to land, once, as one record in the right system. Every stage move on the pipeline board then had to fire its side effects exactly once: stamps, due dates, and downstream objects in operational and finance systems.
- Client
- A field-services company. Not named.
- Layer
- 1 of 4. Integration and state.
- Measured
- 2026-09-11, from the build records.
- Where
- Remote. On accounts the client owns.
Neither CRM could say when something had changed. The first exposed no outbound event path the automation platform could subscribe to, as deployed. The second's connector on that platform exposed two object types and nothing else — none of the objects the later pipeline stages needed to write.
01The constraint
What was actually hard.
Not the workflow count; sixteen workflows are a week of clicking. The hard part was that the same lead could arrive twice from two channels, be updated in one CRM while being created in the other, and be delivered again by a webhook retry — and the system had to produce one record, one stage stamp and one notification every time, with no trigger to anchor any of it on. The obvious substitute, a template on a no-code automation product, fails at the first requirement rather than the tenth, because a template needs a trigger and there was none to attach it to.
02The mechanism
How it works.
Everything hangs off one canonical lead record and one shared intake core. The channel adapters are thin; the core is where the guarantees live.
- Canonical schema before any adapter. All six channels map into one lead shape, so the core never knows which channel called it.
- Dedupe precedence agreed before the first write — phone in E.164 form, then email, then normalised address — written into scope rather than discovered in production.
- An idempotency key on every inbound event — call ID, booking UID, message ID — checked against an event log before any write. A retried webhook produces zero new records.
- For the CRM with no event path: a scheduled status poll five times a day, sized to the API budget and to the lead latency the client would accept, plus a bridge inside the orchestrator supplying the write path the connector lacked.
- Stage truth versus money truth, as one rule written at scope: a money disagreement resolves to the finance system, a stage disagreement resolves to the pipeline board. Without it the two systems sync each other in a loop.
- Exactly-once stage stamping. The events engine reads the target stage's stamp before writing and leaves a marker, so its own write cannot re-trigger it.
- Cross-system identity through a lookup table, deliberately not the board's native relation columns — which is why the build survived a platform migration with every ID intact.
- One error workflow attached to every branch, raising a human-readable alert carrying the execution link.
03The figures
What it measured.
Each figure carries the date it was taken. A number without a date is not on this page.
| Figure | Value | Measured |
|---|---|---|
| Workflows | 16 built · 14 active | 2026-09-11 |
| Functional nodes | 244 | 2026-09-11 |
| Custom code | 67 code nodes · 1,273 lines | 2026-09-11 |
| State tables | 6 tables · 118 columns | 2026-09-11 |
| Channel adapters calling the one shared core | 6 | 2026-09-11 |
| Executions in the platform's seven-day retention window | 262 of 262 successful | window ending 2026-09-11 |
Five status polls a day consume plan-tier execution quota whether or not they find a lead, and that quota is billed monthly. It is priced as a visible line in the proposal rather than absorbed, because a client should see what connecting a closed system costs them. A CRM that ships a webhook removes the line; until it does, the poll is the honest price of the bridge.
04Doing it again
What it would take to do again.
The template is the intake core, the canonical schema and the three state-table schemas; a second client swaps the CRM write node, the geocode rule and the adapters' field maps. The client-specific parts — dedupe precedence, the conflict rule, the stage side-effect table — are decided at scope, before anything is built, and become the acceptance tests.
A fit
Two or more inbound channels, and at least one system with no trigger.
Not a fit
One channel into one system with a native integration. A template does that, and should.
Up against a constraint like this one?
Thirty minutes, no prep, no pitch. Bring the thing that is slow; if it is not a fit, I say so and point you somewhere useful.