# Meetily SQLite Database Schema: Structure for Meetings, Transcripts, and Settings

> Discover the Meetily SQLite database schema for meetings, transcripts, and settings. Explore six core tables managed via versioned migration files in the Tauri backend.

- Repository: [Zackriya Solutions/meetily](https://github.com/Zackriya-Solutions/meetily)
- Tags: architecture
- Published: 2026-07-07

---

**Meetily stores all persistent data in a single SQLite database with six core tables—meetings, transcripts, summary_processes, transcript_chunks, settings, and transcript_settings—managed through versioned migration files in the Tauri backend.**

The open-source meeting assistant Meetily (Zackriya-Solutions/meetily) relies on a lightweight yet comprehensive SQLite database schema to manage meeting metadata, AI-generated transcripts, and LLM configuration. This schema is defined in SQL migration files under the `frontend/src-tauri/migrations` directory and provides the persistent storage layer for the Rust-powered Tauri desktop application.

## Core Tables Overview

The Meetily SQLite database schema consists of six primary tables that cover the complete meeting lifecycle:

- **meetings**: Stores meeting metadata including title and timestamps
- **transcripts**: Contains raw Whisper-generated transcripts and optional AI summaries
- **summary_processes**: Tracks asynchronous summarization job states and performance metrics
- **transcript_chunks**: Holds chunked transcript segments fed to LLM summarizers
- **settings**: Global configuration for LLM providers, models, and API keys
- **transcript_settings**: Per-transcription configuration allowing different providers per meeting

## Detailed Schema Definitions

### meetings Table

The `meetings` table serves as the parent record for all meeting-related data. It uses TEXT-based identifiers and timestamps for SQLite portability.

```sql
-- Defined in frontend/src-tauri/migrations/20250916100000_initial_schema.sql
CREATE TABLE IF NOT EXISTS meetings (
    id TEXT PRIMARY KEY,
    title TEXT NOT NULL,
    created_at TEXT NOT NULL,
    updated_at TEXT NOT NULL
);

```

### transcripts Table

The `transcripts` table stores raw transcription output from Whisper and maintains foreign key relationships to meetings. It includes optional columns for cached summary data.

```sql
CREATE TABLE IF NOT EXISTS transcripts (
    id TEXT PRIMARY KEY,
    meeting_id TEXT NOT NULL,
    transcript TEXT NOT NULL,
    timestamp TEXT NOT NULL,
    summary TEXT,
    action_items TEXT,
    key_points TEXT,
    FOREIGN KEY (meeting_id) REFERENCES meetings(id) ON DELETE CASCADE
);

```

### summary_processes Table

This table tracks the state of asynchronous summarization jobs, including timing metrics, error messages, and processing metadata.

```sql
CREATE TABLE IF NOT EXISTS summary_processes (
    meeting_id TEXT PRIMARY KEY,
    status TEXT NOT NULL,
    created_at TEXT NOT NULL,
    updated_at TEXT NOT NULL,
    error TEXT,
    result TEXT,
    start_time TEXT,
    end_time TEXT,
    chunk_count INTEGER DEFAULT 0,
    processing_time REAL DEFAULT 0.0,
    metadata TEXT,
    FOREIGN KEY (meeting_id) REFERENCES meetings(id) ON DELETE CASCADE
);

```

### transcript_chunks Table

Stores chunked versions of transcripts optimized for LLM context windows, including model parameters and chunk configuration.

```sql
CREATE TABLE IF NOT EXISTS transcript_chunks (
    meeting_id TEXT PRIMARY KEY,
    meeting_name TEXT,
    transcript_text TEXT NOT NULL,
    model TEXT NOT NULL,
    model_name TEXT NOT NULL,
    chunk_size INTEGER,
    overlap INTEGER,
    created_at TEXT NOT NULL,
    FOREIGN KEY (meeting_id) REFERENCES meetings(id) ON DELETE CASCADE
);

```

### settings Table

Global application configuration storing LLM provider credentials and model preferences. The schema was extended via migration to include OpenRouter support.

```sql
CREATE TABLE IF NOT EXISTS settings (
    id TEXT PRIMARY KEY,
    provider TEXT NOT NULL,
    model TEXT NOT NULL,
    whisperModel TEXT NOT NULL,
    groqApiKey TEXT,
    openaiApiKey TEXT,
    anthropicApiKey TEXT,
    ollamaApiKey TEXT,
    openRouterApiKey TEXT   -- Added in 20250920155811_add_openrouter_api_key.sql
);

```

### transcript_settings Table

Per-transcription configuration allowing individual meetings to use different API keys or providers than the global defaults.

```sql
CREATE TABLE IF NOT EXISTS transcript_settings (
    id TEXT PRIMARY KEY,
    provider TEXT NOT NULL,
    model TEXT NOT NULL,
    whisperApiKey TEXT,
    deepgramApiKey TEXT,
    elevenLabsApiKey TEXT,
    groqApiKey TEXT,
    openaiApiKey TEXT
);

```

## Database Relationships and Constraints

The Meetily SQLite database schema enforces **referential integrity** through foreign key constraints. All transcript-related tables (transcripts, summary_processes, transcript_chunks) reference `meetings(id)` with `ON DELETE CASCADE`, ensuring that removing a meeting automatically cleans up related data.

The schema uses **TEXT types for timestamps** rather than SQLite's native datetime types, maintaining compatibility across different SQLite versions and simplifying Rust integration via the `rusqlite` crate.

## Migration Files and Schema Evolution

The database schema evolves through versioned SQL files in `frontend/src-tauri/migrations`:

1. **[`20250916100000_initial_schema.sql`](https://github.com/Zackriya-Solutions/meetily/blob/main/20250916100000_initial_schema.sql)**: Creates the six core tables (meetings, transcripts, summary_processes, transcript_chunks, settings, transcript_settings)
2. **[`20250920155811_add_openrouter_api_key.sql`](https://github.com/Zackriya-Solutions/meetily/blob/main/20250920155811_add_openrouter_api_key.sql)**: Alters the settings table to add the `openRouterApiKey` column for OpenRouter API integration
3. **[`20251223000000_add_meeting_notes.sql`](https://github.com/Zackriya-Solutions/meetily/blob/main/20251223000000_add_meeting_notes.sql)**: Adds the `meeting_notes` table for user-generated markdown or JSON notes

The Rust database wrapper in [`frontend/src-tauri/src/database/mod.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/database/mod.rs) automatically runs these migrations on application startup using the `rusqlite` migration system.

## Working with the Database in Rust

The Tauri backend interacts with the SQLite database through parameterized queries. Here are the common operations used throughout the codebase:

**Inserting a new meeting:**

```rust
let sql = r#"
    INSERT INTO meetings (id, title, created_at, updated_at)
    VALUES (?1, ?2, datetime('now'), datetime('now'));
"#;
db.execute(sql, (&meeting_id, &title))?;

```

**Adding a transcript for a meeting:**

```rust
let sql = r#"
    INSERT INTO transcripts (id, meeting_id, transcript, timestamp)
    VALUES (?1, ?2, ?3, datetime('now'));
"#;
db.execute(sql, (&transcript_id, &meeting_id, &raw_text))?;

```

**Updating the summary processing status:**

```rust
let sql = r#"
    INSERT INTO summary_processes (meeting_id, status, created_at, updated_at)
    VALUES (?1, 'running', datetime('now'), datetime('now'))
    ON CONFLICT(meeting_id) DO UPDATE SET
        status = excluded.status,
        updated_at = datetime('now');
"#;
db.execute(sql, (&meeting_id,))?;

```

**Reading configured LLM provider settings:**

```rust
let row: (String, String, String) = db.query_row(
    "SELECT provider, model, whisperModel FROM settings WHERE id = 'default'",
    [],
    |r| Ok((r.get(0)?, r.get(1)?, r.get(2)?))
)?;

```

## Configuration Storage Architecture

Meetily implements a **two-tier configuration system** through its SQLite database schema. The `settings` table stores global defaults used when no specific overrides exist, while `transcript_settings` allows per-meeting customization of AI providers and API keys. This architecture enables users to run different meetings with different LLM providers (e.g., OpenAI for sensitive meetings, local Ollama for private data) without changing global defaults.

## Summary

- Meetily uses a single SQLite database with six core tables defined in [`frontend/src-tauri/migrations/20250916100000_initial_schema.sql`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/migrations/20250916100000_initial_schema.sql)
- **Foreign key constraints** with `ON DELETE CASCADE` maintain data integrity between meetings and their related transcripts, chunks, and processes
- The schema separates **global settings** from **per-transcription settings** to support flexible LLM provider configuration
- **Migration files** handle schema evolution, including the addition of `openRouterApiKey` and the `meeting_notes` table
- All timestamps use TEXT type for cross-platform SQLite compatibility, managed through Rust's `rusqlite` crate in [`frontend/src-tauri/src/database/mod.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/database/mod.rs)

## Frequently Asked Questions

### Where is the Meetily database schema defined?

The schema is defined in SQL migration files located under `frontend/src-tauri/migrations/` in the Zackriya-Solutions/meetily repository. The initial schema lives in [`20250916100000_initial_schema.sql`](https://github.com/Zackriya-Solutions/meetily/blob/main/20250916100000_initial_schema.sql), while subsequent migrations like [`20250920155811_add_openrouter_api_key.sql`](https://github.com/Zackriya-Solutions/meetily/blob/main/20250920155811_add_openrouter_api_key.sql) modify existing tables. The Rust backend in [`frontend/src-tauri/src/database/mod.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/database/mod.rs) applies these migrations automatically when the application starts.

### What is the difference between settings and transcript_settings tables?

The `settings` table stores **global application configuration** including default LLM providers, Whisper models, and API keys that apply to all meetings. The `transcript_settings` table stores **per-transcription overrides**, allowing individual meetings to use different API keys or providers. This enables users to configure specific meetings with different credentials without changing the global defaults.

### How does Meetily handle schema migrations?

Meetily uses versioned SQL migration files executed by the Rust backend using the `rusqlite` crate's migration system. When the application starts, the database wrapper in [`frontend/src-tauri/src/database/mod.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/database/mod.rs) checks for pending migrations and applies them sequentially. This approach allows the schema to evolve safely—adding columns like `openRouterApiKey` or new tables like `meeting_notes` without breaking existing user data.

### What are the foreign key relationships in the Meetily database?

The transcripts, summary_processes, and transcript_chunks tables each contain a `meeting_id` column that references `meetings(id)` with `ON DELETE CASCADE` constraints. This ensures that deleting a meeting automatically removes all associated transcripts, processing status records, and chunk data. The transcripts table also maintains optional summary fields (summary, action_items, key_points) that cache AI-generated content.