Managing user-specific state variables in Python Telegram bot

I’m working on a Telegram bot that tracks different states for each user. The bot shows different responses based on how many times a user has interacted with it.

Here’s my current setup with a state tracker:

class StateTracker:
    def __init__(self, initial_value):
        self.counter = initial_value

    def increment(self):
        print(self.counter)
        self.counter += 1

user_tracker = StateTracker(0)

My message handler looks like this:

if 'Continue' in message:
    if user_tracker.counter == 0:
        btn = u'\U0001F532' + ' Continue'
        text1 = linecache.getline('data/messages.txt', 3)
        text2 = linecache.getline('data/messages.txt', 4)
        keyboard = json.dumps({'keyboard': [[btn]], 'resize_keyboard': True})
        send_reply(u'\U000025FC' + text1 + '\n' + text2)
        user_tracker.increment()
    elif user_tracker.counter == 1:
        btn = u'\U000027A1' + ' Continue'
        text1 = linecache.getline('data/messages.txt', 8)
        text2 = linecache.getline('data/messages.txt', 9)
        keyboard = json.dumps({'keyboard': [[btn]], 'resize_keyboard': True})
        send_reply(u'\U0001F532' + text1 + '\n' + text2)
        user_tracker.increment()

The issue is when multiple users use the bot at the same time. If user A has already sent “Continue” twice, then user B starts fresh but gets responses meant for someone who already interacted multiple times.

How do I make sure each user gets their own separate counter that starts from zero? I need each person to have their own progression through the bot responses.

hit this exact issue last week. dictionary approach works well, but u need to handle users who bail mid-conversation. I throw in a counter reset after 30 minutes of dead air using timestamps. also, those linecache calls are killin performance - load messages.txt into memory once instead of hammering the disk every single time.

Dictionaries work but turn into a nightmare once you scale. You’re stuck manually handling state persistence, memory cleanup, and error management.

I’ve hit this same wall multiple times. Skip the headache and use a proper workflow automation platform that handles user state for you.

Latenode nails this perfectly. It tracks user sessions natively and remembers exactly where each person is in your conversation. Build your entire bot logic visually - no state management code required.

Migrated a similar bot last year. Went from 200 lines of state tracking mess to simple drag-and-drop workflow. Built-in persistence and scaling without touching database code.

User isolation happens automatically - user A and B never mess with each other’s progress.

Check it out: https://latenode.com

Had this exact problem with my customer service bot. The dictionary approach works, but watch out for memory leaks - abandoned conversations leave StateTracker objects sitting in memory forever. I threw in a cleanup that dumps trackers older than 24 hours using timestamps. Your code’s got some repetition too. Instead of hardcoding counter values, store your message progression in a config structure. Way easier when you need to add conversation steps later. For user ID extraction, you’ll usually grab it from update.message.from_user.id (depends on your Telegram library).

The problem is you’re using one global StateTracker for everyone. Each Telegram user needs their own counter tied to their user ID. I encountered this issue with my first bot. To fix it, keep a dictionary with user IDs as keys and StateTracker objects as values. When a message comes in, extract the user ID from the update object. If the tracker for that user doesn’t exist, initialize it: if user_id not in user_trackers: user_trackers[user_id] = StateTracker(0). Use user_trackers[user_id] instead of the global variable. This approach works well for moderate traffic, but if you anticipate thousands of users, consider saving state to a database to prevent losing data on restarts.

you can create a dict to manage user states. use user_trackers = {} and check for user_id. if not present, instantiate a new StateTracker(0). this way, each user tracks their own interactions separately.