Three ways events reach a bot
- Long polling. Your bot calls an endpoint such as Telegram's
getUpdateswith a timeout. The server holds the request open until there is an update or the timeout expires, then the bot asks again. - Webhooks. You register a public HTTPS URL. The platform sends an HTTP POST for every event.
- Persistent sockets. The bot opens a WebSocket (Discord Gateway, Slack Socket Mode) and receives events over it.
Comparison
| Long polling | Webhooks | Socket / gateway | |
|---|---|---|---|
| Needs a public URL | No | Yes, HTTPS | No |
| Needs an always-on process | Yes | No | Yes |
| Works on serverless | Poorly | Yes | No (in a normal request) |
| Latency | Low | Low | Low |
| Scaling | One poller per bot | Horizontal, behind a load balancer | Sharding for large bots |
| Main risk | Two pollers at once | Spoofed requests, slow responses | Reconnects and resumes |
Long polling: best for development
Polling needs nothing but outbound HTTPS, so it works on a laptop behind a home router. That makes it ideal for development and for small bots on a single machine.
Its failure mode is concurrency. Telegram only allows one consumer: if a second process calls getUpdates, or a webhook is set, you get 409 Conflict. Run exactly one poller, and call deleteWebhook before polling. Remember to confirm updates by passing offset as the last update_id plus one, or you will process them again.
Webhooks: best for production
With webhooks the platform does the waiting. Your code runs only when there is work, which makes webhooks cheap and a natural fit for serverless. They also scale horizontally: put several instances behind a load balancer.
Webhooks come with three duties:
- Verify the sender. Anyone can POST to a public URL. Check Telegram's
X-Telegram-Bot-Api-Secret-Tokenheader, Slack'sX-Slack-Signature, Meta'sX-Hub-Signature-256, or Discord's Ed25519 signature. Our signature generator helps debug this. - Respond quickly. Platforms time out and retry. Slack expects a response within 3 seconds and retries up to three times; GitHub expects a response within 10 seconds. Acknowledge with 200 and move slow work to a queue.
- Be idempotent. Retries mean duplicates. Store the event or update ID and skip ones you have already processed.
Telegram webhooks must use HTTPS on port 443, 80, 88 or 8443.
Sockets: when the platform requires them
Some features only exist on a socket. A Discord bot that reacts to ordinary messages, member joins or presence needs the Gateway. Slack Socket Mode is handy for internal apps behind a firewall, because it needs no public URL.
The cost is an always-on process and reconnect logic. Use a maintained library (discord.js, discord.py, Bolt) instead of writing the protocol yourself.
A rule of thumb
- Developing locally: polling or Socket Mode.
- Production, request-driven work: webhooks.
- Production, you need message streams or presence: a socket, in a supervised always-on process.
You can mix: a Discord bot can take slash commands through an HTTP interactions endpoint and use no Gateway at all, which is much easier to host.
Testing webhooks without deploying
Use a tunnel (Cloudflare Tunnel or ngrok) to expose your local server, or replay saved payloads with our webhook simulator. Replaying a real payload is faster than waiting for the platform and easier to repeat.
Sources
- Telegram getUpdates and setWebhook: core.telegram.org/bots/api#getting-updates
- Slack Events API retries: api.slack.com/apis/events-api#retries
- GitHub webhook best practices: docs.github.com/webhooks/using-webhooks/best-practices-for-using-webhooks
- Discord Gateway: discord.com/developers/docs/events/gateway