Skip to content

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 はスレッド単位インスタンスでありユーザー単位のメモリとキーが合わない。却下。