Attribution pipelines fail quietly. Nobody pages you when a campaign is under-reported by 8% — the dashboard just looks slightly wrong forever, and eventually someone makes a budget decision based on bad numbers.
Start from the event, not the dashboard
The instinct is to design backward from the report you want to show. Resist it. Design forward from a single, strict event schema:
- A stable event name, defined once and versioned deliberately.
- A deduplication key that survives retries and replays.
- A timestamp with a defined source of truth — client-observed vs. server-received.
- An explicit schema version on every record.
Everything downstream — attribution windows, channel grouping, CRM joins — is a transformation on top of that stream, never a patch to it.
Idempotency is the whole game
Marketing events arrive late, arrive twice, and arrive out of order — retried webhooks, offline mobile queues, ad-platform callbacks that fire on their own schedule. If your ingestion isn't idempotent on the dedup key, every retry becomes a phantom conversion.
-- upsert at the ingestion boundary, keyed for idempotencyINSERT INTO raw_events (event_id, source, payload, received_at)VALUES ($1, $2, $3, now())ON CONFLICT (event_id, source) DO NOTHING;The rest of the pipeline treats storage as append-only and immutable — attribution windows are computed as a view over raw events, never baked in at write time.
Attribution windows are a business decision, not a technical one
Last-click, first-click, and multi-touch models will all disagree with each other on the same underlying data. Pick a default model, but keep raw touchpoints intact so you can recompute under a different model later without re-instrumenting anything.
Store raw events, compute attribution as a view. That single decision is what separates a pipeline that survives a strategy change from one that requires a rewrite.
What actually breaks in production
In my experience it's rarely the attribution logic itself. It's clock skew between client and server timestamps, PII scrubbing rules changing after launch, and CRM record matching silently degrading as email formats drift. Build monitoring around volume anomalies and match-rate, not just uptime.