Channel automation that handles auth, albums, and rate limits
After the social media posting module proved itself, the client wanted the same setup for their messenger-based channels. The pattern was similar — dozens of channels, regular posting schedule, content sourced from public feeds — but the underlying platform was fundamentally different. Where the social network has a straightforward API with app-level tokens, this messenger requires full user account authentication. That changes everything: you're not posting as an app, you're posting as a person, which means dealing with phone number verification, two-factor codes, session management, and all the restrictions that come with pretending a bot is a human.
authentication flow
We built the authentication flow as a multi-step wizard inside the platform's admin panel. An operator adds an account by entering a phone number; the system initiates a sign-in request via the MTProto protocol and waits for the verification code. The operator enters the code (and a 2FA password if enabled), and the system stores the authenticated session. These sessions persist across server restarts, but they expire unpredictably — sometimes after weeks, sometimes after days if the platform detects unusual activity. We built automatic session health checks that test each account's ability to read its own profile. If a session dies, the account is flagged and the operator gets a notification to re-authenticate, while the scheduler silently redistributes that account's channels to others.
albums and media groups
Content parsing was the second major challenge. The channels repost media-heavy content — photo albums, videos with captions, mixed media groups. The messenger's API treats a media group (album) as a set of individually sent messages that share a group ID, and they must be sent together in a single API call with specific ordering. If you send them as individual messages, they appear as separate posts instead of a clean album. Our parser identifies media groups in the source content, preserves their structure and ordering, and the posting engine sends them as atomic batches. Getting this right took several iterations — edge cases like albums with mixed photo and video content, or albums where one item has a caption and the others don't, each required specific handling.
adaptive throttling
Rate limiting on this platform is strict and opaque. There's no published rate limit header — you just start getting flood-wait errors that tell you to back off for N seconds. The wait times escalate: first 15 seconds, then a minute, then 10 minutes, and eventually the account gets temporarily restricted. We built an adaptive throttle that tracks flood-wait responses per account, adjusts posting intervals dynamically, and distributes load across accounts to stay well under the threshold. The system targets about 70% of the estimated safe rate, leaving headroom for spikes.
scheduler and bin packing
The scheduler follows the same calendar model as the social media module — time slots per channel, automatic content distribution, manual override capability — but with tighter constraints. Each account can only handle a limited number of channels before the posting frequency triggers restrictions, so the system has to solve a bin-packing problem: assign channels to accounts such that no account exceeds its safe posting rate. When accounts are added or removed, the assignment rebalances automatically.
results
The system manages 25+ channels with daily automated posting, and the authentication re-flows happen about once or twice a week across all accounts — disruptive but manageable with notifications. The biggest lesson from this project: building on a protocol designed for human users, not bots, means every assumption about reliability has to be softer. Sessions expire. Rate limits shift. Media handling has undocumented quirks. The only way to keep it stable is to build every interaction as a recoverable operation — if it fails, log why, back off, and try again with a different account. Resilience isn't a feature here, it's the architecture.
Stack
Backend: Next.js 14 (Route Handlers), Prisma, PostgreSQL
Messaging: Telegram MTProto (via `telegram` package), session persistence
Scheduling: node-cron for posting calendar and session health checks
Content: Media group handling, album reconstruction, adaptive throttling
