Product • Development • 2026-02-18 • 12分 読了 • Jacob Clausen • Engineering
Expo の OTA アップデートサービス(EAS Update)を使って、ステージドロールアウト、リアルタイム監視、ロールバック戦略を組み合わせ、本番で安全にアップデートを配信する方法を学びます。EAS Update は数分でユーザーにアップデートを届けられる設計ですが、実際の挙動を観察したい場合は、やや慎重に進める価値があります。最も強いシグナルは、実際のユーザー、実際のデバイス、実際のトラフィックから得られます。
EAS Update は迅速な伝播を想定しつつも、本番での導入方法やどこでシグナルを見るかをコントロールできるように設計されています。テストに使える時間と対象領域が多いほど、安全にアップデートを出せる傾向がありますが、本番では無制限に時間を取れることは稀で、遅く進めることにもコストがあります。EAS Update はこのトレードオフをなくすものではなく、露出、タイミング、復旧のコントロールを提供することで、各アップデートに対してどの位置に立つか選べるようにします。
この投稿では、EAS Update を本番で運用するための実践的な流れを、ステージドロールアウトや監視から中止やロールバックまで、本番環境でこれらの仕組みがどのように振る舞うかに焦点を当てて説明します。Expo のドキュメントには、直接本番に publish するシンプルな 2 コマンドのフローから、ステージングチャネルやバージョン付きブランチを使ったより構造化されたテストフローまで、チームが使ういくつかのデプロイパターン例が掲載されています。どのパターンを選ぶかはアップデートの作り方や検証方法に影響しますが、この投稿で扱う運用上の原則(段階的に展開し、実際のシグナルを観察し、それに応じて対応する)は、ワークフローに関わらず本番に到達したアップデートに共通して当てはまります。
意図的に小さく出す(Ship small on purpose)
本番コンテキストで「小さく出す」とは、露出を制限することを意味することが多いです。アップデートを全ユーザーに即時配信するのではなく、最初は少数のユーザーにロールアウトして様子を見ることで、影響範囲を限定し、本番での挙動を観察してから拡張できます。
ロールアウトは、アプリが更新をチェックしたときにどの割合のユーザーがその更新を受け取れるかを制限します。他のユーザーは以前のアップデートのままです。本投稿では、単一の公開済みアップデートを対象に動作する「per-update rollouts」を例に説明します。例えば、最初に10%で公開することができます:
eas update --rollout-percentage = 10
これによりコストと影響を抑えつつ、本番の実ユーザーでの挙動を確認する時間が得られます。EAS Update はブランチベースのロールアウト(branch-based rollouts)もサポートしており、ユーザーを別ブランチ(update のストリーム)に段階的に切り替えることも可能です。これらのロールアウトモデルの違いに興味があれば、deployment guide を参照してください。
次に重要なのは、どのシグナルを監視し、どう解釈するかを理解することです。
アップデートのサイズと帯域幅について
ユーザーがダウンロードする各アップデートは帯域幅を消費します。例として、週に1回アップデートを公開し、ユーザーが頻繁にアプリを開く場合、月のうちに複数のアップデートをダウンロードする可能性があります。EAS Update は十分な帯域幅を含んでいるため、ほとんどのアプリで通常の使用では問題になることは少ないです。
アップデートサイズを減らすことは主に信頼性を向上させ、より頻繁にアップデートを配信できる余地を生みます。SDK 55 リリースでは Hermes bytecode diffing(現在ベータ)をオプトインで利用でき、更新が完全な JavaScript バンドルの代わりにバイナリパッチとして配布されます。クライアントは既にインストールされているものに対して diff を適用するため、ダウンロードサイズと帯域幅消費が減ります。bytecode diffing により利用可能な帯域幅の余裕が大きくなり、ユーザーは以前より少ないデータでより多くのアップデートを取得できます。
本番でのロールアウトを観察する
アップデートが少数ユーザーに公開されると、EAS ダッシュボードは本番でそのアップデートがどのように振る舞っているかをほぼリアルタイムで表示します。
アップデートの採用率とボリューム
まず見るべきは、実際にどれだけのユーザーがアップデートを取得しているかです。例えば 10% のロールアウトが設定されていても、ユーザーの 10% が即座にアップデートを適用するわけではありません。デフォルトでは、アプリはコールドスタート時に更新をチェックし、利用可能ならダウンロードします。ダウンロードした更新は次回アプリを再起動したときに適用されるため、ユーザーが一斉に採用することはありません。
チームによっては、起動時に短時間だけ更新のダウンロードを待つために fallbackToCacheTimeout を数秒調整して、アップデートをその場で適用させて採用を早めることがあります。ただしこれをすると、スプラッシュ画面がダウンロード中ずっと表示されるなど起動挙動に影響を与えることがあります。より一般的には、チームは useUpdates のような Updates の JS API を通じてライフサイクルを観察し、アプリ表示後に採用を調整します。useUpdates は更新システムの状態(例: アプリが現在更新をチェックしているか、更新が利用可能か、既にダウンロード済みか)を公開します。
いずれの設定でも、ロールアウト中に通常期待するのは「時間経過に伴う採用の漸増」であり、即時のスパイクではありません。採用が予想外に低い場合、それ自体がシグナルになります: ユーザーが十分にアプリを起動していない、またはアップデートが対象とする runtime version とビルドの対応が合っておらず想定のビルドが対象外になっている、などが考えられます。
クラッシュと致命的エラー
クラッシュデータは初期ロールアウトで最も明確なシグナルであることが多いです。起動時クラッシュや致命的なランタイムエラーは、影響を受けたユーザーがアップデート実行時に直ちに遭遇するため、早く検出されます。通常最初に目にするのは Expo dashboard のデプロイメントやアップデートビューで、各アップデートの起動データと並んでクラッシュ数を確認できます。
なぜアップデートがクラッシュするかを把握するためには、Sentry のような外部クラッシュ監視と組み合わせて、スタックトレースやセッションコンテクストをデプロイメントデータと併せて見ることが多いです。Sentry はほとんどのランタイムクラッシュや例外を拾いますが、非常に早期の起動クラッシュは App Store Connect や Play Console のプラットフォームのクラッシュ報告でしか見えないこともあります。
EAS Update には組み込みのエラー回復機能もあります。新しく適用されたアップデートが起動のごく早い段階(アプリがコンテンツを正常に描画する前)でクラッシュした場合、アプリはそのアップデートを失敗としてマークし、以前に動作していたアップデートへフォールバックできます。これは、起動時にクラッシュしてアプリが使えない状態になり、修正をダウンロードする時間すら与えられない状況を防ぐための防御機構です。
傾向を探す
初期ロールアウトのデータはノイズが多くなりがちです。サンプルサイズが小さいとスパイクやディップが誇張されることがあります。単一のデータポイントに反応するのではなく、次のような傾向を見てください:
- クラッシュやエラー率は、より多くのユーザーがアップデートを受け取るにつれて変化しているか?
- クラッシュはアップデート公開直後に集中しているか?
これらのシグナルを使って、露出を増やしたときに挙動がどう変わるかを判断します。採用が増えてもクラッシュやエラー率が許容範囲内なら、ロールアウトを拡大するのは通常合理的です。採用が増えるにつれて悪化するなら、露出を広げる前に一時停止してください。
ロールアウトを安全に拡大する
アップデートが限定露出で実行されている間に、次の判断はより多くのユーザーへ配信してよいかどうかです。ロールアウトを拡大してもアップデート自体は変更されません。新しい公開は行わず、より多くのデバイスが次回更新をチェックしたときにその同じアップデートを受け取れるようにするだけです。
ロールアウトの割合を増やすには、次を実行します:
eas update:edit
インタラクティブなガイドがアップデートを選択して新しい割合を設定するのを手助けします。監視しているシグナルが露出の増加に伴って許容範囲内であれば、フルオーディエンスに到達するまでロールアウトを拡大していけます。
アップデートの停止とロールバック
ロールアウト中に問題が発生した場合、進行度に応じて停止や元に戻す方法が2つあります。ロールアウトがまだ進行中なら revert(ロールアウトの取り消し)を使い、すでに全ユーザーに到達しているなら rollback(ロールバック)を使います。
ロールアウトを取り消す(Reverting the rollout)
ロールアウトが進行中であれば、ロールアウトを取り消すことができます。ロールアウトの取り消しはそれを停止し、コントロールアップデートを再公開してクライアントを前の状態に戻します。既にアップデートを受け取ったユーザーも元に戻ります。シグナルがロールアウトを続行すべきでないことを示している場合、ロールアウトの取り消しが適切です。
ロールアウトを取り消すには次を実行します:
eas update:revert-update-rollout
ロールアウト完了後のロールバック(Rolling back after a rollout completes)
ロールアウトが完了(例: 100% 到達)している場合、そのロールアウト自体を取り消すことはできません。その時点で、もしそのアップデートを実行すべきでないと判断したらロールバックを行います。ロールバックはクライアントに以前のバージョンを実行するよう指示する新しいアップデートを公開するか、組み込みのアップデートにフォールバックさせます。ロールバックは、アップデートが既に完全に展開されていてユーザーを既知の良好な状態に戻す必要があるときに使います。
ロールバックするには次を実行します:
eas update:rollback
インタラクティブガイドがロールバックの種類を選択する手順と実行を支援します。
永続化された状態の互換性についての注意
ロールアウトを取り消す、あるいは以前のアップデートへロールバックするという前提は、新しいアップデートで作成された永続化状態(ローカルストレージやデータベーススキーマなど)と古いコードが互換性を保っていることに依存します。アップデートが後方互換性のない変更を導入している場合、古いアップデートに戻すとクラッシュや望ましくない挙動を引き起こす可能性があります。そのような場合は、安全にロールバックできないため、互換性を回復する新しいアップデートを公開する必要があるかもしれません。
アップデートのデバッグ
Expo ドキュメントには、ビルドがアップデートを受け取らない、runtime version の不一致、起動直後にクラッシュする、アセットの読み込みに失敗するなど、一般的な失敗シナリオを順に追う包括的なデバッグガイドがあります。また expo-updates のログ確認、runtime version の検証、更新マニフェストの検査といった実用的なデバッグ手法もカバーされています。ほとんどのアップデート問題は設定の不一致や期待するアップデートの対象外になっているビルドに起因することが多く、調査するべきポイントが分かれば比較的簡単に診断できます。
まとめ
まだ本番で EAS Updates を使っていないなら、試してみる価値があります。直接ユーザーに更新を出すのは最初は大きな一歩に感じるかもしれませんが、ロールアウト、監視、復旧オプションが整っていれば、自信を持って更新を導入できるようになります。EAS Updates は高速に動く力を与えつつもコントロールを維持できるように設計されています。変更を段階的に導入し、実際のユーザーでの挙動を観察し、必要に応じて対応する—すべて同じワークフロー内で実行できます。
EAS Update は優れた開発者体験を提供し、チームが世界クラスのユーザー体験や改善を迅速に提供することに集中できるようにします。適切な運用習慣が整えば、アップデートは日々アプリを使う人々のためにアプリを継続的に改善する自然で信頼できる手段になります。