Production checklist
Things to check before pointing real users at your gogram service. None of these are gogram-specific, but missing any of them tends to bite first in the long-running connection world.
Build
- Build with
CGO_ENABLED=0for a static binary you can ship into any container. - Pin gogram to a minor version in
go.mod. Schema-layer bumps can be breaking. - Strip the binary if size matters:
-ldflags="-s -w". Cuts ~30%.
Secrets
- api id / api hash never go in code. Env var or secret store.
- Bot token same.
- Session file (or
StringSession) is as sensitive as the bot token — access to it means impersonating the bot/user. Mount as a read-only secret if your platform supports it; otherwise file permissions600. - If you use
SessionAESKey, the key lives in a different blast radius than the session itself. Otherwise the encryption is theatre.
Supervision
- Run under a supervisor that restarts on exit: systemd, supervisord, Docker restart policy, Kubernetes
restartPolicy: Always. - gogram reconnects internally for transient failures, but it cannot recover from a hard panic. Let the supervisor handle that.
- Set a max-restart-per-minute limit so a deterministic crash does not turn into a hot loop.
Observability
- Use a structured logger (see Logging).
- Export metrics: RPC count, RPC error rate, dispatcher queue depth, reconnect count.
- Alert on: flood wait at
FLOOD_PREMIUMlevel, repeatedAUTH_KEY_UNREGISTERED(session died), reconnect storm.
Graceful shutdown
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
go client.Idle()
<-ctx.Done()
log.Println("shutting down")
client.Stop()
client.Disconnect()ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
go client.Idle()
<-ctx.Done()
log.Println("shutting down")
client.Stop()
client.Disconnect()Stop tells the dispatcher to stop accepting new updates; Disconnect closes the wire. In-flight handlers finish; their goroutines exit cleanly. Skipping this on shutdown is usually fine, but it does mean a few unprocessed updates at the moment of termination.
Horizontal scaling
One Telegram session = one process. Running two gogram clients with the same session file will fight, and Telegram will eventually invalidate the auth key.
To scale horizontally, partition by something else (users, channels, work queue) and let each instance handle its slice. For bot accounts, a load-balancer in front of an HTTP API on top of one gogram instance is usually saner than sharding the bot account itself.
