Late-accept follow-up: auto-fire, heal-tick backstop, and the May 7 historical backfill

Overview

WarmySender is a 4-pillar outreach platform — Cold Emailing, Email Warmup, LinkedIn Outreach, and Multichannel sequences. This page is part of the LinkedIn Outreach pillar and explains the safety net that catches LinkedIn invitation accepts that arrive after your campaign workflow has already moved past the wait_accept step ("late accepts").

Three layers protect the customer-facing latency from accept to first follow-up message:

  1. Webhook-time auto-fire (primary, V15+) — when the late-accept webhook lands, our handler immediately enqueues the follow-up via the existing campaign_send_jobs pipeline.
  2. 6-hour heal-tick backstop — a recurring sweeper picks up edge cases the auto-fire missed (account was disconnected at webhook time, campaign was paused, etc.).
  3. May 7, 2026 historical backfill (V16) — a one-shot script that scans for prospects whose accepts arrived BEFORE the V15 auto-fire wiring landed and enqueues their missing follow-ups via the same safety-gated pipeline.

All three paths route through the same campaign_send_jobs queue, so every per-account safety gate (daily cap, ramp ceiling, cooldown, sending-window clamp) applies to every dispatch regardless of which path triggered it.

Webhook-time auto-fire (primary path, V15+)

When the LinkedIn integration delivers a late-accept webhook, our handler runs three actions in a single request:

  1. Stamp late_accept_observed_at on the matched prospect (the SAFE sentinel that NEVER touches linkedin_accepted_at, linkedin_status, or the workflow advance).
  2. Call the auto-fire dispatcher, which walks the campaign step graph to find the right post-accept message step and inserts a campaign_send_jobs row.
  3. Emit a structured audit event with metadata.source = 'late_accept_webhook_auto_fire' AND metadata.branch_taken = 'post_acceptance_followup_dispatched' (V16 normalized — both fields together are the canonical query for late-accept dispatch volume).

From your perspective, an accept that lands inside your sending window with cap headroom produces a follow-up message within minutes. See Why a late LinkedIn accept may take time to message for the worked-example timeline.

Idempotency is double-protected: the dispatcher's late_accept_followup_sent_at IS NULL guard at enqueue time, plus the partial unique index on campaign_send_jobs at the database level. A re-fire of the same webhook (network retry, dedup race, etc.) is a no-op.

6-hour heal-tick backstop

The recurring heal scheduler runs every 6 hours and catches what the auto-fire couldn't enqueue. Common triggers:

The heal-tick has a hard cap of 200 rows per 6-hour tick. With backlogs in the hundreds, the backstop alone takes days to drain — which is why the May 7 historical backfill exists as a one-shot.

The May 7, 2026 historical backfill (V16)

Before the V15 auto-fire wiring landed (May 7, 2026), every late accept relied on the 6-hour heal-tick to dispatch its follow-up. That worked, but the rate-cap of 200 rows per 6-hour tick combined with backlogs in the hundreds meant some prospects waited 100+ hours between accept and first follow-up — far longer than any reasonable user expectation.

The backfill scans for prospects with this pattern:

For each match, the backfill calls the same canonical helper the live engine uses (enqueuePostAcceptanceNextStep) which routes through ensureNextJobExists, which respects every per-account safety gate at job execution time.

Account-safety caps on the backfill

Two hard caps apply, both enforced at the SQL predicate level so the cap cannot be bypassed by a bug in the application code:

Both caps preserve the LinkedIn-side safety invariant CLAUDE.md describes: account safety always wins over speed, throughput, or user intent. A banned LinkedIn account is unrecoverable; we err on the side of caution at every layer.

Rows the backfill enqueues still go through ensureNextJobExists at job execution time, so even within the per-day cap of 50, every dispatch is gated by your campaign's sending window, the per-account ramp ceiling (especially conservative on days 1–14 of warmup), and any active cooldown. The backfill cannot cause an over-send.

What users see after the backfill runs

Customer-facing dashboard changes after a backfill run:

You will NOT see:

Why named backfills (and not silent re-stamping)

Every WarmySender backfill is a named, dated, opt-in script with a DRY-RUN default and explicit CONFIRM=yes commit gate. Three reasons:

This is the same discipline behind every LinkedIn-side change at WarmySender: explicit, capped, observable, reversible.

Common questions

My follow-up landed within seconds of the accept — was that the auto-fire or the backfill?

The auto-fire (V15+ webhook-time path). The May 7 backfill targets prospects whose accepts arrived BEFORE V15 landed; if your accept arrived after, the auto-fire path handled it. You can tell which by checking the audit event tags: late_accept_webhook_auto_fire = V15+ webhook path; pre_ll333_backfill_2026_05_07 = V16 backfill; late_accept_auto_fire = heal-tick origin.

My prospect accepted weeks ago and just got a follow-up — was something broken?

Yes, but not catastrophically. Pre-V15, late accepts relied on the 6-hour heal-tick (rate-capped 200 rows/tick) which couldn't keep up with backlogs in the hundreds. Some prospects waited 100+ hours between accept and follow-up. The May 7, 2026 V16 backfill picked up your prospect from this stuck cohort and enqueued the missing follow-up via the same safety-gated pipeline the live engine uses. We're sorry for the delay — it was caused by the rate-cap on the backstop heal-tick, not by your campaign configuration.

Will the backfill send messages outside my campaign's sending window?

No. The backfill enqueues jobs into campaign_send_jobs, which the engine then runs through the same safety gates as every other dispatch. If the engine picks up a backfilled job at 23:00 and your sending window is 09:00–17:00, the job is automatically deferred to 09:00 the next morning. Your authored intent always wins.

Will the backfill exceed my LinkedIn daily message cap?

No. Two layers protect this: (1) the backfill's own per-account/day cap of 50 enqueues prevents queueing more than 50 follow-ups against any single account in any given run; (2) at execution time, the engine reads your account's current daily counter and defers any job that would exceed the cap. The combined effect is that even a 1000-prospect backfill on one account drains gradually over many days at most 50/day, never burst.

Why was my account specifically affected?

Pre-V15, every late accept on every account on the platform relied on the 6-hour heal-tick. Accounts with high invite volume + a high late-accept rate (typically because of a longer wait_accept timeout, OR many accepts arriving outside the original window) accumulated the largest backlogs. Sales Nav-heavy accounts and accounts with longer-than-default wait windows were over-represented in the May 7 cohort. The V15 fix removes the bottleneck for everyone going forward; the backfill drains the historical pile-up.

How can I see which of my prospects were touched by the backfill?

Email hello@warmysender.com with your workspace name and we'll send a CSV export of all prospects whose follow-ups were enqueued by the backfill. The data lives in linkedin_events with metadata.source = 'pre_ll333_backfill_2026_05_07' and can be exported per workspace.

Is this related to the May 7 V16 webhook source-tag fix and the auto-resubscribe?

Yes — both are part of the same V16 batch. The source-tag normalization made dashboard queries on late-accept dispatch volume reliable (queries on the canonical source + branch_taken pair now match every event, where pre-V16 about half were missed because the source tag varied). The webhook auto-resubscribe ensures customer accounts stay observable when an upstream webhook source drops — see Why am I still getting re-login emails when my account shows Connected? for the full picture.

If V15 is the fix, why do we need the backfill?

V15 fixes the GOING-FORWARD path — every NEW late accept after May 7 uses the webhook-time auto-fire. But prospects whose accepts arrived BEFORE May 7 are stuck in the rate-capped heal-tick queue. The backfill is the one-shot drainage of that historical cohort. After the backfill completes, the heal-tick reverts to its low-volume backstop role (most ticks find 0 rows) and steady-state dispatch is purely webhook-driven.

Still have questions? Email hello@warmysender.com with your workspace name and we'll dig into the specific prospects and timing.