How Meetily Stores Meeting Data and Transcripts in SQLite: Complete Technical Guide

Meetily persists all meeting-related information in a local SQLite database located in the user's application data directory, utilizing a DatabaseManager Rust struct in the Tauri backend to handle connection pooling, automated schema migrations, and Write-Ahead Logging (WAL) maintenance.

Meetily, an open-source meeting transcription application developed by Zackriya-Solutions, stores all user data locally using SQLite to ensure privacy and offline functionality. The Tauri-based backend manages the database lifecycle through a centralized DatabaseManager that abstracts connection pooling, migration handling, and transaction safety. This article examines the exact storage mechanisms, schema evolution strategy, and data flow from audio capture to persistent storage as implemented in the repository source code.

Database Initialization and Migration Strategy

The database lifecycle begins in frontend/src-tauri/src/database/manager.rs, where the DatabaseManager struct orchestrates file creation, legacy migration, and schema versioning. When the application starts, DatabaseManager::new_from_app_handle constructs the full platform-specific path to meeting_minutes.sqlite (e.g., ~/Library/Application Support/Meetily/meeting_minutes.sqlite on macOS), copies any existing legacy .db files if detected, creates the database file when missing, and then applies all pending migrations.

Migration scripts reside in frontend/src-tauri/migrations and are executed automatically via sqlx::migrate!("./migrations"). This ensures the schema matches the current code version on every startup. The migration files follow a chronological naming convention that incrementally evolves the database structure:

Connection Pooling and WAL Management

The DatabaseManager maintains a pooled connection via SqlitePool::connect, storing the pool in self.pool for reuse across all queries. This pooling strategy prevents connection exhaustion during high-frequency transcription inserts.

For data integrity, the manager implements Write-Ahead Logging (WAL) management routines:

  • Startup Cleanup – On initialization, the manager checks for corrupted WAL/SHM files (.sqlite-wal and .sqlite-shm), removes them if necessary, and re-opens the database to ensure a clean state.
  • Transaction Helper – The with_transaction method wraps operations in transactions that automatically commit on success or roll back on failure.
  • Shutdown Checkpoint – The cleanup method executes PRAGMA wal_checkpoint(TRUNCATE) during application shutdown, flushing pending writes to the main database and deleting WAL files to prevent data fragmentation.

Database Schema Structure

The schema centers on relational tables that link meeting metadata to transcription segments and derived content:

  • meetings – Stores meeting metadata with columns id, title, start_ts, and end_ts.
  • transcripts – Contains individual transcription segments with id, meeting_id (foreign key), speaker_id, text, and ts (timestamp).
  • speakers – Maps speaker identifiers to display names using id and name columns.
  • summaries – Persists AI-generated meeting summaries linked to specific meeting records.
  • meeting_notes – Stores user-edited notes associated with meetings.
  • settings – Houses configuration data including API keys for OpenRouter, Gemini, and Ollama endpoints.

The transcripts table maintains referential integrity through meeting_id and speaker_id relationships, enabling efficient queries that reconstruct the full conversation timeline for any given meeting.

Data Flow from Recording to Storage

The storage pipeline operates through four distinct stages:

  1. Audio Capture – The application captures raw microphone and system audio streams during active recording sessions.
  2. Speech Processing – Only speech segments are extracted and sent to the Whisper transcription engine, filtering out silence or noise.
  3. Transcription Insertion – Whisper returns text fragments that are inserted into the transcripts table via Tauri commands, linking each segment to the active meeting_id and identified speaker_id.
  4. Metadata Persistence – When users create meetings or generate summaries, the frontend invokes Tauri commands that execute SQL insert statements against the SQLite pool, populating the meetings, summaries, and meeting_notes tables.

Queries follow a standard pattern where the frontend fetches data by invoking commands that run prepared statements like SELECT * FROM transcripts WHERE meeting_id = ? ORDER BY ts.

Practical Code Examples

The following Rust patterns demonstrate how Meetily interacts with the database layer using sqlx:

// Initialize the database manager at application startup
let db = DatabaseManager::new_from_app_handle(&app_handle).await?;

// Insert a new meeting record
sqlx::query!(
    "INSERT INTO meetings (title, start_ts) VALUES (?, ?)",
    "Team Stand-up",
    chrono::Utc::now().timestamp()
)
.execute(db.pool())
.await?;
// Persist a transcription segment with speaker attribution
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?;
// Retrieve all transcripts for a specific meeting ordered by timestamp
let rows = sqlx::query!(
    "SELECT text, ts FROM transcripts WHERE meeting_id = ? ORDER BY ts",
    meeting_id
)
.fetch_all(db.pool())
.await?;

Summary

  • Meetily stores all data in a local SQLite file (meeting_minutes.sqlite) managed by the DatabaseManager struct in frontend/src-tauri/src/database/manager.rs.
  • Schema evolution is handled automatically through versioned migration files in frontend/src-tauri/migrations, utilizing sqlx::migrate! for deployment.
  • The application uses connection pooling (SqlitePool) and a custom with_transaction helper to ensure thread-safe database access.
  • Write-Ahead Logging (WAL) files are managed through startup corruption checks and shutdown checkpointing via PRAGMA wal_checkpoint(TRUNCATE).
  • Core tables include meetings, transcripts, speakers, summaries, meeting_notes, and settings, supporting full offline storage of meeting metadata and transcripts.

Frequently Asked Questions

Where does Meetily store the SQLite database file on disk?

The database file is located in the platform-specific application data directory, specifically at ~/Library/Application Support/Meetily/meeting_minutes.sqlite on macOS, with equivalent paths under %APPDATA% on Windows and $HOME/.config on Linux. This location is constructed dynamically by DatabaseManager::new_from_app_handle based on the Tauri application handle.

How does Meetily handle database schema updates when the application upgrades?

Schema updates are applied automatically on startup through sqlx::migrate!("./migrations"), which executes SQL scripts in frontend/src-tauri/migrations in chronological order. Each migration file (such as 20251101000000_add_summary_backup.sql) contains the specific DDL statements needed to evolve the schema, ensuring the database structure always matches the current application version without manual intervention.

What tables are created in the Meetily SQLite database?

The core tables include meetings (meeting metadata), transcripts (speech-to-text segments), speakers (speaker identification), summaries (AI-generated meeting summaries), meeting_notes (user notes), and settings (API keys and configuration). These tables are defined in 20250916100000_initial_schema.sql and expanded by subsequent migration files.

How does Meetily prevent data loss if the application crashes during a meeting?

The DatabaseManager utilizes Write-Ahead Logging (WAL) mode with automatic checkpointing. On startup, it removes corrupted WAL/SHM files to prevent database lock-ups. During normal operation, the with_transaction helper ensures atomic writes, and the cleanup method performs a PRAGMA wal_checkpoint(TRUNCATE) on graceful shutdown, forcing all pending writes from the WAL to the main database file.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →