Design Telegram bot broadcasts: subscriptions, rate limits, and retries
Turn notification broadcasts into pausable, resumable jobs with consent, 429 handling, bounded retries, unsubscribe state, failure classes, and progress.
“Send one notification to every subscriber each day” sounds like a loop, but a reliable broadcast is a resumable batch job. The bot must know who actually subscribed, which deliveries succeeded, when to pause for rate limits, and when to stop retrying after a user blocks it. Otherwise, a restart can cause either missed messages or duplicate notifications.
Telegram's official bot introduction states that bots cannot start conversations with users who have never contacted them; a user must message the bot first or add it to a group. grammY's flood-limit guidance treats 429 as a normal control signal: send, wait when Telegram tells you to wait, and retry instead of ignoring errors or using unbounded concurrency.
Build a subscription list, not a username import
Having a username does not mean a bot can send that account a message. A useful subscription record includes:
- a stable chat identifier, not only a changeable username;
- the topics or notification types the user explicitly selected;
- subscription time, language, and time zone;
- the latest delivery result;
- unsubscribe, blocked, or permanent-failure status.
Offer clear /subscribe, /unsubscribe, and /status paths. For marketing or frequent notifications, explain the content and cadence at opt-in instead of treating anyone who once pressed Start as consenting to every broadcast.
Persist each broadcast as a job
Do not store only “the loop is currently at recipient 417.” Persist a broadcast job and a delivery record for each recipient.
| Object | Useful fields | | --- | --- | | Broadcast job | Content version, audience rule, created time, state, started and completed times | | Recipient delivery | Job ID, chat ID, pending / sent / retry / failed, attempt count, last error | | Message content | Reviewable snapshot or version ID so recovery cannot silently replace it |
After a restart, the worker can continue pending and retry deliveries rather than starting from the beginning. Job ID plus chat ID also forms a useful idempotency key so one broadcast cannot create two successful deliveries for the same recipient.
Treat 429 as an instruction to wait
Telegram can return a flood-control error when requests arrive too quickly. A reliable sender reads the returned delay, waits, and retries with controlled concurrency. grammY's auto-retry documentation explains that errors carrying retry_after should wait for that duration, while network and server errors generally need bounded exponential backoff.
The requirement should distinguish:
- rate limiting: wait and retry; do not mark a permanent failure;
- temporary network or server failure: use bounded backoff;
- blocked or unauthorized chat: stop sending to that chat and update its subscription;
- invalid content or parameters: stop the job and repair the template;
- unknown result: inspect local delivery state instead of blindly repeating.
A single fixed sleep does not model every limit, and a large fan-out of parallel calls makes recovery harder. Throughput can change. Respect Telegram's returned delay and make the job pausable and resumable.
Pair retries with deduplication
Telegram may accept a send request while the caller loses the response. Immediately repeating the call can create two notifications. At the business layer:
- allow only one active delivery for each job and recipient;
- record the attempt and content version before sending;
- route unknown outcomes to delayed confirmation or review, not a tight retry loop;
- include a visible notification date or identifier where occasional duplicates matter;
- resume only deliveries that are neither successful nor permanently failed.
One API call cannot give an entire batch exactly-once semantics. A practical target is to make duplicates detectable, bounded, and explainable.
Give operators preview, pause, and useful counts
A broadcast bot should support:
- sending a preview to test accounts;
- showing estimated audience, topic, language, and content version;
- requiring confirmation before the job starts;
- pausing without claiming new pending deliveries;
- resuming from stored progress;
- counting sent, retrying, permanently failed, and unsubscribed recipients separately;
- aggregating failure reasons without exposing a recipient list in a group chat.
If notifications respect time zones or quiet hours, split the audience by subscriber settings rather than the server clock. Whether Telegram Serverless provides a timer or requires an external scheduler must be checked against current platform capabilities. Code that can calculate a time does not prove the runtime will wake itself then.
A requirement template you can adapt
Build a subscription notification bot. Users can subscribe, view status, and unsubscribe. An administrator creates a draft, selects topic and language, sends a preview, and confirms before starting. Persist every broadcast as a job and deduplicate by job and chat; after a restart, continue only unfinished recipients. On 429, wait for the returned duration before retrying. Use bounded backoff for temporary failures. Stop retrying chats that blocked the bot or are no longer authorized. The administrator can pause, resume, and view counts for sent, retrying, permanently failed, and unsubscribed deliveries.
Acceptance checklist
- A username that never started the bot is not treated as a deliverable subscriber.
- Repeated subscription creates one active subscription.
- Resuming the same job twice does not resend to successful recipients.
- A simulated 429 pauses and resumes from the same progress.
- A network failure cannot create an unlimited tight retry loop.
- Unsubscribed or blocked users do not enter later jobs.
- Pause stops new deliveries; resume preserves progress.
- Editing content creates a new version instead of mutating an active job.
- Summary counts reconcile with delivery-state details.
How this relates to BotFatherV2
BotFatherV2 creates and modifies Telegram Serverless bots through an AI conversation. Defining subscription state, broadcast jobs, unsubscribe behavior, rate limiting, and failure classes turns “send notifications” into a testable requirement.
This does not mean the platform already provides arbitrary queues, timers, external databases, or high-volume paid broadcasting. Public documentation describes a fixed SDK surface; scheduling, third-party services, and costs need separate verification. The initial AI-development release also does not add paid-AI runtime capabilities. BotFatherV2 is independent and is not affiliated with Telegram's official BotFather.
Sources
- Telegram, Bots: An introduction for developers, accessed October 13, 2026.
- grammY, Scaling Up IV: Flood Limits, accessed October 13, 2026.
- grammY, Retry API Requests, accessed October 13, 2026.
- BitBear Studio, Develop with AI, accessed October 13, 2026.