RORK LABEN
FUNDING — RorkがLeft Lane Capital主導で$15Mのシードを調達。Peak XV・True Ventures・Goodwater・a16z Speedrunが参加しましたENGINE — Rork MaxはClaude CodeとClaude Opus 4.6で駆動。X で800万超のビューを集め、2週間で年間売上を倍増させましたSWIFT — Rork MaxはWebで初めてSwiftアプリを生成できるビルダーで、Apple伝統のXcodeを置き換える位置づけですPRODUCT — Rork MaxはiPhone・iPad・Apple Watch・Apple TV・Vision Pro・iMessageまでApple全域に対応しますCLASSIC — 通常のRorkはReact Native(Expo)で、英語の説明だけからiOS/Androidアプリを生成しストア配信できますPRICING — 無料で始められ、有料は月25ドル〜。Rork Maxは月200ドルですFUNDING — RorkがLeft Lane Capital主導で$15Mのシードを調達。Peak XV・True Ventures・Goodwater・a16z Speedrunが参加しましたENGINE — Rork MaxはClaude CodeとClaude Opus 4.6で駆動。X で800万超のビューを集め、2週間で年間売上を倍増させましたSWIFT — Rork MaxはWebで初めてSwiftアプリを生成できるビルダーで、Apple伝統のXcodeを置き換える位置づけですPRODUCT — Rork MaxはiPhone・iPad・Apple Watch・Apple TV・Vision Pro・iMessageまでApple全域に対応しますCLASSIC — 通常のRorkはReact Native(Expo)で、英語の説明だけからiOS/Androidアプリを生成しストア配信できますPRICING — 無料で始められ、有料は月25ドル〜。Rork Maxは月200ドルです
記事一覧/開発ツール
開発ツール/2026-06-25上級

機内モードで開くと有料会員にペイウォールが出る — RevenueCat の権限をオフラインでも保つキャッシュ設計

電波の弱い場所でアプリを開いた有料会員に、一瞬ペイウォールが見えてしまう。RevenueCat の customerInfo がオフライン起動で揺れる仕組みと、最後の正解を信頼期限つきでキャッシュして権限を維持する設計を、Expo アプリの動くコードで整理します。

Rork444RevenueCat26Expo99サブスクリプション60オフライン3

プレミアム記事

地下鉄に乗っている読者から「課金しているのに、アプリを開いた瞬間だけ購入画面が出る」という報告をもらったことがあります。再現しようと機内モードで自分のアプリを立ち上げたら、確かに起動直後の 1 秒ほど、有料コンテンツの上にペイウォールがちらりと重なりました。料金は払われているのに、です。

原因は課金の判定そのものではなく、権限を確認するための通信が間に合っていないことでした。RevenueCat は便利ですが、「会員かどうか」をネットワーク越しに取りに行く瞬間が必ずあります。そこがオフラインだと、アプリは一度「まだ会員と確認できていない」状態を経由します。ここからは、その瞬間に有料会員を締め出さないためのキャッシュ層を、Expo(React Native)アプリの実装として組み立てていきます。

オフライン起動で customerInfo が揺れる仕組み

react-native-purchasesPurchases.getCustomerInfo() は、まずローカルキャッシュを返し、その裏でサーバーと照合します。ここで誤解しやすいのが、キャッシュは永続的に信頼されるわけではないという点です。SDK は一定時間が経つとキャッシュを「古い」とみなし、ネットワークが必要だと判断します。完全にオフラインのコールドスタートでは、この再取得が失敗し、entitlements.active が空に近い状態で返ってくることがあります。

つまり問題は二段階で起きます。最初に SDK のキャッシュが残っていれば助かりますが、アプリを数日ぶりに開いた、あるいはOSがプロセスを完全に破棄した後だと、頼れるキャッシュがありません。ここで「active が空なら非会員」と素直に書いていると、払っている読者がペイウォールに戻されます。

私自身、壁紙アプリを 6 本ほど個人開発で運用していますが、ユーザーがアプリを開く場所は自宅の Wi-Fi だけではありません。通勤電車、飛行機、山の中、海外の空港。「通信できる前提」で権限を判定すると、もっとも静かに離れていくのは、いちばん大切にすべき有料会員です。

「最後に確認できた正解」を自前で持つ

RevenueCat のキャッシュとは別に、アプリ側で「最後に確実に会員だと確認できた事実」を保存します。重要なのは、保存するのが真偽値ではなく、いつまで有効かという期限であることです。サブスクリプションには必ず expirationDate があります。これを保存しておけば、オフラインでも「その期限まではまだ会員のはず」と判断できます。

// entitlementCache.ts
import AsyncStorage from "@react-native-async-storage/async-storage";
 
const KEY = "entitlement.lastKnownGood.v1";
const ENTITLEMENT_ID = "premium"; // RevenueCat ダッシュボードの Entitlement 識別子
 
export type CachedEntitlement = {
  // この期限まではオフラインでも会員として扱ってよい(ISO 文字列)
  activeUntil: string | null;
  // 端末時刻の巻き戻し検知用。書き込んだ瞬間の壁時計
  savedAt: string;
};
 
// ネットワークで権限を確認できたときだけ呼ぶ
export async function writeLastKnownGood(
  activeUntil: string | null
): Promise<void> {
  const payload: CachedEntitlement = {
    activeUntil,
    savedAt: new Date().toISOString(),
  };
  await AsyncStorage.setItem(KEY, JSON.stringify(payload));
}
 
export async function readLastKnownGood(): Promise<CachedEntitlement | null> {
  const raw = await AsyncStorage.getItem(KEY);
  if (!raw) return null;
  try {
    return JSON.parse(raw) as CachedEntitlement;
  } catch {
    // 壊れたキャッシュは握りつぶし、ネットワーク判定に委ねる
    await AsyncStorage.removeItem(KEY);
    return null;
  }
}

JSON.parse を必ず try で囲んでいるのは理由があります。永続化したデータは、保存途中の異常終了などでまれに壊れます。壊れたキャッシュで JSON.parse が例外を投げると、それがそのまま起動時のクラッシュになりかねません。読み取りで壊れていたら捨ててネットワーク判定に戻す、という退避を最初から書いておきます。

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
電波の弱い場所で有料会員にペイウォールが出ていた人が、オフライン起動でも権限を保てる実装を手に入れられる
RevenueCat の customerInfo のキャッシュ方針と信頼期限の置き方を理解し、解約後に権限が残り続ける事故を防げる
コールドスタートの初回描画を「読み込み中・キャッシュ・ネットワーク照合」の三段で組み、ちらつきのない課金画面を作れる
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

開発ツール2026-06-14
Rork のサブスクを RevenueCat の Entitlement で組む — アクセス判定・Offering 駆動のペイウォール・復元の実装メモ
Rork(Expo)アプリの課金を RevenueCat で実装する際の設計メモです。Entitlement を唯一の真実とするアクセス判定、Offering 駆動でハードコードを避けるペイウォール、購入復元とリスナーの実装、サンドボックスで詰まりやすい点まで動くコードで整理します。
開発ツール2026-06-16
課金復元より先に広告を初期化したら、有料ユーザに一瞬広告が出た — Rork(Expo)アプリの起動順序設計
同意取得・ATT・広告初期化・課金復元・リモート設定を、起動の数百ミリ秒のあいだにどの順番で走らせるか。順序を1つ間違えるだけで、有料ユーザに広告が一瞬出たり、EEA で同意なしの計測が走ったりします。Rork で生成した Expo アプリの起動処理を1つのオーケストレータに畳み、競合を設計で潰す手順を実装メモとしてまとめます。
開発ツール2026-06-15
解約だと思って権限を切ったユーザーは、まだ払う気だった — 支払い猶予期間と権限維持の実装
購読の支払いが失敗しても、それは解約ではありません。猶予期間中に権限を切ると復帰可能な売上を自分で捨てます。Rork(Expo)アプリで猶予・課金リトライ・アカウントホールドを取り違えず、権限維持と復帰導線を出す実装をまとめます。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →