System Design: Cloudflare Serverless Social Network
Cloudflare Workers、R2、D1、KV、Durable Objectsを活用したスケーラブルなサーバーレスSNSのシステム設計。
Twitter/XやThreadsのようなソーシャルネットワーク(SNS)を設計するには、高い書き込みスループット、リアルタイムなニュースフィード配信(Fanout Service)、そして低遅延なメディア配信が求められます。
Cloudflare Edge Ecosystem(Workers、R2 Object Storage、D1 Database、KV、Durable Objects)を活用することで、完全なサーバーレスSNSを構築できます。
1. SNSシステム設計の主な課題#
- ニュースフィード配信(Fanout): フォロワー数千〜数百万人に効率よく投稿を届ける。
- メディアの保存と配信: Egress(データ転送量)無料のストレージでコストを抑えつつCDN配信。
- エッジでの低遅延キャッシュ: ユーザーに近い位置でタイムラインやプロフィールを読み込む。
2. システム構成概要 (Architecture)#
- Cloudflare Workers: エッジAPI Gateway。認証、投稿作成、フィード取得を処理。
- Cloudflare R2: 画像・動画用の転送量無料オブジェクトストレージ。
- Cloudflare D1: 分散SQLiteデータベース(ユーザー、投稿、フォロー関係)。
- Cloudflare KV: 超低遅延なタイムラインキャッシュ。
- Durable Objects (DO): ファンアウト処理やいいね/コメント数の集計を行う非同期バックグラウンドエンジン。
+--------------+ HTTP / Upload +---------------------+
| User Client | <----------------------> | Cloudflare Workers |
+--------------+ +---------------------+
/ | \
Presigned URL | \ Cache Feed
v v v
+-------+ +-------+ +-------+
| R2 | | D1 | | KV |
+-------+ +-------+ +-------+
|
Async Event
v
+--------------------------+
| Durable Object (Fanout) |
+--------------------------+text3. 実装例 (Code Implementation)#
3.1. Durable Object + KV によるフィードファンアウト処理#
src/feed-fanout.ts
export class FeedFanoutDO implements DurableObject {
private state: DurableObjectState;
constructor(state: DurableObjectState) {
this.state = state;
}
async fetch(request: Request): Promise<Response> {
const { authorId, postId, followers } = await request.json();
// 各フォロワーのKVタイムラインに投稿IDをプッシュ // [!code focus]
const updates = followers.map(async (followerId: string) => {
const feedKey = `user:feed:${followerId}`;
const currentFeed: string[] = (await ENV_KV.get(feedKey, 'json')) || [];
const updatedFeed = [postId, ...currentFeed.slice(0, 99)];
await ENV_KV.put(feedKey, JSON.stringify(updatedFeed), { ttl: 86400 * 7 });
});
await Promise.all(updates);
return new Response('Feed Fanout Completed', { status: 200 });
}
}typescript3.2. Cloudflare R2 への直接メディアアップロード#
src/media.ts
export async function generateUploadUrl(env: Env, filename: string): Promise<string> {
// R2 署名付きアップロードURLの生成
const objectKey = `posts/${Date.now()}-${filename}`;
const signedUrl = await env.MY_R2_BUCKET.createSignedUrl(objectKey, {
expiresIn: 3600,
method: 'PUT'
});
return signedUrl;
}typescript[!NOTE] Cloudflare R2は転送手数料(Egress Fees)が完全無料なため、高画質な画像や動画配信の帯域コストを劇的に削減できます。
4. 利点と注意点 (Trade-offs)#
[!TIP] メリット:
- インフラ管理ゼロ: RedisやKafka、Kubernetesクラスターの運用管理が不要。
- エッジネイティブ: タイムラインが全世界のエッジノード(KV)から高速に返却される。
[!WARNING] 注意点:
- 超大規模アカウント対応: フォロワーが数百万人に及ぶ場合は、ハイブリッドFanout(アクティブユーザーにはFanout-on-Write、非アクティブにはD1からのFanout-on-Read)を検討する必要があります。