# Database Schema for Meetily: Complete SQLite Table Reference and Migration Guide

> Explore the Meetily database schema with this comprehensive SQLite table reference and migration guide. Understand the full database structure for the Tauri backend.

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

---

**Meetily uses a lightweight SQLite database accessed through SQLx, with its schema defined in versioned migration files and type-safe Rust structs in the Tauri backend.**

The open-source meeting assistant **Meetily**, hosted in the `Zackriya-Solutions/meetily` repository, persists all data locally in a single **SQLite** file accessed through **SQLx**. The **database schema for Meetily** defines tables for meetings, transcripts, summary jobs, and provider settings, using both SQL migrations and **Rust** structs to maintain a type-safe data layer.

## Core Tables in the Meetily Database Schema

The initial schema defines six core tables that handle meetings, transcript segments, summary jobs, audio chunks, and provider configuration. Several columns were added through later migrations to support folder-based organization, audio synchronization, and additional API providers.

### meetings

The **meetings** table stores one row per recorded meeting according to the base migration 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). It includes the following columns:

- `id` TEXT PRIMARY KEY – Unique identifier for the meeting
- `title` TEXT NOT NULL – Display title
- `created_at` TEXT NOT NULL – ISO timestamp of creation
- `updated_at` TEXT NOT NULL – ISO timestamp of last update
- `folder_path` TEXT – Added later to support folder-based organization

### transcripts

The **transcripts** table stores individual transcript entries, typically representing a paragraph or speaker turn. As implemented in `Zackriya-Solutions/meetily`, its columns include:

- `id` TEXT PRIMARY KEY
- `meeting_id` TEXT FOREIGN KEY → `meetings(id)`
- `transcript` TEXT NOT NULL
- `timestamp` TEXT NOT NULL
- `summary` TEXT, `action_items` TEXT, `key_points` TEXT – AI-generated metadata
- `audio_start_time` REAL, `audio_end_time` REAL, `duration` REAL – Added later for precise playback synchronization with the original audio file

### summary_processes

The **summary_processes** table tracks the status and results of the LLM-driven meeting-summary pipeline. Its columns are:

- `meeting_id` TEXT PRIMARY KEY FOREIGN KEY → `meetings(id)`
- `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

### transcript_chunks

The **transcript_chunks** table stores the raw chunks sent to the Whisper engine or other STT back-ends. It contains:

- `meeting_id` TEXT PRIMARY KEY FOREIGN KEY → `meetings(id)`
- `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

### settings and transcript_settings

The **settings** table holds global configuration for LLM and STT providers:

- `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 a later migration to support OpenRouter

The **transcript_settings** table stores provider-specific credentials for transcription services:

- `id` TEXT PRIMARY KEY
- `provider` TEXT NOT NULL, `model` TEXT NOT NULL
- `whisperApiKey` TEXT, `deepgramApiKey` TEXT, `elevenLabsApiKey` TEXT
- `groqApiKey` TEXT, `openaiApiKey` TEXT

## How the Meetily Schema Evolves Through Migrations

Meetily applies schema changes through numbered SQL migration files that run automatically on launch. These migrations reside in `frontend/src-tauri/migrations/` and modify the base tables using standard `ALTER TABLE` statements.

### Initial Schema Creation

The file [`frontend/src-tauri/migrations/20250916100000_initial_schema.sql`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/migrations/20250916100000_initial_schema.sql) creates all base tables when the app is first installed. This script defines the `meetings`, `transcripts`, `summary_processes`, `transcript_chunks`, `settings`, and `transcript_settings` tables.

### Audio Synchronization and Folders

The migration [`frontend/src-tauri/migrations/20251006000000_add_audio_sync_fields.sql`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/migrations/20251006000000_add_audio_sync_fields.sql) extends the schema with two feature sets. It adds `folder_path` to the `meetings` table and `audio_start_time`, `audio_end_time`, and `duration` to the `transcripts` table, enabling precise audio playback synchronization and folder-based meeting organization.

### Extended API Provider Support

The migration [`frontend/src-tauri/migrations/20250920155811_add_openrouter_api_key.sql`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/migrations/20250920155811_add_openrouter_api_key.sql) adds the `openRouterApiKey` column to the `settings` table. According to the `Zackriya-Solutions/meetily` source code, additional migrations such as [`add_summary_backup.sql`](https://github.com/Zackriya-Solutions/meetily/blob/main/add_summary_backup.sql) and [`add_gemini_api_key.sql`](https://github.com/Zackriya-Solutions/meetily/blob/main/add_gemini_api_key.sql) continue to extend the schema as the application evolves.

## Rust Model Definitions for Type-Safe Access

All database tables are represented as structs in [`frontend/src-tauri/src/database/models.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/database/models.rs). These structs implement SQLx's `FromRow` derive macro, mapping rows directly to Rust types for compile-time query validation.

The following excerpt from [`models.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/models.rs) shows the `MeetingModel` and `Transcript` structs:

```rust
#[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
pub struct MeetingModel {
    pub id: String,
    pub title: String,
    pub created_at: DateTimeUtc,
    pub updated_at: DateTimeUtc,
    pub folder_path: Option<String>,
}

#[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
pub struct Transcript {
    pub id: String,
    pub meeting_id: String,
    pub transcript: String,
    pub timestamp: String,
    pub summary: Option<String>,
    pub action_items: Option<String>,
    pub key_points: Option<String>,
    pub audio_start_time: Option<f64>,
    pub audio_end_time: Option<f64>,
    pub duration: Option<f64>,
}

```

The `Option<T>` fields correspond to columns added by later migrations or nullable fields in the SQLite schema.

## Working with the Meetily Database

The following examples demonstrate how the Rust backend interacts with the Meetily database schema using SQLx compile-time checked macros.

### Inserting a New Meeting

This query inserts a row into the `meetings` table with a generated UUID and current timestamp:

```rust
use sqlx::sqlite::SqlitePool;
use uuid::Uuid;
use chrono::Utc;

async fn create_meeting(pool: &SqlitePool, title: &str) -> sqlx::Result<()> {
    let id = Uuid::new_v4().to_string();
    let now = Utc::now();
    sqlx::query!(
        r#"
        INSERT INTO meetings (id, title, created_at, updated_at, folder_path)
        VALUES (?1, ?2, ?3, ?4, NULL)
        "#,
        id,
        title,
        now.to_rfc3339(),
        now.to_rfc3339()
    )
    .execute(pool)
    .await?;
    Ok(())
}

```

### Querying Transcripts by Meeting

This function retrieves all transcript rows for a specific `meeting_id`, ordered by timestamp:

```rust
use sqlx::sqlite::SqlitePool;

async fn get_transcripts(pool: &SqlitePool, meeting_id: &str) -> sqlx::Result<Vec<Transcript>> {
    let rows = sqlx::query_as!(
        Transcript,
        r#"
        SELECT *
        FROM transcripts
        WHERE meeting_id = ?1
        ORDER BY timestamp ASC
        "#,
        meeting_id
    )
    .fetch_all(pool)
    .await?;
    Ok(rows)
}

```

### Updating Summary Process Status

This update modifies the `summary_processes` table to reflect the current state of the LLM pipeline:

```rust
async fn set_summary_status(
    pool: &SqlitePool,
    meeting_id: &str,
    new_status: &str,
) -> sqlx::Result<()> {
    sqlx::query!(
        r#"
        UPDATE summary_processes
        SET status = ?1, updated_at = ?2
        WHERE meeting_id = ?3
        "#,
        new_status,
        chrono::Utc::now().to_rfc3339(),
        meeting_id
    )
    .execute(pool)
    .await?;
    Ok(())
}

```

### Storing Provider Settings

This insertion persists user configuration to the `settings` table, including API keys for multiple providers:

```rust
async fn insert_setting(pool: &SqlitePool, setting: Setting) -> sqlx::Result<()> {
    sqlx::query!(
        r#"
        INSERT INTO settings (
            id, provider, model, whisperModel,
            groqApiKey, openaiApiKey, anthropicApiKey,
            ollamaApiKey, openRouterApiKey
        )
        VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9)
        "#,
        setting.id,
        setting.provider,
        setting.model,
        setting.whisper_model,
        setting.groq_api_key,
        setting.openai_api_key,
        setting.anthropic_api_key,
        setting.ollama_api_key,
        setting.open_router_api_key
    )
    .execute(pool)
    .await?;
    Ok(())
}

```

## Key Files Defining the Database Schema

Understanding the following files is essential for working with Meetily's data layer:

- [`frontend/src-tauri/src/database/models.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/database/models.rs) – Rust struct definitions that map directly to DB tables via SQLx
- [`frontend/src-tauri/migrations/20250916100000_initial_schema.sql`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/migrations/20250916100000_initial_schema.sql) – Creates the base tables on first install
- [`frontend/src-tauri/migrations/20251006000000_add_audio_sync_fields.sql`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/migrations/20251006000000_add_audio_sync_fields.sql) – Adds `folder_path` and audio-sync columns
- [`frontend/src-tauri/migrations/20250920155811_add_openrouter_api_key.sql`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/migrations/20250920155811_add_openrouter_api_key.sql) – Extends `settings` with OpenRouter support
- [`frontend/src-tauri/src/database/manager.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/database/manager.rs) – Centralizes the SQLite connection pool and migration runner
- [`frontend/src-tauri/src/database/commands.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/database/commands.rs) – Tauri commands exposing CRUD operations to the frontend UI

## Summary

The Meetily database schema is designed for local-first meeting data storage with SQLite and SQLx.

- **Six core tables** handle meetings, transcripts, summary jobs, audio chunks, and provider settings
- **Versioned migrations** in `frontend/src-tauri/migrations/` apply schema changes incrementally without breaking existing data
- **Rust structs** in [`frontend/src-tauri/src/database/models.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/database/models.rs) provide compile-time type safety via SQLx `FromRow` derives
- **Nullable columns** such as `folder_path`, `audio_start_time`, and `openRouterApiKey` allow backward-compatible feature additions

## Frequently Asked Questions

### What database engine does Meetily use?

Meetily stores all persistent data in a local **SQLite** database. The Rust backend accesses this database through **SQLx**, which provides compile-time checked queries and automatic row mapping via the structs in [`frontend/src-tauri/src/database/models.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/database/models.rs).

### Where are the Meetily database migrations stored?

Schema migrations live in `frontend/src-tauri/migrations/` inside the repository. Each migration file is timestamped and executed in order by the migration runner defined in [`frontend/src-tauri/src/database/manager.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/database/manager.rs).

### How does Meetily handle schema updates?

Meetily applies schema updates through incremental SQL migration files. For example, [`20251006000000_add_audio_sync_fields.sql`](https://github.com/Zackriya-Solutions/meetily/blob/main/20251006000000_add_audio_sync_fields.sql) adds playback synchronization columns, and [`20250920155811_add_openrouter_api_key.sql`](https://github.com/Zackriya-Solutions/meetily/blob/main/20250920155811_add_openrouter_api_key.sql) extends the `settings` table. These run automatically when the Tauri application starts.

### What is the purpose of the summary_processes table?

The `summary_processes` table tracks the lifecycle and output of the LLM-driven summarization pipeline. It stores processing status, timing, chunk counts, error messages, and final results for each meeting, enabling the UI to display progress and retrieve generated summaries.