FIM One は 2 つのデータベースバックエンドをサポートしています: SQLite(デフォルト、ゼロコンフィグ)と PostgreSQL(本番環境に推奨)。バックエンドは DATABASE_URL 環境変数によって決定されます。
# SQLite (default — no configuration needed)
DATABASE_URL=sqlite+aiosqlite:///./data/fim_one.db
# PostgreSQL (production)
DATABASE_URL=postgresql+asyncpg://user:pass@localhost:5432/fim_one
テーブルは最初の起動時に自動的に作成されます。手動マイグレーションステップは不要です。
SQLite vs PostgreSQL
| SQLite | PostgreSQL |
|---|
| セットアップ | ゼロコンフィグ、ファイルベース | 別のサーバーが必要 |
| 並行処理 | シングルライター(グローバルロック) | 完全なMVCC、行レベルロック |
| マルチワーカー | サポートなし(WORKERSは1である必要があります) | 完全にサポート |
| SSEストリーミング | ストリーム中に保持される接続は他のリクエストをブロックする可能性があります | 同時読み取りと書き込みは影響を受けません |
| バックアップ | .dbファイルをコピー | pg_dumpまたはストリーミングレプリケーション |
| 最適用途 | 開発、シングルユーザー、デモ | 本番環境、マルチユーザー、チーム |
ローカル開発: SQLiteはそのまま動作します — データベースサーバーなし、Redisなし、設定は不要です。コーディングを開始するだけです。本番環境: Docker Composeでデプロイし、PostgreSQL + Redisが自動的にプロビジョニングされます。手動でのデータベースセットアップは不要です。
既知の制限: SQLite 同時ストリーミング
SQLite は同時負荷下でボトルネックになる可能性があります。FIM One は Server-Sent Events (SSE) を使用して AI レスポンスをストリーミングします。ストリーミング中、各アクティブな SSE 接続はストリームの期間中、接続プールから 1 つのデータベース接続を保持します。SQLite はグローバル書き込みロックを実装しており、一度に 1 つの書き込み操作のみが実行でき、他のすべての書き込みはそれの後ろでキューイングされます。接続プールは最大 30 の同時接続をサポートしていますが(pool_size=20 + max_overflow=10)、ボトルネックはプール自体ではなく、ロック自体です。複数のユーザーが同時にチャットしている場合、彼らの書き込み操作(メッセージの保存、トークンカウントの更新)は互いに対してシリアル化されます。観察される可能性のある症状:
- 別のユーザーがストリーミング中に会話リストの読み込みが遅い
- アクティブなチャットセッション中に設定ページが遅い
- 複数のストリームがアクティブな場合、API レスポンスが遅延する
推奨事項: 2~3 人以上の同時ユーザーがいる場合は、PostgreSQL に切り替えてください。PostgreSQL は MVCC(Multi-Version Concurrency Control)と行レベルロックを使用しているため、同時読み取りと書き込みは互いにブロックすることなく独立して進行します。
コネクションプール設定
FIM One は各バックエンド用に SQLAlchemy コネクションプール設定を内部で設定します。これらはチューニング済みのデフォルト値であり、環境変数を必要としません。DATABASE_URL スキームに基づいて自動的に適用されます。これらを理解することで、実行時の動作を説明するのに役立ちます。
SQLite プール設定
| 設定 | 値 | 説明 |
|---|
pool_size | 20 | プール内の永続接続の基本数 |
max_overflow | 10 | 負荷時に作成される追加接続(合計最大30) |
| WAL ジャーナルモード | 有効 | Write-Ahead Logging により、書き込み中の同時読み取りが可能になり、ロック競合が大幅に削減されます |
busy_timeout | 30s | 書き込みロックが保持されている場合、他の書き込みは即座に失敗する代わりに、最大30秒待機してからエラーを発生させます |
synchronous | NORMAL | WAL モードで安全です。デフォルトの FULL よりも優れた書き込みスループットを提供します |
WAL モードと30秒の busy_timeout は、新しい接続ごとに SQLite PRAGMA を介して設定されます。この組み合わせにより、短命の読み取り(会話リストの読み込み、設定の取得)が長時間実行される書き込みトランザクションによってブロックされず、同時書き込みが失敗する代わりに適切にキューイングされることが保証されます。
PostgreSQL プール設定
| 設定 | 値 | 説明 |
|---|
pool_size | 10 | プール内の永続接続の基本数 |
max_overflow | 20 | 負荷時に作成される追加接続(合計最大30) |
pool_timeout | 30s | タイムアウトエラーを発生させる前に、プールから空いている接続を待つ最大時間 |
pool_recycle | 1800s | 接続は30分ごとにリサイクルされ、古い接続を防ぎます(アイドル接続を閉じるクラウドホスト型データベースの場合に重要) |
PostgreSQL は MVCC を介してネイティブに同時実行性を処理するため、プール設定は主にリソース使用量を制御し、競合ではなく。30分のリサイクル間隔により、ファイアウォール、ロードバランサー、またはアイドル TCP 接続を暗黙的にドロップするマネージドデータベースサービスの問題を回避できます。
PostgreSQLへの切り替え
ステップ 1: PostgreSQL インスタンスを起動する
最も簡単な方法は Docker を使用することです:
docker run -d \
--name postgres \
-e POSTGRES_PASSWORD=secret \
-e POSTGRES_DB=fim_one \
-p 5432:5432 \
postgres:16-alpine
ステップ 2: DATABASE_URL を設定する
.env ファイルに次の行を追加または更新します:
DATABASE_URL=postgresql+asyncpg://postgres:secret@localhost:5432/fim_one
ステップ 3: FIM One を再起動する
# Local development
./start.sh portal
# Or restart your process manager / systemd service
テーブルは初回起動時に自動的に作成されます。手動スキーママイグレーションは不要です。
既存の SQLite データは自動的にはマイグレーションされません。 DATABASE_URL を SQLite から PostgreSQL に切り替えると、新しいデータベースから開始されます。SQLite に既存の会話、エージェント、またはコネクタがあり、それらを保持する必要がある場合は、以下のデータマイグレーションセクションを参照してください。
Docker Compose (本番環境に推奨)
Docker Composeでデプロイする場合、PostgreSQLとRedisは既に含まれており、自動設定されます — 追加のセットアップは不要です。docker-compose.ymlはDATABASE_URLを内部で設定します — .envの値はオーバーライドされます:
environment:
DATABASE_URL: postgresql+asyncpg://fim:fim@postgres:5432/fim_one
Docker Composeを使用する場合、追加のデータベースセットアップは不要です。
データ移行
SQLiteからPostgreSQLへの組み込み移行ツールはありません。ほとんどのデプロイメントでは、推奨されるアプローチはあなたの状況によって異なります:
新規デプロイメント(既存データなし): DATABASE_URLをPostgreSQLの接続文字列に設定し、FIM Oneを起動するだけです。すべてのテーブルは自動的に作成されます。
保持する必要がある既存データ: 手動エクスポート/インポートが必要です。一般的なアプローチ:
sqlite3 CLIやPythonスクリプトなどのツールを使用してSQLiteからデータをエクスポートする
- 必要に応じてデータを変換する(SQLiteとPostgreSQLにはマイナーな型の違いがあります)
psql、pg_restore、またはアプリケーションレベルの挿入スクリプトを使用してPostgreSQLにインポートする
開発セットアップから本番環境にアップグレードするほとんどのユーザーにとって、PostgreSQLで新規に開始し、UIを通じてエージェントとコネクタを再作成する方が簡単です。会話履歴は通常、手動移行を正当化するほど重要ではありません。