Yjsベースの共同編集アプリを作ったら、インフラ構成が3回変わった話
新しいソーシャルアプリを開発している「Senspace」でCTOをしているりょーまです。今回はYjsベースの共同編集アプリを開発する中で、インフラ構成を3回も変えることになったので、その変遷をまとめてみました。
WebSocket × リアルタイム同期のアプリの開発はいろいろライブラリがあるのでやればそこそこ調子よく進みますが、実際に運用レベルで動かそうとするとハマりどころも多いです。Yjsはそのあたりのデータ同期をすごくいい感じに抽象化してくれるライブラリですが、どのインフラで、どう永続化するか、どう再接続に耐えるかで構成が大きく変わってきます。
この記事では、最初にAWSで始めてみた構成から、Cloudflare + Partykitへの移行、さらにCloudflare独自のPartykit実装を使ってD1ストレージと組み合わせる構成に至るまで時系列で紹介していきます。
第1フェーズ:AWS構成
✅ 使用技術
- Yjs(公式ライブラリ)
- AWS Lambda + API Gateway
- DynamoDB
- CloudFront
Yjs公式が提供しているWebSocketサーバーを参考にしながら、LambdaとAPI Gatewayを使って初期構成を組みました。CloudFrontをかませて認証周りも含めて一応動く、みたいなところまではできます
❌ 問題点
WebSocketで初回同期時にやりとりされるデータ量が増えてくると、API Gatewayが抱えるWebSocketのペイロードサイズ制限(128 KB) にぶつかります。コラボレーションが活発になればなるほど初期データが大きくなって、この制限で死にます。
第2フェーズ:Cloudflare + Partykit
✅ 使用技術
- y-partykit(Partykitのyjsラッパーを利用)
- Cloudflare Workers
- Partykit
PartykitはWebSocketの扱いが楽になるライブラリで、Yjsとのラッパーもあったので使ってみました。Cloudflare Workersにデプロイする構成で、WebSocketまわりの再接続やネットワーク切断時の復旧もかなり安定。
❌ 問題点
ただし、保存周りでトラブル。具体的には以下のような挙動がありました:
- Cloudflareのコールドスタート問題で、バックエンドでデータをロードしている間にクライアントが変更を投げるとその変更が保存されないことがある
どうやら、初回ロードのGetはキャッシュしているので早いのですが、Workerの立ち上げが非同期に行われるため、そのタイミングで飛んできた更新が捨てられるっぽい。これは明確なバグというよりCloudflare WorkerとDurable Objectの仕様に近く、永続化の処理をちゃんと分ける必要があることがわかりました。Readyステートを取ることも難しそうだったので断念。
また、Partykit独自のデプロイ設定があり、Wranglerをつかった柔軟な構成変更ができない点も問題がありました。
第3フェーズ:CloudflareがつくってるPartykit + D1で永続化
最終的に行き着いたのがこの構成:
✅ 使用技術
- Cloudflare公式が提供するPartykit
- Cloudflare workers + Durable Objects
- Cloudflare D1(SQLベースの永続ストレージ)
Cloudflareが昨年Partykitを吸収しており純正のPartykit実装だとWranglerで通常通り柔軟な構成ができます。なので、Durable Objectで一時的にデータを持ちつつ、D1に定期的にスナップショット保存するような構成が組みやすいです。
🛠 工夫したところ
- Durable Object内ではYjsの状態を保持&リアルタイム配信
- 一定間隔でD1に保存
- 起動時はD1からロード → メモリ上に展開
まとめ
リアルタイムな共同編集アプリのバックエンドを構築する中で、以下のような知見を得ました:
フェーズ | 主な構成 | メリット | 課題 |
---|---|---|---|
第1段階 | AWS Lambda + API Gateway + DynamoDB | サーバーレスで構成しやすい | WebSocketの容量制限で初回同期が失敗 |
第2段階 | Cloudflare Workers + Partykit | WebSocketの管理が楽、再接続にも強い | 初回ロード中の更新が保存されない |
第3段階 | Cloudflare純正Partykit + Durable Object + D1 | 安定したリアルタイム性と永続性の両立 | 現状順調 |
Yjsを使うことで難易度が高そうな共同編集アプリも試せる反面、ちゃんと動かすにはそれなりに設計や構成が必要でした。
もしよければ、Xのフォローお願いします!
Discussion