RepoDocsDiscord

Deployment and operations

Run with PM2

Install production dependencies on the server, then start Mochi through Bun:

bun install --production
bun run pm2:start
bun run pm2:startup

Run the command printed by pm2:startup with the required system privileges, then save the current process list:

bun run pm2:save

The ecosystem file keeps the process running, restarts it after crashes, and writes logs to logs/pm2-out.log and logs/pm2-error.log. Keep application settings and secrets in .env. After changing them, reload the process with:

bun run pm2:restart

Other useful commands are bun run pm2:logs, bun run pm2:stop, and bun run pm2:delete.

Database model

Mochi uses SQLite with Bun’s native bun:sqlite driver and WAL mode. The schema is managed by versioned migrations in src/database/migrations/ and recorded in schema_migrations.

The durable invite lifecycle ledger (invite_events) and bonus adjustment history (invite_bonus_adjustments) are the source of truth. invite_members, inviters, and daily_invite_stats are projections that can be rebuilt from the ledger.

The Discord invite snapshot is authoritative, including an empty snapshot. The persisted invite_cache is only a temporary fallback when Discord cannot be queried; a successful empty fetch clears stale cache rows.

Rebuild projections

After manually changing invite data, rebuild the projections:

bun run rebuild-projections                                      # all guilds
bun run rebuild-projections -- --guild <guildId>                 # one guild
bun run rebuild-projections -- --guild <guildId> --dry-run        # preview only, no writes

Migrations

The current migration sequence is:

Migration Contents
001 Complete initial schema: invite ledger, projections, invite logs, invite cache and labels, guild settings, and bot attribution
002 Namespaced plugin migration metadata
003 Per-guild plugin enablement settings
004+ Future production schema changes

The new bot starts with one complete baseline migration. Once Mochi is deployed with data that must be preserved, migrations are append-only: never edit, squash, or remove a released migration. Add the next numbered migration for schema changes.

In particular, migration 001 remains unchanged after release.

Development databases are disposable while the bot is being built. Reset one explicitly when changing the baseline; the application never does this at startup:

rm data/mochi.sqlite

Migration 001 will create a clean database on the next start.

Plugin migrations follow the same safety model, with migration namespaced by plugin ID and recorded in plugin_schema_migrations. They run in ascending version order; each migration and its record are written in one transaction. There are no automatic down migrations. Disabled plugins do not run migrations, and their existing tables are never removed.

Testing

Run the complete test suite:

bun test

Tests use isolated in-memory databases and never touch data/mochi.sqlite.

3 weeks agoLast edited 2026-08-21T12:27:15.000Z3 weeks agoCreated 2026-08-21T12:27:15.000ZSodaSyrup