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, and end_ts timestamps
  • transcripts: Contains id, meeting_id, speaker_id, text, and ts (timestamp) columns, linking each utterance to a specific meeting
  • speakers: Maps id to name for speaker identification

Extended Functionality Tables

Subsequent migrations add specialized storage:

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:

  1. Startup validation: Checks for corrupted .wal and .shm files, removing them if necessary before opening the database
  2. Graceful shutdown: The cleanup method executes PRAGMA 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:

  1. Audio capture produces raw mic and system streams
  2. The transcription pipeline sends speech segments to the Whisper engine
  3. Whisper returns text fragments that Tauri commands insert into the transcripts table 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/migrations handles updates seamlessly
  • Reliability: WAL mode management and transaction helpers in DatabaseManager prevent corruption and ensure atomic operations
  • Structured Schema: Separate tables for meetings, transcripts, speakers, summaries, and meeting_notes maintain data integrity
  • Rust Backend: The Tauri backend uses SqlitePool and 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:

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 →