Twenty requests, one row. Replies and bookings into a CRM exactly once.
n8n workflows that move LinkedIn, email and Calendly events into the CRM without losing or doubling any of them, and a CRM switch with no downtime.
Delivered09/2026
- Client
- A Nordic B2B SaaS (name withheld)
- Role
- Built the automations, with Tim N.
- Period
- 08/2026 → 09/2026
- Proof
- 8 claims
- With
- Tim N.
- Stack
- n8n · Node.js · Python · CRM API · Slack
- 1ProblemReplies were missed, sent to Slack twice, or never reached the CRM.
- 2BuildAn atomic claim per event, CRM written before Slack, and a 24-hour shadow run.
- 3Result0 errors in the shadow run and 2,075 duplicate companies merged.
Problem
A Nordic B2B SaaS ran outreach on LinkedIn and email and booked calls through Calendly. Replies were missed, reached Slack twice, or never made it into the CRM, and the team was moving to a new CRM at the same time.
Build
Every event gets a key, and an atomic claim on an n8n Data Table lets only the first copy through, so 20 concurrent requests write 1 row P1. The CRM is written before Slack, and only replies that need action reach a person.
I rebuilt the workflows that wrote to the old CRM and ran the new ones in shadow mode for 24 hours, sending nothing, before the switch P2.
Route
Replies from LinkedIn and email outreach and Calendly bookings arrive as webhooks, sometimes more than once.
- Normal run01DoneReplies from LinkedIn and email outreach and Calendly bookings arrive as webhooks, sometimes more than once.
- 02DoneEach event gets a key. An atomic claim on a Data Table lets only the first copy through: 20 concurrent requests write 1 row.
- 03DoneRetries and duplicates stop here instead of reaching Slack twice.
- 04DoneReplies are classified into six labels, in English and Finnish. Rules decide first.
- 05DoneThe CRM is written first, so nothing that reached Slack is missing from the CRM.
- 06DoneOnly replies that need action go to Slack and a person. Declines are stored in the CRM and stop there.
- Something breaks07FailedOne workflow reported success while Slack received nothing. Its filter required a campaign field that real reply events do not carry.
- Recovery08DoneI fixed the condition and replayed exactly the 3 events that were lost. The tests now run on real payloads, not sample ones.
Result
The switch went through with 0 errors in the shadow run P2. I backfilled 72 missed events P3, merged 2,075 duplicate companies P4, and 199 of 199 workflow tests pass P5.
Along the way I found why €1,704.80 of LinkedIn Ads had brought 0 leads: the lead forms had been rejected and a tracking tag was missing, and the campaign was stopped P6.
What went wrong
One workflow reported success while Slack received nothing. Its filter required a campaign field that real reply events don't carry. I fixed the condition and replayed exactly the 3 events that were lost P7. Since then the tests run on real payloads, not sample ones.
Limits
The client is not named. Opt-outs can never be overwritten by a sync, which left some merges for a person to decide.
My part
Tim N. leads the client relationship. I wrote 239 of the project's 241 commits P8: the claim pattern, the cutover, the backfill and the tests.
My commits in the project repository239 / 241 · 99%
Proof of delivery · NLV-26-CRM
| # | Claim | Evidence | As of | Confidence |
|---|---|---|---|---|
| P1 | 20 concurrent requests for the same event write exactly 1 row. |
| 16 Oct 2026 | I hold the artifact |
| P2 | The new CRM ran in shadow mode for 24 hours with 0 errors before the switch. |
| 16 Oct 2026 | I hold the artifact |
| P3 | Backfilled 72 missed events with 0 errors. |
| 16 Oct 2026 | I hold the artifact |
| P4 | Merged 2,075 duplicate companies. |
| 16 Oct 2026 | I hold the artifact |
| P5 | 199 of 199 workflow tests pass. |
| 22 Sept 2026 | I hold the artifact |
| P6 | Found why €1,704.80 of LinkedIn Ads brought 0 leads (rejected lead forms and a missing tag), and the campaign was stopped. |
| 16 Oct 2026 | I hold the artifact |
| P7 | A filter that real reply payloads failed had dropped events silently; I fixed it and replayed exactly the 3 that were lost. |
| 16 Oct 2026 | I hold the artifact |
| P8 | 239 of the project's 241 commits are mine. |
| 21 Oct 2026 | I hold the artifact |