Multi-Tenant Router¶
Route requests to dedicated SQLite configs per tenant slug.
uv run python docs/examples/patterns/multi_tenant/router.py
Source¶
1"""Dispatch requests to dedicated SQLite configs per tenant."""
2
3from sqlspec.adapters.sqlite import SqliteConfig
4from sqlspec.core import SQL
5
6__all__ = ("TenantRouter", "main")
7
8
9TENANTS: "tuple[str, ...]" = ("acme", "orbital")
10
11
12class TenantRouter:
13 """Maintain isolated SqliteConfig instances for each tenant slug."""
14
15 def __init__(self, tenants: "tuple[str, ...]") -> None:
16 self._configs = {slug: SqliteConfig(pool_config={"database": ":memory:"}, bind_key=slug) for slug in tenants}
17
18 def insert_article(self, slug: str, title: str) -> None:
19 config = self._configs[slug]
20 with config.provide_session() as session:
21 session.execute(
22 """
23 CREATE TABLE IF NOT EXISTS articles (
24 id INTEGER PRIMARY KEY AUTOINCREMENT,
25 title TEXT NOT NULL
26 )
27 """
28 )
29 session.execute("INSERT INTO articles (title) VALUES (:title)", {"title": title})
30
31 def list_titles(self, slug: str) -> "list[str]":
32 config = self._configs[slug]
33 with config.provide_session() as session:
34 result = session.execute(SQL("SELECT title FROM articles ORDER BY id"))
35 return [row["title"] for row in result.all()]
36
37
38def main() -> None:
39 """Insert one record per tenant and print the isolated results."""
40 router = TenantRouter(TENANTS)
41 router.insert_article("acme", "Acme onboarding")
42 router.insert_article("orbital", "Orbital checklist")
43 payload: dict[str, list[str]] = {slug: router.list_titles(slug) for slug in TENANTS}
44 print(payload)
45
46
47if __name__ == "__main__":
48 main()