What Database Technologies Are Used by Meetily? SQLite and SQLx Explained

Meetily stores all persistent data in an embedded SQLite database and interacts with it exclusively through the async Rust ORM sqlx, keeping every meeting record local and offline.

Zackriya-Solutions/meetily is a privacy-first meeting assistant that keeps all data on the user's machine. The database technologies used by Meetily center on a lightweight pairing of SQLite for file-based storage and SQLx for type-safe async queries.

The Core Database Technologies Behind Meetily

SQLite: The Local Relational Engine

Meetily persists every meeting, transcript, summary, and setting into a single SQLite file named meeting_minutes.sqlite. Because SQLite is a serverless, file-based database engine, Meetily never contacts an external database server. The entire data layer lives inside the user's application-data directory, making the app fully offline-first.

SQLx: Compile-Time Checked Async ORM

All database interactions flow through sqlx version 0.8 with the features runtime-tokio, sqlite, and chrono enabled. According to the frontend/src-tauri/Cargo.toml manifest, this setup provides async connection pooling via SqlitePool, compile-time-checked queries, and built-in migration support. The DatabaseManager type in the source code wraps these capabilities into a reusable interface.

Initializing the Database on App Startup

When the Tauri application launches, initialize_database_on_startup in frontend/src-tauri/src/database/setup.rs decides whether this is the user's first run or a normal startup. If it is not the first launch, the function creates a DatabaseManager and injects it into the shared application state.

// src/database/setup.rs
pub async fn initialize_database_on_startup(app: &AppHandle) -> Result<(), String> {
    // Detect first launch → emit event or initialise immediately
    let is_first_launch = DatabaseManager::is_first_launch(app).await?;
    if is_first_launch {
        // First‑run path – UI can show onboarding
    } else {
        // Normal start – create manager and inject into shared state
        let db_manager = DatabaseManager::new_from_app_handle(app)
            .await
            .map_err(|e| format!("Failed to init DB: {}", e))?;
        app.manage(AppState { db_manager });
    }
    Ok(())
}

This pattern ensures that the SQLite file is ready before any UI component attempts to query data.

Creating the SQLite File and Running Migrations

The DatabaseManager::new function in frontend/src-tauri/src/database/manager.rs handles the physical database file. It creates the parent directory if needed, copies an existing database or creates a new one with Sqlite::create_database, connects a SqlitePool, and then applies migrations.

// src/database/manager.rs
pub async fn new(tauri_db_path: &str, backend_db_path: &str) -> Result<Self> {
    // Ensure parent directory exists
    if let Some(parent) = Path::new(tauri_db_path).parent() {
        fs::create_dir_all(parent)?;
    }

    // Create or copy the DB file
    if !Path::new(tauri_db_path).exists() {
        if Path::new(backend_db_path).exists() {
            fs::copy(backend_db_path, tauri_db_path)?;
        } else {
            Sqlite::create_database(tauri_db_path).await?;
        }
    }

    // Build a connection pool and run migrations
    let pool = SqlitePool::connect(tauri_db_path).await?;
    sqlx::migrate!("./migrations").run(&pool).await?;
    Ok(DatabaseManager { pool })
}

Migrations live in frontend/src-tauri/migrations and are referenced by the macro sqlx::migrate!("./migrations"). This guarantees that schema changes stay up-to-date across releases.

Querying Meeting Data with SQLx

Actual CRUD operations are performed in modules like frontend/src-tauri/src/database/commands.rs. The following simplified example shows how Meetily fetches every meeting record using sqlx::query_as and maps rows to a MeetingModel struct.

// src/database/commands.rs (simplified)
pub async fn get_all_meetings(db: &DatabaseManager) -> Result<Vec<MeetingModel>> {
    sqlx::query_as::<_, MeetingModel>("SELECT * FROM meeting")
        .fetch_all(db.pool())
        .await
}

The MeetingModel type is defined in frontend/src-tauri/src/database/models.rs alongside other #[derive(sqlx::FromRow)] structs such as Transcript and SummaryProcess. Repository-specific logic is further organized under frontend/src-tauri/src/database/repositories/.

Key Source Files in Meetily's Database Layer

Summary

  • Meetily relies on an embedded SQLite database stored in a local meeting_minutes.sqlite file.
  • The SQLx async ORM handles all queries, pooling, and migrations via SqlitePool.
  • The DatabaseManager type in manager.rs creates the database file, establishes the pool, and runs sqlx::migrate! on startup.
  • All meeting data stays on the user's machine because Meetily never connects to an external database server.

Frequently Asked Questions

Does Meetily use PostgreSQL or MySQL?

No. Meetily uses only SQLite as implemented in the project source code. The sqlx crate is compiled with the sqlite feature alone, and the application is intentionally designed to remain offline-first without external database servers.

Where is the Meetily database file stored on disk?

The SQLite file is named meeting_minutes.sqlite and resides in the user's application-data directory. The exact path is determined at runtime by the DatabaseManager and passed as tauri_db_path in frontend/src-tauri/src/database/manager.rs.

How does Meetily handle database schema changes?

Schema changes are managed through versioned SQL migration scripts stored in frontend/src-tauri/migrations. The DatabaseManager automatically executes sqlx::migrate!("./migrations").run(&pool) whenever the application starts, ensuring the schema is current.

What Rust crate does Meetily use for database access?

Meetily uses sqlx version 0.8 with the runtime-tokio, sqlite, and chrono features. This crate provides the SqlitePool, compile-time query checking, and migration runner that power the entire data layer.

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 →