For ScsDriver (my $5.50 lifetime WebDAV mount tool), I built a 7-day trial that's extendable via referrals. After 8 months, I have ~12k invite events in my logs. About 8% of them are clearly fake — from invite farms, bot accounts, or one-click-delete trials.
Here are the 4 detection heuristics I tried and how they stacked up.
Heuristic 1: Same IP, multiple signups within 24h
Hypothesis: Multiple invite activations from the same IP signal a farm.
Implementation: GROUP BY signup_ip WHERE COUNT(*) > 5 IN 24h.
False positive rate: 11%. Busted users behind CGNAT, university networks, shared corporate proxies.
True positive rate: Caught ~40% of obvious farms. Missed sophisticated farms using residential proxies.
Verdict: Start here, but don't make this your primary detector. It's too noisy.
Heuristic 2: Account age < 24h at time of invite
Hypothesis: Real users invite after using the product. Fake accounts invite immediately upon signup.
Implementation: (account_age_at_invite < 24h) flag.
False positive rate: 7%. Some legitimate new users do invite on day 1 ("hey friend, just signed up for this, try it").
True positive rate: 40% recall. Caught the lazy farm pattern.
Verdict: Better than IP. Still not great as primary signal. The 7% FP rate creates too many disputes.
Heuristic 3: Time-to-second-action < 60s
Hypothesis: Farms automate the install → claim-invite chain in under 60 seconds. Humans take longer.
Implementation: Track time between signup_complete and invite_claim.
False positive rate: 4%. Very few real users complete the full chain that fast.
True positive rate: 55%. Caught the bulk of automated farms.
Verdict: Strong signal. Combine with account_age for compounding accuracy.
Heuristic 4: Activation signal scoring (the only one that worked)
Hypothesis: Real users use the product. Fake users don't. The product's own telemetry is the strongest signal.
Implementation: Score each invitee 0-10 based on:
- Did they create at least 1 file? (+2)
- Did they keep the app open > 5 minutes? (+2)
- Did they restart the app at least once? (+2)
- Did they use features beyond the trial tutorial? (+2)
- Did they hit any error in the logs? (+1)
- Did they come back on day 2? (+1)
If score < 3, the invite is "fake-tier" — discount the inviter's reward.
False positive rate: 1.5%. The signal is so specific to real usage that it almost never trips on legitimate users.
True positive rate: 89% recall on actual farms. The signal catches patterns heuristics 1-3 miss.
Verdict: This is the one that worked. Activate it.
Why heuristics 1-3 are not enough alone
Each catches 40-55% of farms. But they're catching different farms. Combining them gets you ~75% recall. The activation signal catches 89% on its own.
Activation signal also has a property the others don't: it's silent. False positives don't feel policed because the discount is faceless. Users in the 1.5% FP rate just see "your invite rewarded less than expected" without knowing why.
How I combine them in production
def classify_invite(invite):
score = 0
if invite.invitee_activation_score < 3:
return 'fake'
if invite.account_age_at_invite < 86400 and invite.ttl_to_action < 60:
return 'fake'
if invite.ip_dup_count > 10:
return 'suspect' # not auto-fake, but watch
return 'real'
The primary signal is activation score. The fast-fresh combo is secondary. IP cluster is for monitoring, not enforcement.
What I'd add if I had more data
A graph signal: if invitee A's invites only go to accounts that themselves invite other accounts in a tight cluster, that's a farm topology. I don't have enough data yet to detect this reliably.
A timing signal: farms tend to invite at regular intervals (every 30 minutes, every hour). Legitimate users invite at irregular times. I have a draft of this but haven't validated.
The takeaway
Heuristic-based detection alone gets you 60-75% recall. Activation-signal detection gets you 90% with much lower FP rate.
The boring truth about fraud: the product knows best. Anyone using your product is probably real. Anyone who isn't, isn't.
Build your detection on the product's own signals. Treat network/IP/account-age heuristics as supporting evidence, not primary.
Top comments (0)