Asopitech With · Mail client
Gmail with Alopex DB
Gmail is a mail service for sending, storing and searching mail. What if we rebuilt it with Alopex DB?
Updated: Oct 12, 2026
What the service does
A Gmail-like mail service sends, receives and stores mail, and adds search that answers questions about the inbox, summaries of long threads, and help with drafting replies. The data is messages, threads, labels, contacts and attachment details.
Where the data lives
- SQL tables: messages, threads, labels and the link between messages and labels live in tables. Filtering by sender, date or label is plain SQL.
- Vectors: body embeddings sit in a vector column, so a question such as “last week’s mail about booking the business trip” finds the right messages.
- Full-text search: subjects and bodies carry a full-text index, so a word such as an order number is found as written.
- Columnar tables: the send and receive log is loaded into a columnar table through HTTP ingest, where counts by sender or by month are aggregated.
The app writes each incoming message as one unit. The message row, its labels and its body embedding are committed in the same transaction. The app creates the embeddings. Search never sees a half-written message.
Deployment
Alopex DB is embedded in the mail client on the user’s device. The mailbox is a single .alopex file. Inbox search and semantic search run on the device, so the client works offline and message bodies stay on the device.
Why Alopex DB fits
Mail search becomes useful when filters, exact words and closeness in meaning work together. Alopex DB handles all three inside SQL and protects every write with a transaction.
See it in code
Messages and labels live in tables, filtered by label and ordered newest-first. The basic inbox operation.
import alopex
# メールボックスは1つの .alopex ファイル
db = alopex.Database.open("gmail.alopex")
db.execute_sql("""
CREATE TABLE IF NOT EXISTS messages (
id INTEGER PRIMARY KEY,
sender TEXT,
subject TEXT,
received DATE
)
""")
db.execute_sql("""
CREATE TABLE IF NOT EXISTS message_labels (
message_id INTEGER,
label TEXT
)
""")
messages = [
(1, "boss@example.com", "出張の手配", "2026-10-20"),
(2, "news@example.com", "週刊ニュース", "2026-10-19"),
(3, "boss@example.com", "見積もりの確認", "2026-10-18"),
]
for m in messages:
db.execute_sql("INSERT INTO messages (id, sender, subject, received) VALUES (?, ?, ?, ?)", list(m))
for mid, label in [(1, "仕事"), (3, "仕事"), (2, "ニュース")]:
db.execute_sql("INSERT INTO message_labels (message_id, label) VALUES (?, ?)", [mid, label])
# 「仕事」ラベルのメールを、新しい順に並べる
rows = db.execute_sql("""
SELECT m.received, m.sender, m.subject
FROM messages AS m
JOIN message_labels AS l ON l.message_id = m.id
WHERE l.label = ?
ORDER BY m.received DESC
""", ["仕事"])
for row in rows:
print(row["received"], row["subject"])Filtering by sender, date and label is plain SQL; semantic and full-text search layer on top.
Alopex DB writes mail, labels and embeddings in one transaction. Prototype a mail client with it; the steps are in the quickstart.