Building
How a Telegram bot stores data between messages
By the Botable team
Telegram stores nothing on your behalf, each update arrives with no memory of the last. Anything a bot needs to remember has to go in your own database, keyed by chat id and user id. In-memory variables are lost on every restart.
Watch it
Every bot gets its own SQLite file. How to open the tables it created, read the rows, and confirm that what you think is being saved is actually being saved.
Read the transcript
Everything said in the video, in order.
A bot that remembers anything has to put it somewhere. Tickets, preferences, who signed up, what they asked for last week — all of it lands in storage the moment the bot starts running.
On Botable that storage is one SQLite file per bot, and the Database tab is a window straight onto it.
The Database tab opens the file the bot is actually using. One SQLite file, in that bot's own directory, holding everything it has ever stored.
There is no database server to provision and no connection string to keep secret. Nothing in here is shared with any other bot you own.
The list on the left is not a schema Botable imposes on you. These are the tables your bot's own code created, each with the number of rows in it.
Lumen Support keeps four. The tickets people open, the users who opened them, the FAQ topics they read, and its own settings. One click switches between them.
The strip above the column headers is the schema. Every column with its type abbreviated to a few letters, so a table this wide still fits on one line, and the primary key in bold.
Search does not ask which column you mean. It matches your term against every text column in the table at once.
Enter runs it. Eighteen tickets narrow to the one whose subject mentions a refund, and the count beside the table name drops to one.
Rows arrive fifty at a time, whatever the table. Users holds sixty, so it comes back as two pages, with the arrows at the bottom right to move between them.
This is not a read only viewer. Hover any row and two controls appear at its right edge: one opens the row for editing, one deletes it.
A wrong value is usually a one field problem. Editing opens the row as a form, one field per column. Asking the agent to fix it instead would cost a full build and a new version of the bot.
The bot is reading this same file while you sit here looking at it, so a value you save is the value the next message sees. Delete asks first, and means it: the row leaves the file.
Every bot's own SQLite file, browsable and repairable from the workspace. Start free at botable dot I O.
The short version
A Telegram bot is stateless by default: each update arrives independently, and the API carries no memory of what happened before. Anything the bot should remember, a user's settings, a running score, a half-finished form, a watchlist, must be written to storage you control. The keying decision matters more than the storage engine. User-scoped data keys on the user id and follows a person across every chat; chat-scoped data keys on the chat id and is shared by everyone in a group; conversation state usually needs both, because two people filling in the same form in one group must not overwrite each other. In-memory variables are the standard beginner trap, since they work perfectly in testing and silently lose everything on the next deploy or restart, which produces bug reports that cannot be reproduced. A small embedded database like SQLite is enough for the overwhelming majority of bots.
Step by step
What actually needs storing?
Anything that must survive the next message: preferences, subscriptions, balances, progress through a flow, and the history you will want to report on later. If losing it would produce a bug report, it belongs in the database rather than in a variable.
How should rows be keyed?
By user id for anything personal, by chat id for anything shared, and by both for conversation state inside a group. Getting this wrong is what causes two people in one group to overwrite each other's answers, a bug that never appears in a private-chat test.
Why is in-memory state a trap?
Because it works flawlessly until the process restarts, and processes restart constantly, deploys, crashes, host maintenance, scaling. The resulting failure is intermittent and unreproducible, which is the most expensive kind. Write it down from the start.
Does a bot need a heavyweight database?
Almost never. SQLite in a file handles thousands of users comfortably and needs no server, no connection pool and no separate hosting. Reach for something larger when you genuinely have concurrent writers across multiple instances, not before.
What catches people out
- Chat ids are negative for groups and supergroups; storing them as unsigned silently breaks group data
- A user changing their @username does not change their user id, key on the id, never the username
- If your host has an ephemeral filesystem, a SQLite file is wiped on redeploy unless it is on a persistent volume
Questions
Does Telegram store anything for the bot?
Only messages in the chat itself, which the bot cannot search or read back arbitrarily. There is no key-value store, no user profile store and no session store provided by the API. Everything is yours to keep.
How long should conversation state be kept?
Long enough to resume, then expire it. A half-finished form from three weeks ago should not silently continue when the person says something unrelated. A day or two is a reasonable default, and it should be an explicit decision.
Want a bot that does this?
Describe it in plain language and Botable writes the code, gives the bot its own database, deploys it and keeps it running. Everything on this page is handled for you, the token, the webhook, the storage, the hosting.
Keep reading
- Bot securitytelegram bot security
- Create a Telegram bothow to create a telegram bot
- Bot analyticstelegram bot analytics