Storage Engines¶
Irenogram stores session data — authorization key, user info, peer cache, and update state — using a pluggable
storage backend. Five backends are available out of the box. All of them inherit from the abstract
Storage base class so you can also write your own.
Abstract Base: Storage¶
Storage defines the interface every backend must implement. You never instantiate it
directly, but it documents the contract all backends follow.
Key async methods you can count on across every backend:
open()— open or create the storagesave()— flush pending changes to the mediumclose()— cleanly shut down the connectiondelete()— permanently remove the stored sessionexport_session_string()— serialise the session to a portable base-64 stringupdate_peers()/get_peer_by_id()/get_peer_by_username()— peer-cache operationsupdate_state()— persist the update gap state (pts, qts, date, seq)
FileStorage (Default)¶
FileStorage persists the session in a SQLite file with a .session extension.
It is the default when you pass a plain string name to Client.
from pyrogram import Client
app = Client("my_account")
The file my_account.session is created in the current working directory. Change the location with
workdir:
from pyrogram import Client
app = Client("my_account", workdir="sessions/")
You can also pass a FileStorage instance directly when you need full control:
from pathlib import Path
from pyrogram import Client
from pyrogram.storage import FileStorage
storage = FileStorage("my_account", workdir=Path("sessions/"))
app = Client("my_account", storage_engine=storage)
MemoryStorage¶
MemoryStorage keeps everything inside an in-memory SQLite database. The session
disappears the moment the process exits — no file is ever written.
from pyrogram import Client
app = Client(
":memory:",
api_id=12345,
api_hash="0123456789abcdef0123456789abcdef"
)
You can also resume an existing session by supplying a previously exported session string:
from pyrogram import Client
from pyrogram.storage import MemoryStorage
storage = MemoryStorage(":memory:", session_string="BQAB...")
app = Client(":memory:", storage_engine=storage)
Warning
In-memory sessions are completely lost when the process exits. Re-authorization is required on every restart unless you export the session string before shutting down.
SQLiteStorage¶
SQLiteStorage is the shared SQLite implementation that FileStorage
and MemoryStorage both extend. It handles schema creation, schema migration, and all SQL
operations. You can subclass it directly if you want SQLite behaviour with a custom connection strategy.
import sqlite3
from pyrogram.storage import SQLiteStorage
class CustomStorage(SQLiteStorage):
async def open(self):
self.conn = sqlite3.connect("custom_path.db", check_same_thread=False)
self.create()
MongoStorage¶
MongoStorage stores session data in a MongoDB collection. This is ideal for
horizontally-scaled or cloud-deployed applications where a shared, persistent store is needed across multiple
instances.
Installation¶
MongoStorage requires an async MongoDB driver. Two are supported:
pip install async-pymongo
or
pip install motor
Usage with async-pymongo¶
import asyncio
import async_pymongo
from pyrogram import Client
from pyrogram.storage import MongoStorage
async def main():
conn = async_pymongo.AsyncClient("mongodb://localhost:27017")
storage = MongoStorage("my_account", connection=conn)
app = Client("my_account", storage_engine=storage)
async with app:
print(await app.get_me())
asyncio.run(main())
Usage with Motor¶
import asyncio
import motor.motor_asyncio
from pyrogram import Client
from pyrogram.storage import MongoStorage
async def main():
conn = motor.motor_asyncio.AsyncIOMotorClient("mongodb://localhost:27017")
storage = MongoStorage("my_account", connection=conn)
app = Client("my_account", storage_engine=storage)
async with app:
print(await app.get_me())
asyncio.run(main())
Removing peers on logout¶
By default peer cache is kept across logouts. Pass remove_peers=True to wipe it on every
log_out() call:
storage = MongoStorage("my_account", connection=conn, remove_peers=True)
Note
Session data is stored in a MongoDB database whose name matches the name parameter you pass to
MongoStorage. Each session gets its own session, peers, usernames, and update_state
collections inside that database.
Warning
Passing a synchronous pymongo.MongoClient object raises an exception at runtime. You must use an
async driver such as async_pymongo or motor.
String Sessions¶
Any backend can export its session as a portable, base-64-encoded string. This is useful for serverless platforms (Heroku, AWS Lambda, Railway, Docker) where you cannot write files to disk.
Export the string from a working session:
import asyncio
from pyrogram import Client
async def main():
async with Client("my_account") as app:
session_string = await app.export_session_string()
print(session_string)
asyncio.run(main())
Use the exported string in your deployment environment with MemoryStorage:
import asyncio
from pyrogram import Client
from pyrogram.storage import MemoryStorage
SESSION = "BQAB..."
async def main():
storage = MemoryStorage(":memory:", session_string=SESSION)
async with Client(":memory:", storage_engine=storage) as app:
print(await app.get_me())
asyncio.run(main())
Tip
Store the session string in an environment variable rather than hard-coding it. Read it at runtime with
os.environ.get("SESSION_STRING").
Writing a Custom Backend¶
Subclass Storage and implement all abstract methods to plug in any data store you
need:
from typing import List, Tuple
from pyrogram.storage import Storage
class RedisStorage(Storage):
def __init__(self, name: str, redis_client):
super().__init__(name)
self.redis = redis_client
async def open(self):
pass
async def save(self):
pass
async def close(self):
await self.redis.aclose()
async def delete(self):
await self.redis.delete(f"session:{self.name}")
async def update_peers(self, peers: List[Tuple[int, int, str, str, str]]):
pass
async def update_usernames(self, usernames: List[Tuple[int, str]]):
pass
async def update_state(self, update_state=object):
pass
async def get_peer_by_id(self, peer_id: int):
pass
async def get_peer_by_username(self, username: str):
pass
async def get_peer_by_phone_number(self, phone_number: str):
pass
async def dc_id(self, value: int = object):
pass
async def api_id(self, value: int = object):
pass
async def test_mode(self, value: bool = object):
pass
async def auth_key(self, value: bytes = object):
pass
async def date(self, value: int = object):
pass
async def user_id(self, value: int = object):
pass
async def is_bot(self, value: bool = object):
pass