
2026/01/24 2:26
レイテンシは誰も好まない:低遅延開発サンドボックスの構築方法
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
Summary:
アーキテクチャのオーバーホールにより、認可・ルーティング・課金・永続化を処理していた重いソケットサーバが除去されました。これにより、10〜30 秒のコールドスタートと200 ms以上のレイテンシーが解消されました。機械をウォームプールへ事前プロビジョニングすることで、コールドスタートは約50 ミリ秒にまで短縮されます。クライアントはJWT認証を用いてサンドボックスマシンに直接接続し、ソケットレイヤーを完全に排除します。課金と永続化はLLMルーターへ移行され、残高不足時にはHTTP 402を返し、バッチでデータベース書き込みを実行します。ルーティングは
<task_id>.machine.compyle.ai から <machine_id>.sandbox.compyle.ai に変更され、Fly.io の fly‑replay プロキシを活用してリクエストごとに1回だけバウンスをキャッシュします。初期の直接接続では、サンノゼデータセンターからの距離が原因でバージニア州のユーザーに約79 ミリ秒の往復レイテンシーが残ります。米国・ヨーロッパ・アジアのマルチリージョナルウォームプールを実装することで、サンドボックスをユーザーに近づけ、端末の往復レイテンシーを中央値13 ミリ秒(最小13 ミリ秒、最大16 ミリ秒)まで短縮します。最大のパフォーマンス向上は新しいコンポーネントを追加したわけではなく、ソケットサーバを除去したことによるものであり、Fly.io のプライベートネットワークとバウンス挙動のキャッシュが低レイテンシー直接接続実現の鍵となりました。本文
誰も遅延を好きではありません――特に開発者は。ターミナルやエディタで文字を入力すると、すぐに表示されることを期待します。Compyle では「一時的なクラウド開発環境」を起動し、エージェントとユーザーが IDE+ターミナルを共有しています。リモートサンドボックスをローカルのように感じさせるにはどうすればよいでしょうか?
TL;DR
低レイテンシーなサンドボックスを作りたいなら、中間者を排除し、サーバーをユーザーの近くに置きましょう。
初歩的アプローチ
当初の構成は次のようになっていました:
- ユーザーがタスクを開始
- プライマリリージョンで新しいサンドボックスをプロビジョニング
- エージェントと通信するためにソケットサーバーを介して
- 認証処理
- 正しいサンドボックスへのルーティング
- エージェントが送信したメッセージの永続化(サンドボックスには認証情報を与えない)
主な懸念事項は次の三つです:
| 懸念 | 結果 |
|---|---|
| 起動時間 | 10–30 秒 |
| レイテンシー | >200 ms |
| セキュリティ | 適切 – 公開インターネットに露出せず、秘密情報は持たない |
起動時間
- Dockerfile が数百 MB、暗号化ボリュームをアタッチ。
- 最高ケース:10 秒;最悪ケース:30 秒。
- ユーザーはエージェントの初回メッセージが来るまで最大で 30 秒間ロード画面を見る。
レイテンシー
- すべてのリクエストに余分なネットワークホップが発生。
- WebSocket 接続をソケットサーバー経由で行うとオーバーヘッド増大。
- ホットパスでの永続化はデータベースクエリから追加レイテンシーを招く。
- ターミナル/IDE の遅延:約200 ms というキー入力から文字表示までの時間 ― 受け入れ難い。
セキュリティ
- エージェントはパブリックインターネットに公開されず、秘密情報を保持しない。 (詳細は別機会に。)
起動時間の改善:ウォームプール
毎回新しいマシンをプロビジョニングする代わりに、ウォームプール を常備します:
| 変更前 | 変更後 |
|---|---|
| コールドスタート 10–30 秒 | ウォームスタート 約50 ms |
これでコールドスタートは解消されますが、レイテンシーはまだ課題です。
中間者を排除(Fly.io を愛する理由)
余分なネットワークホップを取り除くことが最大の勝利でした。ソケットサーバーには次の三つの責務がありました:
- 認証
- エージェントメッセージの課金・永続化
- 正しいマシンへのリクエストルーティング
1. 認証
旧: ソケットサーバーでユーザー認証 → DB クエリを毎回実行。
新: タスク作成時に JWT を生成し、マシンとクライアントへ送付。クライアントは直接接続し、マシン側がトークンを検証。ミスマッチは拒否。
2. 課金・永続化
旧: ソケットサーバー経由でリクエストごとに課金し、残高不足ならエージェントを中断。
新: LLM ルータがすべてのメッセージを受け取り、クレジット不足時に
402 を返却。エージェント自身をメッセージの真実源とし、永続化は別キューでバッチ処理してデータベースへの負荷を緩和。
3. リクエストルーティング
旧:
<task_id>.machine.compyle.ai のような URL を使い、DB でマシンを検索し Fly.io のプライベートネットワークアドレスへルーティング。新: ドメインを
<machine_id>.sandbox.compyle.ai に変更し、Fly.io の fly‑replay プロキシ機能を利用:
- サーバーは
と307
ヘッダーで応答fly-replay - Fly のネットワークがリクエストを指定マシンへ転送
- Fly がこの挙動をキャッシュし、転送は一度だけ行われる
マルチリージョンウォームプール
ソケットサーバーを排除した後も、地理的な距離によってレイテンシーが変わりました。
- San Francisco のユーザー → San Jose のサンドボックス:往復約 79 ms(最小 73 ms、最大 85 ms)
- 東海岸のユーザー → 同じリモートサンドボックス:同様の遅延
解決策は複数リージョンにウォームプールをデプロイし、各ユーザーのサンドボックスを地理的に近づけることです。
| リージョン | のレイテンシー |
|---|---|
| 近隣 | 最小 13 ms、最大 16 ms、中央値 13 ms(平均 14 ms) |
最終結果
- ターミナル往復時間を >200 ms から 14 ms に短縮
- アーキテクチャは初期設計よりもインフラが少なくなった
- 最大の速度向上はソケットサーバーとそのコードを排除したことによる
教訓: シンプルな解決策こそ最善。複雑さを増す前に、何を削除できるか探しましょう。