Context: Anonymized production engagement · domain: GTM / CRM / meetings
The problem
After a sales call, the CRM is supposed to hold a useful note: who was there, what was discussed, what the next step is. In practice that note is often late, thin, or missing — not because people are lazy, but because the handoff from meeting tools to CRM has no reliable trigger.
I have been shipping meeting → CRM note paths where the RevOps lead cares about hygiene, sales cares about speed, and IT cares about not running another brittle schedule that pages nobody when it quietly stops. The choice that decides most outcomes is simple: do you poll for work, or do you react when work appears?
What people usually try
The naive path is a timer:
- Every N minutes, query the meeting system, the file store, the call platform, or a staging sheet for “new” items.
- For each candidate, build a summary (rules, LLM, or both).
- Match a contact or deal in the CRM.
- Create or update a note / activity / custom object.
- Mark the source as processed — if you remember to.
That design optimizes for “I can demo it this afternoon.” It does not optimize for production.
Latency. A five-minute poll means the average wait is half that interval even on a perfect run, plus processing time. Sales does not experience “near real time”; they experience “sometime after the call, maybe.”
Cost. Empty polls still cost API calls, workflow runs, and LLM pre-checks if you are careless about when you call a model. Sparse events on a dense schedule are pure waste.
Reliability. Poll windows create race conditions around “newness.” Items that change state between list calls, or fail mid-process without a durable cursor, become ghosts. Schedulers also hide outages: a green schedule is not the same as “all meetings processed.”
Idempotency (or the lack of it). Without a hard key on “this meeting / this transcript version already produced this CRM artifact,” you get duplicate notes or a processed flag that lies. Tighter schedules and longer lookbacks usually make the system louder without making it correct.
What we implemented instead
The production path is event-driven end to end:
- Emit or subscribe to a real completion signal — e.g. a Graph change notification when a transcript is available, a webhook from the meeting stack, or an internal “ready for CRM” event after validation.
- Enqueue a unit of work with a stable business key (meeting identity + content version), not “row 47 from the last list call.”
- Process once, safely: fetch payload, summarize with a fixed schema, resolve CRM associations, write the note, store a processing receipt.
- Retry with the same key. Failures re-enter the queue; successes short-circuit on the receipt.
- Backfill as a separate job for the window when subscriptions or producers were down — not as the forever primary loop.
Why this wins on the four axes:
- Latency. Work starts when the event arrives. You are not waiting for the next clock tick.
- Cost. You pay for real changes. Idle systems stay quiet.
- Reliability. You can monitor lag, dead letters, and subscription health as first-class signals. A stuck queue is visible; an empty poll schedule is not a signal at all.
- Idempotency. The business key is designed in. Redelivery is expected. CRM writes become upserts against a known identity, not “create another note because the timer ran again.”
The principle holds across CRMs and meeting platforms: the CRM note is a reaction to a fact, not a scavenger hunt on a schedule.
What broke / what we learned
The failure mode I keep hitting is confusing “workflow ran” with “business outcome landed.”
An event-driven pipeline can still fail after the webhook: contact match misses, the CRM API rejects a payload, the model returns an empty summary, or a partial write succeeds while the receipt never stores. If your only alert is “HTTP 200 on the notification endpoint,” you ship silent gaps that look like success from the edge.
We learned to separate three health views:
- Ingress: events received and accepted.
- Processing: jobs completed, retried, or dead-lettered.
- CRM effect: note/activity present for the business key (or an explicit “skipped with reason”).
When those three disagree, you have a real incident. Under the old poll model, a green schedule often hid incidents with no ticket.
A second lesson: idempotency is a product requirement, not a cleanup script. Two AI notes for one call kills trust faster than any latency SLA can save you.
Takeaway for operators
- Prefer events over polls for meeting → CRM notes. Schedules are fine for backfill and reconciliation, not for the main path.
- Design a stable business key and write CRM updates idempotently. Assume every event can arrive twice.
- Monitor ingress, processing, and CRM effect separately. A green webhook is not the same as a note the RevOps lead can use.
---
*Dealing with this in production? The AI Systems Diagnostic is the starting point.*

