ADR 0008: ユーザーメモリを KV に格納する (D1 から変更)
Context
ADR 0004 は Upstash Redis の用途を「重複排除・ロック → KV」「ユーザーメモリ → D1」と振り分けていた。再検討の結果、Upstash 由来のデータは KV へ全面移行する方針に変更する。
- メモリシステム(10 種別・TTL・重要度スコア・ユーザー毎上限 100 件)は
tied-botの独自実装であり、ストレージ機能に依存していない(Redis でも単純な key-value として使っていた)。 - ユーザー毎のエントリ上限が 100 件のため、ユーザー単位の単一 JSON ドキュメントで十分扱えるサイズ(KV の値上限 25 MB に対して余裕)。
- D1 に置く場合、メモリのためだけにスキーマ・マイグレーション・Drizzle 定義が増える。D1 の利用は
reactionsに絞った方が初導入の運用負担が小さい。
Decision
- ユーザーメモリは KV の
memory:{userId}キーに単一 JSON ドキュメントとして格納する。 - 種別毎 TTL・重要度スコアリング・上限 100 件の剪定は、現行
lib/memory/のロジックをアプリ層(domain/application)に移植して維持する(KV のキー TTL は使わず、エントリ毎の期限はドキュメント内のタイムスタンプで判定)。 /memory_show/memory_stats/memory_clearはこのドキュメントの読み書きで実装する。- D1 のテーブルは
reactionsのみとする(ADR 0004 の他の決定 — Turso→D1 / ベクトルは Vectorize / S3→R2 — は変更なし)。
Consequences
- 良い点: Upstash の置き換え先が KV に一本化され、D1 スキーマが最小になる。メモリの読み書きは「ユーザー毎 1 get / 1 put」で完結し、実装が単純。
- 悪い点 / 注意:
- 同一ユーザーのメモリを並行更新すると last-write-wins で片方が消える可能性がある(read-modify-write)。ユーザー単位の更新頻度は低く実用上許容するが、問題になれば該当処理を Agent (DO) 経由に直列化するか D1 に昇格する。
- 全ユーザー横断の集計(管理画面の
/memories一覧など)は KV の list + 逐次 get になる。後続フェーズで管理画面を作る際、必要なら D1 への昇格を再検討する。
- フォローアップ: 既存 Upstash データのバックフィルスクリプト(Redis → KV JSON ドキュメント変換)。
Alternatives
- D1 に格納(旧 ADR 0004 案): 型付き集計・横断検索に強いが、当面の利用(bot の応答時参照 +
/memory_*)にはユーザー単位ドキュメントで十分。スキーマ運用が増えるため見送り(将来の昇格余地は残す)。 - Agent (DO) のストレージに格納: 強整合だが、Agent はスレッド単位インスタンスでありユーザー単位のメモリとキーが合わない。却下。