How Meetily Uses SQLite for Storing Meeting Data, Transcripts, and Summaries

Meetily persists all meeting-related information in a local SQLite database located in the user's application-data directory, managed by the DatabaseManager in the Tauri backend with automated migrations and WAL management.

Meetily is an open-source meeting assistant that leverages SQLite as its primary data store for an offline-first, local-first architecture. The application stores all meeting metadata, transcripts, speaker information, and generated summaries in a single SQLite database file. This approach ensures user data remains on-device while providing reliable ACID compliance and efficient querying through the Tauri backend.

Database Architecture and Location

Local Storage Configuration

The database file, named meeting_minutes.sqlite, resides in the system's application data directory (e.g., ~/Library/Application Support/Meetily/ on macOS or equivalent paths on Windows/Linux). This location ensures the database persists across application updates and system restarts while respecting platform-specific data storage conventions.

DatabaseManager Implementation

The DatabaseManager struct in frontend/src-tauri/src/database/manager.rs handles the complete database lifecycle. The constructor DatabaseManager::new_from_app_handle constructs the full platform-specific path, checks for legacy .db files that need migration, and initializes the SQLite file if absent. It creates a pooled connection using SqlitePool::connect that remains available for the application lifetime.

Schema Design and Migration Strategy

Core Tables Structure

The initial schema, defined in frontend/src-tauri/migrations/20250916100000_initial_schema.sql, establishes the foundational tables:

  • meetings: Stores meeting metadata including id, title, start_ts, and end_ts
  • transcripts: Contains individual text segments with meeting_id, speaker_id, text, and timestamp ts
  • speakers: Maintains speaker identities with id and name fields

Extended Data Tables

Subsequent migrations incrementally expand the schema to support additional features:

Automated Migration System

Meetily uses sqlx::migrate!("./migrations") to automatically apply pending migrations on startup. This guarantees the schema matches the current application version without manual intervention. The migration files follow timestamp-based naming conventions (e.g., 20250916100000_initial_schema.sql) to ensure deterministic execution order.

Connection Handling and Transactions

The DatabaseManager provides a pooled SqlitePool (self.pool) for concurrent access. For atomic operations, the with_transaction helper method manages transaction boundaries, automatically committing successful operations or rolling back on failure. This ensures data consistency when inserting related records across multiple tables, such as linking a transcript entry to its meeting and speaker.

WAL Management and Data Integrity

To prevent corruption and ensure durability, the database implements Write-Ahead Logging (WAL) management. On startup, DatabaseManager checks for corrupted WAL or SHM files, removing them if necessary before reopening the database. During shutdown, the cleanup method executes PRAGMA wal_checkpoint(TRUNCATE) to flush pending writes to the main database file and remove temporary WAL files, leaving the database in a clean, portable state.

Data Flow and Implementation Examples

Storing Meeting Metadata

When a user initiates a meeting, the application inserts a row into the meetings table:

// Insert a new meeting
sqlx::query!(
    "INSERT INTO meetings (title, start_ts) VALUES (?, ?)",
    "Team Stand-up",
    chrono::Utc::now().timestamp()
)
.execute(db.pool())
.await?;

Persisting Transcript Segments

As the Whisper transcription engine produces text fragments, they are immediately stored in the transcripts table:

// 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?;

Querying Stored Data

The frontend retrieves data through Tauri commands that execute SQL against the SQLite pool:

// 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

  • Meetily stores all data in a local SQLite file (meeting_minutes.sqlite) in the user's application data directory
  • The DatabaseManager in frontend/src-tauri/src/database/manager.rs handles pooling, transactions, and WAL management
  • Core tables include meetings, transcripts, and speakers, with additional tables for summaries, meeting_notes, and settings
  • Automated migrations via sqlx::migrate! ensure schema consistency across application versions
  • WAL checkpointing on shutdown guarantees data durability and prevents file corruption

Frequently Asked Questions

Where does Meetily store the SQLite database file?

Meetily stores the database at meeting_minutes.sqlite in the platform-specific application data directory, such as ~/Library/Application Support/Meetily/ on macOS or equivalent locations on Windows and Linux. The exact path is constructed by DatabaseManager::new_from_app_handle based on the Tauri application handle.

How does Meetily handle database schema updates?

The application uses sqlx::migrate! to automatically apply SQL migration files located in frontend/src-tauri/migrations on startup. Each migration file is timestamped to ensure correct execution order, allowing the schema to evolve from the initial 20250916100000_initial_schema.sql through subsequent updates that add tables for summaries, notes, and API keys.

What happens if the SQLite database is corrupted or has WAL issues?

On startup, DatabaseManager detects and removes corrupted WAL or SHM files before opening the database. During shutdown, the cleanup method runs PRAGMA wal_checkpoint(TRUNCATE) to flush all pending writes and clean up temporary files, ensuring the database remains in a consistent state.

Can multiple processes access the Meetily database simultaneously?

While SQLite supports multiple readers, Meetily uses a connection pool (SqlitePool) within the single Tauri backend process to manage access. The with_transaction method ensures atomic operations by wrapping related inserts in transactions, preventing data inconsistency during concurrent read/write operations within the application.

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 →