はじめに
「投稿したのに一覧に出てこない」——読み取りレプリカの遅延が原因。Read-After-Write整合性(自分が書いたものは自分が読める)とモノトニック読み取り(時間が戻らない)を保証する設計をClaude Codeに生成させる。
CLAUDE.mdに設計ルールを書く
## 読み後整合性設計ルール
- Read-After-Write: ユーザーが書き込んだ直後のクエリはプライマリDBで実行
- 書き込み後15秒以内: プライマリで読み取り、以降はレプリカに移行
- Redisにwrite_timestampを保存(TTL: 15秒)
- クリティカルなエンドポイントは常にプライマリ
生成される実装(抜粋)
// DBルーター
export class DBRouter {
async markWrite(userId: string): Promise<void> {
await redis.set(`raw:${userId}`, Date.now().toString(), { PX: 15_000 });
}
async getReadClient(userId: string | undefined): Promise<PrismaClient> {
const writeTime = userId ? await redis.get(`raw:${userId}`) : null;
return writeTime ? primaryDB : replicaDB; // TTL内はプライマリ
}
}
// Expressミドルウェア
export function trackWrite(req, res, next) {
const originalJson = res.json.bind(res);
res.json = (body) => {
if (req.method !== 'GET' && res.statusCode < 400 && req.userId) {
dbRouter.markWrite(req.userId).catch(() => {});
}
return originalJson(body);
};
next();
}
// モノトニック読み取り: レプリカラグをpg_stat_replicationで確認
async function canUseReplica(sessionId: string): Promise<boolean> {
const lastRead = await tracker.getLastReadTime(sessionId);
const replicaLag = await getReplicaLagMs(); // SELECT EXTRACT(EPOCH FROM replay_lag)*1000
return Date.now() - replicaLag >= lastRead;
}
まとめ
- CLAUDE.md に書き込み後15秒はプライマリ読み取り・モノトニック読み取り保証・Redisでwrite_timestamp管理を明記
- trackWriteミドルウェア がレスポンス成功時に自動でRedisフラグを設定——アプリコードに整合性ロジックを書かなくてよい
- attachReadDB がユーザーのwrite履歴を見てプライマリ/レプリカを自動選択——TTL15秒で自然にレプリカへ移行
- pg_stat_replication でレプリカラグをリアルタイム監視——ラグが大きい場合はプライマリへ自動フォールバック
DB設計のレビューは **Code Review Pack(¥980)* の /code-review で確認できます。*
みょうが (@myougatheaxo) — ウーパールーパーのVTuber。
Top comments (0)