How Meetily Stores Meeting Data and Transcripts Using SQLite: A Complete Technical Guide
Meetily persists all meeting recordings, transcripts, and metadata in a local SQLite database managed by the DatabaseManager struct in the Tauri backend, using sqlx migrations and WAL mode for atomicity and crash recovery.
Meetily is an open-source meeting assistant that prioritizes data privacy by keeping everything local. According to the Zackriya-Solutions/meetily source code, the application implements a robust Rust-based storage layer that handles meeting data and transcripts using SQLite, ensuring your sensitive conversations never leave your device.
Database Location and Initialization
Where Meetily Stores Your Data
On macOS, Meetily creates the database at ~/Library/Application Support/Meetily/meeting_minutes.sqlite. Windows and Linux equivalents follow platform-specific application data directories. The DatabaseManager::new_from_app_handle method in frontend/src-tauri/src/database/manager.rs constructs this path automatically and handles legacy database migration if an older .db file exists.
Migration and Schema Setup
During initialization, the manager executes sqlx::migrate!("./migrations") to apply all scripts from frontend/src-tauri/migrations. This includes the foundational 20250916100000_initial_schema.sql which creates core tables, plus incremental updates like 20251101000000_add_summary_backup.sql for the summaries table and 20251223000000_add_meeting_notes.sql for the meeting_notes table.
Core Database Schema
Meetings and Transcripts Tables
The initial schema defines the relationships between meetings and their content:
- meetings: Stores
id,title,start_ts, andend_tstimestamps - transcripts: Contains
id,meeting_id,speaker_id,text, andts(timestamp) columns, linking each utterance to a specific meeting - speakers: Maps
idtonamefor speaker identification
Extended Functionality Tables
Subsequent migrations add specialized storage:
- summaries: Generated meeting summaries (added in
20251101000000_add_summary_backup.sql) - meeting_notes: Free-form user notes linked to meetings (
20251223000000_add_meeting_notes.sql) - settings: API keys for OpenRouter, Gemini, and Ollama endpoints
Connection Management and Reliability
Pooled Connections with SqlitePool
The DatabaseManager maintains a SqlitePool connection pool (self.pool) created via SqlitePool::connect. All queries execute through this pool, and the manager provides a with_transaction helper that automatically commits or rolls back transactions, ensuring data integrity during complex operations.
WAL Mode and Crash Recovery
To prevent corruption, Meetily implements Write-Ahead Logging (WAL) management:
- Startup validation: Checks for corrupted
.waland.shmfiles, removing them if necessary before opening the database - Graceful shutdown: The
cleanupmethod executesPRAGMA wal_checkpoint(TRUNCATE)to flush pending writes and delete WAL files, leaving a single compact database file
Data Flow from Recording to Storage
Transcription Pipeline
When you record a meeting:
- Audio capture produces raw mic and system streams
- The transcription pipeline sends speech segments to the Whisper engine
- Whisper returns text fragments that Tauri commands insert into the
transcriptstable with timestamps and speaker IDs
Metadata Persistence
When creating a meeting, the application inserts a row into meetings. Associated summaries populate the summaries table, while user notes go to meeting_notes. The frontend queries these tables via Tauri commands using SQL like SELECT * FROM transcripts WHERE meeting_id = ?.
Working with the Database in Code
Inserting Meeting Data
// Obtain a DatabaseManager instance (usually done at app start)
let db = DatabaseManager::new_from_app_handle(&app_handle).await?;
// Insert a new meeting
sqlx::query!(
"INSERT INTO meetings (title, start_ts) VALUES (?, ?)",
"Team Stand‑up",
chrono::Utc::now().timestamp()
)
.execute(db.pool())
.await?;
Storing Transcript Fragments
// Save a transcript fragment
sqlx::query!(
"INSERT INTO transcripts (meeting_id, speaker_id, text, ts) VALUES (?, ?, ?, ?)",
meeting_id,
speaker_id,
"We need to finalize the budget.",
chrono::Utc::now().timestamp()
)
.execute(db.pool())
.await?;
Retrieving Transcripts
// Fetch all transcripts for a meeting
let rows = sqlx::query!(
"SELECT text, ts FROM transcripts WHERE meeting_id = ? ORDER BY ts",
meeting_id
)
.fetch_all(db.pool())
.await?;
Summary
- Local-First Storage: Meetily stores meeting data and transcripts using SQLite in your application data directory, ensuring complete privacy
- Migration System: Automatic schema evolution via sqlx migrations in
frontend/src-tauri/migrationshandles updates seamlessly - Reliability: WAL mode management and transaction helpers in
DatabaseManagerprevent corruption and ensure atomic operations - Structured Schema: Separate tables for
meetings,transcripts,speakers,summaries, andmeeting_notesmaintain data integrity - Rust Backend: The Tauri backend uses
SqlitePooland parameterized queries for safe, efficient database access
Frequently Asked Questions
Where is the Meetily SQLite database file located?
On macOS, the database resides at ~/Library/Application Support/Meetily/meeting_minutes.sqlite. Windows stores it in %APPDATA%\Meetily\meetings_minutes.sqlite, while Linux uses ~/.local/share/Meetily/meeting_minutes.sqlite. The DatabaseManager::new_from_app_handle method determines the platform-specific path automatically.
How does Meetily handle database schema updates?
Meetily uses sqlx's migration system. When the app starts, DatabaseManager runs sqlx::migrate!("./migrations") to apply any pending SQL scripts from frontend/src-tauri/migrations. This incremental approach allows seamless updates from older versions without data loss.
What tables store meeting transcripts and speaker information?
The transcripts table stores individual utterances with meeting_id, speaker_id, text, and timestamp columns. Speaker names reside in the speakers table, linked via foreign keys. The meetings table contains metadata like title and duration, while summaries stores AI-generated meeting summaries.
How does Meetily prevent SQLite corruption?
The DatabaseManager implements multiple safeguards: it checks and removes corrupted WAL/SHM files on startup, uses a SqlitePool for connection management, provides a with_transaction helper for atomic operations, and runs PRAGMA wal_checkpoint(TRUNCATE) during cleanup to ensure all data is written to the main database file before shutdown.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →