Implementation worksheet · 5 min read
A Behavioral Event Freshness Policy for Campaigns
Write a freshness policy with one row per campaign type: the triggering event, the maximum age at which acting on it is still sensible (cart abandonment: hours; feature-adoption nudge: days; win-back: weeks), what the campaign should do when data arrives late (skip, not send stale), and the staleness check the send actually performs. The failure this prevents is structural: pipelines batch, retry and backfill, so events routinely arrive hours or days old — and a campaign that fires on arrival time rather than event time congratulates users on the purchase they made last Tuesday. Freshness is a property of the campaign's meaning, not of the pipeline's speed; the policy is where the two are reconciled.
Teams debate pipeline latency in engineering terms (minutes vs seconds) while campaigns fail on a different axis entirely: the event was fresh when it happened and stale when the batch landed. The policy makes each campaign declare what 'too old to act on' means — a question with different answers per campaign and no answer at all in most orgs.
Put it into practice
1. Classify campaigns by decay speed
Interruption-recovery (abandoned cart, failed payment) decays in hours. Momentum nudges (feature adoption, onboarding steps) decay in days. State-change campaigns (plan change, renewal window) barely decay. One column: how long until acting looks weird?
2. Distinguish event time from arrival time
Every trigger evaluates event_timestamp, never ingestion time. This one convention eliminates the largest stale-trigger class — backfills and retries re-delivering old events as if new.
3. Define the late-arrival behavior as skip-and-log
An abandonment event older than its freshness window skips the send and increments a staleness counter. Sending late is worse than not sending: the user either completed the action (message reads broken) or moved on (message reads creepy).
4. Gate re-computed audiences the same way
Batch audience refreshes re-qualify users from old events — the segment equivalent of a stale trigger. Audience entry conditions carry the same max-age clause as triggers, or the weekly refresh quietly resurrects last month's intent.
5. Alert on staleness rates, not just pipeline lag
A rising skipped-for-staleness counter is the early warning that a pipeline slowed below a campaign's needs — visible in campaign terms before anyone reads an infra dashboard. Review it weekly next to campaign performance.
Freshness policy (one row per campaign type)
Copy this structure into your review document and record your observed result for each row.
| Campaign | Trigger event | Max age | On late arrival |
|---|---|---|---|
| Cart abandonment | cart_abandoned | 6 hours | skip + count |
| Failed payment recovery | payment_failed | 24 hours | send (state-checked first) |
| Feature adoption nudge | feature_first_use | 72 hours | skip |
| Onboarding step reminder | step_completed | 48 hours | re-check current state, then send |
| Win-back | last_active threshold | re-verified at send | re-query, never cached |
A failure worth checking
The backfill blast: a pipeline outage is fixed, three days of events replay in an hour, and every time-sensitive campaign fires on all of them at once — thousands of 'you left something in your cart' messages about carts resolved days ago. The pipeline did nothing wrong; the campaigns had no concept of event age. One max-age clause per trigger converts a replay from an incident into a log line.
Common questions
Shouldn't the pipeline just be faster?
Speed helps and doesn't substitute: retries, backfills and vendor outages guarantee occasional late delivery forever. The policy makes campaigns correct under real conditions; latency work makes staleness rarer. Do both, in that order.
Who sets the max-age numbers?
The campaign owner proposes from user experience ('when does this message become weird?'), data engineering confirms feasibility. The number is a product decision wearing a technical costume — which is why it was never written down before.
Basis and scope
This is a proposed implementation method using illustrative examples, not a measured benchmark or a customer case study. Prepared with AI assistance. Validate product-specific behavior against current documentation and your own test environment.