Database Schema for Meetily: Complete SQLite Table Reference and Migration Guide
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. It includes the following columns:
idTEXT PRIMARY KEY – Unique identifier for the meetingtitleTEXT NOT NULL – Display titlecreated_atTEXT NOT NULL – ISO timestamp of creationupdated_atTEXT NOT NULL – ISO timestamp of last updatefolder_pathTEXT – 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:
idTEXT PRIMARY KEYmeeting_idTEXT FOREIGN KEY →meetings(id)transcriptTEXT NOT NULLtimestampTEXT NOT NULLsummaryTEXT,action_itemsTEXT,key_pointsTEXT – AI-generated metadataaudio_start_timeREAL,audio_end_timeREAL,durationREAL – 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_idTEXT PRIMARY KEY FOREIGN KEY →meetings(id)statusTEXT NOT NULLcreated_atTEXT NOT NULL,updated_atTEXT NOT NULLerrorTEXT,resultTEXTstart_timeTEXT,end_timeTEXTchunk_countINTEGER DEFAULT 0processing_timeREAL DEFAULT 0.0metadataTEXT
transcript_chunks
The transcript_chunks table stores the raw chunks sent to the Whisper engine or other STT back-ends. It contains:
meeting_idTEXT PRIMARY KEY FOREIGN KEY →meetings(id)meeting_nameTEXTtranscript_textTEXT NOT NULLmodelTEXT NOT NULL,model_nameTEXT NOT NULLchunk_sizeINTEGER,overlapINTEGERcreated_atTEXT NOT NULL
settings and transcript_settings
The settings table holds global configuration for LLM and STT providers:
idTEXT PRIMARY KEYproviderTEXT NOT NULL,modelTEXT NOT NULL,whisperModelTEXT NOT NULLgroqApiKeyTEXT,openaiApiKeyTEXT,anthropicApiKeyTEXT,ollamaApiKeyTEXTopenRouterApiKeyTEXT – Added in a later migration to support OpenRouter
The transcript_settings table stores provider-specific credentials for transcription services:
idTEXT PRIMARY KEYproviderTEXT NOT NULL,modelTEXT NOT NULLwhisperApiKeyTEXT,deepgramApiKeyTEXT,elevenLabsApiKeyTEXTgroqApiKeyTEXT,openaiApiKeyTEXT
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 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 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 adds the openRouterApiKey column to the settings table. According to the Zackriya-Solutions/meetily source code, additional migrations such as add_summary_backup.sql and 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. 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 shows the MeetingModel and Transcript structs:
#[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:
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:
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:
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:
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– Rust struct definitions that map directly to DB tables via SQLxfrontend/src-tauri/migrations/20250916100000_initial_schema.sql– Creates the base tables on first installfrontend/src-tauri/migrations/20251006000000_add_audio_sync_fields.sql– Addsfolder_pathand audio-sync columnsfrontend/src-tauri/migrations/20250920155811_add_openrouter_api_key.sql– Extendssettingswith OpenRouter supportfrontend/src-tauri/src/database/manager.rs– Centralizes the SQLite connection pool and migration runnerfrontend/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.rsprovide compile-time type safety via SQLxFromRowderives - Nullable columns such as
folder_path,audio_start_time, andopenRouterApiKeyallow 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.
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.
How does Meetily handle schema updates?
Meetily applies schema updates through incremental SQL migration files. For example, 20251006000000_add_audio_sync_fields.sql adds playback synchronization columns, and 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.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →