A signup notification is worth having for the feeling: someone just showed up, and you hear about it before anyone else. Telegram carries that feeling better than Slack or email. It's the app already open on your phone, and a message there gets read whether you're at your desk or standing in line for coffee.
What makes it worth doing well is the distance between the event and the message. A signup, the instant it fires, is an email address and a timestamp. What you actually want buzzing in your pocket is a name, the company behind it, and the quiet confidence that it only went off because it was worth going off for. Closing that distance is the whole job.
the message you'd actually want
Start from the notification you'd be glad to receive. It names a person, not an address — Ada Lovelace from Analytical Engines tells you something the moment you glance at it, where a.lovelace@example.io just means more work later. It arrives once, not twice when someone double-taps the button. It stays silent for the bot that found your form and the disposable address on its ninth free account. And when it's a real prospect, it says so, so a glance is enough to know whether to put your coffee down.
None of that is in the signup event. All of it lives in the gap between the event arriving and the message going out — a gap that's otherwise a single fetch call with no room to think.
what telegram asks of you
Telegram adds a few rules of its own, worth knowing before you wire anything up. A bot can never message you first: you send it /start, and only then may it reply. So every message needs a chat_id that the Telegram app shows you nowhere — the usual ritual is to /start the bot, call getUpdates, and read your own id out of the JSON. Group ids come back negative, and if Telegram promotes a group to a supergroup the id changes underneath you. Channels need the bot added as an administrator before it can post at all.
Two more surface once it's running. Messages use MarkdownV2, which reserves _, *, . and a dozen other characters — the first email with an underscore returns a 400 and no message. And a bot may send at most one message per second to a single chat, so a signup spike answered by a naive retry becomes a wall of 429s. None of this is a reason to skip Telegram. It's the reason the send is worth doing somewhere that handles it once, instead of in a fetch call you copy into the next project.
the steps that close the gap
Put a pipeline between the signup and the send. dedupe collapses the double-submit into one message. enrich.person turns the bare email into a name and the company behind the domain. classify hands the enriched signup to a model with a typed set of labels and writes the verdict back as a field, and filter drops the spam before your phone ever moves. throttle is the one Telegram practically designed for you: its per-chat limit is one message a second, so pacing the pipe isn't hygiene here, it's how you never meet a 429.
representation
01source
02pipeline · 5 steps
- 01CTLdedupekey $event.email · within 1h
- 02ENRenrich.person$event.email → name + company
- 03ENRclassifyintent · hot_lead / normal / spam
- 04CTLfilterdrop unless $classify.intent != "spam"
- 05CTLthrottlemax 30 per 1m · key telegram
03destinations · 2
- totelegramTelegramchat@founders
- towarehouse.pgPostgrestableevents.signups
What lands on your phone is *Ada Lovelace* — Analytical Engines with the model's read attached, not new signup: a.lovelace@example.io. Spam never makes a sound. Postgres keeps every signup, pinged or not. And the chat id, the escaping, and the rate limit all live in the pipe — not in a handler you have to redeploy to change.
how ingestlayer does this
Telegram is a first-class destination: paste the BotFather token once and the webhook is registered and verified for you. Send /start to the bot — or add it to the group — and you pick the chat from a list. No getUpdates spelunking, and reserved MarkdownV2 characters in your field values are escaped automatically. The dedupe, enrich, classify, filter, and throttle steps are the same actions from the Discord version of this post — stack them once, fan out to as many chats as you like.
Connect a bot and send an event — the quickstart is an npm install and one track() call.