Signal Feed Engine
Status: production. Runs every day without me.
Problem
Most outbound lists answer "who fits" and stop there. Fit without timing is how you end up emailing a company nine months before they care. I wanted a machine that watches for the events that make a company reachable this week, not eventually.
How it runs
Two loops on a cron schedule:
- A weekly discovery loop finds net-new companies through signal legs: hiring activity, leadership changes, funding filings, tech-stack changes, review velocity, and a couple of legs I keep to myself.
- A daily refresh loop re-scores everything already in the pool. Signals decay, so a company that was hot three weeks ago and did nothing since drifts back down the ranking.
Every lead lands in a Postgres database with its signal history attached, gets scored, then flows into enrichment (see the enrichment waterfall) before any campaign touches it. Suppression runs before delivery: competitors, existing conversations, and gateway-fronted domains get routed out or rerouted to LinkedIn.
One rule I hold on every campaign: pair an event-driven list with a static ICP list. The event layer gives you the why-now, the static layer gives you volume. Running either one alone is the most common mistake I see in other people's outbound.
Stack
Node scripts on an always-on VM, Postgres (Supabase), a self-hosted scraping worker with a seven-tier fetch cascade, and a handful of data vendors ordered free-first. No Clay in this pipeline.
History
This started as a paid data product with its own storefront. I shelved the storefront in July 2026 when I moved the business to pay-per-meeting, and kept the engine, because the thing that made the product work is the same thing that fills my own campaigns. The engine is the fulfillment layer now.
Worth stealing
The decay-and-rescore loop. A static score goes stale silently; a daily re-score turns your database into a ranked queue you can trust on any given morning.