# How Meetily Stores Meeting Data and Transcripts Using SQLite: A Complete Technical Guide

> Discover how Meetily stores meeting data and transcripts in SQLite. Learn about the DatabaseManager struct, sqlx migrations, and WAL mode for robust data persistence.

- Repository: [Zackriya Solutions/meetily](https://github.com/Zackriya-Solutions/meetily)
- Tags: how-to-guide
- Published: 2026-07-11

---

**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`](https://github.com/Zackriya-Solutions/meetily/blob/main/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`](https://github.com/Zackriya-Solutions/meetily/blob/main/20250916100000_initial_schema.sql) which creates core tables, plus incremental updates like [`20251101000000_add_summary_backup.sql`](https://github.com/Zackriya-Solutions/meetily/blob/main/20251101000000_add_summary_backup.sql) for the `summaries` table and [`20251223000000_add_meeting_notes.sql`](https://github.com/Zackriya-Solutions/meetily/blob/main/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:

- **summaries**: Generated meeting summaries (added in [`20251101000000_add_summary_backup.sql`](https://github.com/Zackriya-Solutions/meetily/blob/main/20251101000000_add_summary_backup.sql))
- **meeting_notes**: Free-form user notes linked to meetings ([`20251223000000_add_meeting_notes.sql`](https://github.com/Zackriya-Solutions/meetily/blob/main/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:

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

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

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

```rust
// 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.