{"slug": "m-12-my-referral-system-slept-for-3-days-here-s-the-sql-trigger-that-woke-it-up", "title": "'m 12. My referral system slept for 3 days — here's the SQL trigger that woke it up", "summary": "Harun, a 12-year-old developer, built KODA, an AI coding mentor, entirely on a POCO C55 Android phone. He discovered that his referral system had never fired because the client-side code only attached referrals within a 10-minute window, but users often confirmed their emails hours later. He fixed it by extending the window to 48 hours and moving the logic into a database trigger that automatically increments referral counts and grants ambassador status, bypassing Row Level Security restrictions.", "body_md": "Quick recap if you're new: I'm Harun, 12 years old, no laptop. I build **KODA** — an AI coding mentor — entirely on a POCO C55 Android phone. Vanilla JS + Supabase + Groq + Netlify.\n\nThis week I opened my database expecting a growth story. I found a mystery instead.\n\n| username | referred_by | referral_count | is_ambassador |\n|---|---|---|---|\n| me (founder) | NULL | 0 | false |\n| my brother | NULL | 0 | false |\n| my 2 friends | NULL | 0 | false |\n| 4 strangers | NULL | 0 | false |\n\n8 users. **Zero referrals. Zero ambassadors.** The \"Invite a friend, unlock Gold Mode\" loop I was so proud of? It had never fired. Not once.\n\nNo error messages. No red banners. Just... silence. Silent failures are the worst failures.\n\nMy client code only attached a referral if the account was less than 10 minutes old when the user logged in:\n\n```\nif (ref !== me.id && ageMs < 10 * 60 * 1000) {\n  await db.from('profiles').update({ referred_by: ref })\n    .eq('id', me.id).is('referred_by', null);\n}\n```\n\nBut my signup flow says: *\"check your inbox, tap the confirmation link, THEN sign in.\"*\n\nHumans don't do that in 10 minutes. They confirm their email hours later. By then `ageMs`\n\nis huge and the referral dies silently. Every single time.\n\n**Fix:** a 48-hour window.\n\n```\nif (ref !== me.id && ageMs < 48 * 60 * 60 * 1000) { ... }\n```\n\nHere's the embarrassing part. The client wrote `referred_by`\n\non the NEW user... and that was it. Nothing anywhere incremented the referrer's `referral_count`\n\nor flipped `is_ambassador = true`\n\n.\n\nAnd it *can't* be done from the client anyway — Row Level Security (good security!) blocks users from editing other people's rows.\n\n**Fix:** move the logic into the database. A `security definer`\n\ntrigger that powers up the referrer automatically:\n\n```\ncreate or replace function public.bump_referrer()\nreturns trigger language plpgsql security definer\nset search_path = public as $$\nbegin\n  if new.referred_by is not null\n     and new.referred_by <> new.id\n     and (old is null or old.referred_by is null) then\n    update public.profiles\n    set referral_count = coalesce(referral_count, 0) + 1,\n        is_ambassador = true\n    where id = new.referred_by;\n  end if;\n  return new;\nend; $$;\n\ndrop trigger if exists trg_bump_referrer on public.profiles;\ncreate trigger trg_bump_referrer\nafter insert or update of referred_by on public.profiles\nfor each row execute function public.bump_referrer();\n```\n\nNow when a referral lands, the database itself grants the Gold. No client code, no RLS fights. When RLS says \"no,\" move the logic to the database.\n\nOne deploy = one bundle. This bundle (v9) shipped with:\n\n`print(f'{bugs=} {count=}')`\n\n— yes, on Python 3.14, the current \"pi version.\"Why batch? Because every deploy costs attention and risk on a phone. Ship in bundles, test once, celebrate once.\n\nIf you're a senior dev: **roast my trigger in the comments.** I read every single word.\n\n*Built with ❤️ by Harun (age 12) on a POCO C55.*", "url": "https://wpnews.pro/news/m-12-my-referral-system-slept-for-3-days-here-s-the-sql-trigger-that-woke-it-up", "canonical_source": "https://dev.to/koda2026/m-12-my-referral-system-slept-for-3-days-heres-the-sql-trigger-that-woke-it-up-4375", "published_at": "2026-08-25 13:17:52+00:00", "updated_at": "2026-08-25 13:43:46.155490+00:00", "lang": "en", "topics": ["developer-tools", "ai-products"], "entities": ["Harun", "KODA", "POCO C55", "Supabase", "Groq", "Netlify"], "alternates": {"html": "https://wpnews.pro/news/m-12-my-referral-system-slept-for-3-days-here-s-the-sql-trigger-that-woke-it-up", "markdown": "https://wpnews.pro/news/m-12-my-referral-system-slept-for-3-days-here-s-the-sql-trigger-that-woke-it-up.md", "text": "https://wpnews.pro/news/m-12-my-referral-system-slept-for-3-days-here-s-the-sql-trigger-that-woke-it-up.txt", "jsonld": "https://wpnews.pro/news/m-12-my-referral-system-slept-for-3-days-here-s-the-sql-trigger-that-woke-it-up.jsonld"}}