Auto-Removal Without the Drama: Grace Periods and the Ban API Footguns

Auto-Removal Without the Drama: Grace Periods and the Ban API Footguns

Removing lapsed members is the least glamorous part of running a paid channel and the easiest to get badly wrong. Two things go wrong: the policy, and the API.

The API problems are worse, because they are silent.

Footgun one: unbanning removes people

From Telegram's Bot API documentation for unbanChatMember:

"By default, this method guarantees that after the call the user is not a member of the chat, but will be able to join it. So if the user is a member of the chat they will also be removed from the chat."

Read that again. Calling unbanChatMember on somebody who is currently a member kicks them out.

The name suggests a safe, corrective action. It is not. The method guarantees a post-condition — "not a member, but able to join" — and it will remove an active member to get there.

The realistic disaster: a member lapses, gets removed, resubscribes, rejoins. Later, a cleanup job runs unbanChatMember across everyone who was ever removed, intending to tidy up ban state. It ejects your paying subscriber without a word.

The fix is one parameter:

unbanChatMember(chat_id, user_id, only_if_banned=True)

only_if_banned does nothing if the user isn't banned. Use it every single time unless you have thought hard about why you shouldn't. There is no good reason to omit it in a membership system.

Footgun two: short bans are permanent

From the documentation for banChatMember:

"If user is banned for more than 366 days or less than 30 seconds from the current time they are considered to be banned forever."

Both ends of that range are traps, and the lower one is vicious.

A natural implementation of "remove this person but let them rejoin when they pay" is a very short ban followed by an unban. If your until_date computes to less than 30 seconds from now — a rounding error, a clock skew, an off-by-one — the user is banned forever. No error is returned. It looks like it worked.

Same at the other end: a ban intended as "one year" that computes to 366 days plus a second is permanent.

Safe patterns:

Footgun three: revoking the primary link

From revokeChatInviteLink:

"If the primary link is revoked, a new link is automatically generated."

Helpful, and a problem if you didn't expect it. Revoking the primary link invalidates every published copy of it — your website, your pinned posts, your ads, the link in a subscriber's saved messages — and silently issues a replacement.

Revoke non-primary links you created for a purpose. Leave the primary link alone unless you specifically intend to invalidate everything.

Now the policy

With the API hazards handled, the question is when to remove someone.

Removing at the instant of failure is the wrong default. A large share of failed renewals are people who wanted to stay and were short on Stars — a prepaid balance problem, not a decision. Removing them instantly converts a recoverable lapse into a lost member and a support message.

A grace period is cheap and works.

GraceEffect
0 daysMaximum churn, maximum support load. Avoid.
3 daysGood default. Covers "I'll top up later."
7 daysGenerous. Reasonable for high-value channels and long-tenured members.
14+ daysToo long. Teaches people the deadline isn't real.

Three days is the sensible default. Long enough to top up, short enough that the subscription still means something.

Tenure-based grace

Not every lapse deserves the same treatment. An eight-month member and a first-month member are different situations.

TenureGrace
First period3 days
3+ months5 days
12+ months7 days, plus a personal message

Your longest-standing members are your most valuable and your least likely to be gaming anything. Treating them identically to a day-one signup is a small cruelty with a real cost.

Say it before you do it

Most anger about removal is not about the removal. It is about surprise.

Before: "Your subscription lapsed. You have 3 days to top up before access ends."

On removal: "Your access to [Channel] has ended. Rejoin any time here — you'll be back immediately."

The second message is what separates a lost customer from a returning one. Make it clear that rejoining is trivial and that nothing was held against them. Never remove someone silently — silence reads as a technical fault, and they will tell people your bot is broken.

The checklist

  1. Always pass only_if_banned=True to unbanChatMember
  2. Never compute a until_date that could land under 30 seconds
  3. Don't revoke the primary invite link during routine operations
  4. Warn before removing, always
  5. Default to 3 days' grace, more for long-tenured members
  6. Make rejoining one tap
  7. Log every removal with the reason — you will need it when someone asks

The API details matter more than the policy here. A generous grace period cannot save you from a cleanup job that silently ejects paying members.


API behaviour quoted from Telegram's Bot API documentation, verified September 2026. Method behaviour changes — re-check before implementing.