Why Telegram Bot API integration breaks in production
Integrating the Telegram Bot API into a mobile app almost always goes smoothly on a test bot with a single active user — and falls apart when production has thousands of devices, unstable mobile internet, and multiple backend instances.
The main reason is that the Bot API works on a long polling or webhook model: the app receives updates through a server rather than directly, and any failure in that chain turns into lost notifications or duplicates.
A classic failure is lost updates. If the server acknowledges an update before it is actually delivered to the device, and the app has gone to the background or lost its network connection at that moment, the message disappears irrevocably.
Telegram considers it delivered and will not send it again. The opposite situation is duplicates: on redelivery after a timeout, the same update is processed twice, and the user sees two identical pushes or two entries in the history.
A third source of failures is state divergence between the client and the bot. The user tapped a button in the app, the bot updated the status on the server, but the mobile client stayed on the old version of the screen.
Without explicit state synchronization, such discrepancies accumulate and lead to conflicts: the bot considers a request closed, while the app shows it as active.
Let's break down how this is addressed: idempotent update processing, reliable notification delivery with confirmation on the device side, and a single source of truth for state.
What a managed bot integration into an application provides
Notification deliverability instead of "sent and hoping"
A notification sent via a bot goes through a chain: application → intermediary service → Telegram Bot API → device.
A break at any step used to look like "the message got lost": the user didn't find out about the order status, support received a ticket and manually figured out what happened.
A managed integration records the result of each send and retries delivery with an increasing delay until it receives confirmation. The share of delivered notifications reaches a steady plateau instead of dipping during peak load hours.
Support response time and the class of failures on restart
When delivery status is visible in a shared dashboard, the operator responds based on facts, not guesswork: response time is cut from hours to minutes, because there's no need to pull logs and ask the user again.
Separately, the class of failures on restart of the intermediary service is closed — the queue is not lost, unprocessed requests are restored from the state store, and after a restart not a single notification goes into the void.
Support workload and predictability
Every eliminated class of failures is a stream of identical requests that simply disappears.
Support stops being a "failure receiver" and deals with substantive questions, while the team sees delivery and response time metrics as ordinary operational indicators rather than as an incident. Let's break down how this is structured in the configuration and on the application side.
Connection methods: comparison of technical options
Connecting a bot to an application is always a choice between two update delivery modes and one intermediary.
Webhook mode: the platform itself sends each event to your address, latency is minimal, but a public address with a valid certificate is required, along with a handler that responds quickly — otherwise the platform accumulates retries and eventually disables delivery.
Update polling mode: the application itself periodically requests accumulated events, no public address is needed, but latency and extra traffic appear, and with multiple service instances events begin to duplicate.
An intermediary service removes some of these limitations: it receives the webhook, queues events, and serves them to the application at a convenient pace.
This adds one node to the scheme, but provides resilience to peaks and allows updating the application without downtime in event reception.
| Option | When it fits | Limitations |
|---|---|---|
| Webhook directly | One service, stable public address, minimal latency needed | Requires a certificate and a fast response; if the address is unavailable, delivery is paused |
| Update polling | Development and debugging, closed environment without a public address | Delivery latency, extra requests, duplicates with multiple instances |
| Intermediary service | Multiple instances, peak loads, frequent releases | More complex scheme: queue and reprocessing control needed |
In practice, the choice is almost always determined by how many application instances run simultaneously and whether it has a public address.
If there is one instance and the address is stable — a direct webhook is simpler and faster; if the application scales or is deployed in a closed environment — an intermediary service pays for itself already at the first peaks. We leave update polling for debugging and local scenarios where latency is not critical.
Separately, it is worth building in failure handling: redelivery, idempotency of operations, and an event log, so that incident investigation takes minutes rather than hours.
How we handle integration: stages of engineering work
Integration with the Telegram Bot API almost never starts from a clean slate: the client already has a bot, a webhook or update polling, some scenarios live in the mobile app, and some on the server.
That is why the first step is not to write code, but to capture the current state and points of failure.
- Integration audit. We build a map: which Bot API methods are called, where the token is stored, who receives updates and how, how the app learns about the status of an order or payment. The output is a list of bottlenecks: races on repeated delivery, lack of idempotency, manual steps in support.
- Designing the exchange scheme. We determine who owns the state — the bot or the app backend — and separate the flows: user commands, notifications, service events. We fix the message format and retry rules so that the loss of a single update does not break the scenario.
- Webhook setup. We switch the bot from update polling to a webhook where predictable latency is needed, or keep polling for environments without a public address. We configure the secret header, IP restriction, and validation of incoming requests.
- Delivery verification. We run scenarios under load and with artificial failures: duplicate updates, timeouts, resending after a service crash. We check that the user does not receive two identical notifications and does not lose a single one.
- Assembly and connection in the app. We connect the mobile client to the bot backend: token-based authorization, account linking, handling scenarios when the user returns to the app from the chat.
- Observability. We set up call logging, delivery metrics, and alerts on error growth — so that a failure in the exchange is visible before users complain.
- Documentation handover. We provide operating regulations: how to update the token, what to do when the webhook address changes, how to read the logs, and where to look during an incident.
Each stage ends with an artifact that can be verified — a scheme, a configuration, or a test run. Describe your task — we will come back with an estimate and a work plan following these steps.
Artifacts and configuration that stay with you
Integrating a bot with an application is not a "set it and forget it" task: six months later, the team must understand how the integration works, where the keys are stored, and what to do in case of a failure. That is why we hand over the entire result as a working kit, not as verbal agreements.
- Integration diagram — how the application, the bot, and your backend exchange events: entry points, queues, handling of retries and timeouts.
- Bot configuration — webhook parameters, the list of commands, message templates, and keyboard layouts in a single file, not in a chat with the developer.
- Access policies — which services and people can read tokens, change settings, and view logs; scheduled rotation of secrets.
- Operations regulations — what we monitor, which alerts are critical, and how we roll back to the previous configuration in case of a failure.
- Team instructions — a step-by-step walkthrough of typical tasks: adding a command, changing the greeting, connecting a new scenario.
- Dependency map — which external services are involved and what will happen to the bot if they become unavailable.
- Change log — what changed in the configuration and when, so incidents can be investigated without archaeology.
The kit is designed for your engineer, not just for us: with these documents, a new developer gets up to speed on the project in days, not weeks. If you already have your own support team, we hand everything over in its format and run a walkthrough based on real scenarios.
Case study: how we reduced notification loss and response time
The client — a delivery service with an iOS and Android app — complained that customers were "disappearing": an order was placed, a courier was assigned, and the person only found out about it by opening the app.
Notifications were sent through standard channels, but some devices cut them off in the background, and some users simply disabled push notifications. Support was drowning in "where is my order" requests, and each such request cost operator time.
We analyzed the notification delivery funnel and saw two gaps: there was no confirmation that a message actually reached the device, and there was no fallback channel when the primary one went silent.
We added Telegram Bot API as a second channel: the bot is linked to an account via a one-time code from the app, and order statuses are also sent to the messenger.
The key thing is feedback: the system sees whether a message was delivered or not, and if the primary channel did not confirm delivery within the allotted time, it duplicates it to the bot.
What changed in numbers
| Metric | Before | After |
|---|---|---|
| Share of delivered notifications | ~70% | above 95% |
| Support response time to a "disappearance" | hours | minutes |
| "Where is my order" requests | baseline level | several times fewer |
We also specifically configured the bot not to duplicate what the person had already seen in the app — otherwise the channel quickly turns into spam and gets disabled.
The link is stored on our side, unlinking takes one tap, and when changing devices the user goes through linking again.
A few weeks after launch, the share of delivered notifications grew from roughly 70% to values above 95%, and the flow of requests about missing orders dropped severalfold — support switched to real problems instead of "check the status." This is the case where a second channel does not replace push notifications but insures them: the system knows the message got through and does not leave the customer in the dark.
How a webhook differs from polling updates and which to choose
The Telegram Bot API offers two ways to receive updates: the application itself polls the server using the getUpdates method, or Telegram itself sends updates to a specified address via setWebhook.
The difference is not cosmetic — it determines delivery latency, resilience under load, and the infrastructure you will have to maintain.
Polling works without a public address: the application periodically asks the server whether there are new messages and confirms processed ones via offset.
This is convenient for local debugging and isolated environments, but latency equals the polling interval, and with multiple application instances it is easy to get duplicates or gaps — state has to be synchronized separately.
A webhook flips the scheme: Telegram itself initiates a request to your handler, delivery latency drops to the time of a single network request, and horizontal scaling becomes honest — multiple instances behind a load balancer process the stream independently.
The price of a webhook is infrastructure requirements. You need a public address with a valid TLS certificate, and the handler must respond quickly and not block on long operations: we offload heavy logic to a queue and send Telegram confirmation immediately.
If the handler crashes or responds with an error, Telegram retries delivery — meaning processing must be idempotent by update_id, otherwise a retry will create a duplicate order or a double charge.
Resilience is solved differently. Polling survives restarts by storing the offset, but during downtime it accumulates a queue and hits request limits.
A webhook depends on the availability of your address: a short-term failure leads to retries, a prolonged one leads to the webhook being disabled, so monitoring and automatic reinstallation are needed.
For production with live traffic we choose a webhook; for debugging and isolated stands — polling; switching between modes is reversible and done with a single operation.
Technical concerns before starting integration
Before starting integration, engineering teams usually raise the same set of questions: how the bot will behave under load, what happens during a network failure, where to store the token, and whether an unsuccessful change can be rolled back without downtime. Below are answers to the ones that most often stall the decision.
How does the bot handle Telegram Bot API rate limits?
During mass mailings or peak activity, the bot hits the limit on the number of requests per second.
We set up a queue with exponential backoff and retries instead of hammering the API in a loop: when a response with a rate-limit exceeded code comes back, the request is returned to the queue with an increased interval.
This way the bot doesn't lose messages and doesn't get temporarily blocked. For mailings to tens of thousands of recipients, we add time-based sharding — delivery is stretched out, but it goes through completely.
What happens when the same event is delivered again?
Telegram may resend an update if it didn't receive confirmation. We make processing idempotent: each event is assigned an identifier, and a repeated delivery doesn't create a duplicate order, payment, or notification.
Identifiers are stored with a TTL sufficient to cover the redelivery window. This protects against double charges and duplicate messages to the user.
How safe is it to store the bot token?
The token is full access to the bot, so it must not be in the code or the repository. We keep it in a secure secrets store, inject it into the runtime environment at startup, and rotate it if a leak is suspected.
Access to the store is role-restricted, and all operations with the token are logged. In case of compromise, the token is revoked via a service bot, and a new one is issued without rebuilding the application.
Can integration changes be rolled back without downtime?
Yes. We roll out changes via a canary release: the new version of the handler receives a small share of traffic, metrics are compared with the current ones, and if they deviate, traffic is returned to the previous version.
The data schema is extended in a backward-compatible way, so a rollback doesn't require migrations. Users don't notice the switch — the bot keeps responding.
If your question isn't on the list — describe the task, and we'll come back with an estimate and a work plan.
Let's discuss your task and come back with an estimate
To make the review substantive rather than "just tell us in a nutshell," send us the inputs for your scenario: how the app is currently connected to the Telegram Bot API (webhook or polling), which bot events should reach the user in the app, and what already works. That's enough to estimate the scope and avoid sending you back and forth with clarifying questions.
Next, we analyze the task and come back with a work plan: where the boundary lies between the bot and the app, how accounts are linked, which notification and authorization scenarios we cover, and what we reuse from the current code.
For each item — a timeline estimate and scope of work, with explicitly called-out risks: platform limitations, message delivery, and behavior when the service is unavailable.
Here's what you get from the review:
- a diagram of how the app, bot, and backend connect, with failure points;
- a list of scenarios: login via the bot, notifications, passing data to the app;
- a breakdown of work by stages with timeline estimates and dependencies;
- requirements for access, bot tokens, and the test environment;
- a release plan: what we roll out first, how we test on real users;
- post-launch support terms and the procedure for follow-up work.
The next step is simple: describe the task in your own words — the current state, what should work after integration, and which deadlines are critical. We'll come back with an estimate and a plan, not generic words.







