撤退を決める前に、インストール履歴を数える

撤退の理由は、作った本人が使わなくなったことです。機能はAI(Claude Code)とMCP、スプレッドシートの組み合わせに置き換わっていました。

ただ、App Storeに載せていたアプリは、自分が使わなくなったからといってすぐ畳める保証がありません。他のストアが使っていれば、止めた時点でその人の運用に影響が出ます。

撤去前にインストール履歴を実測した

そこで、撤去前にインストール履歴を数えました。継続して入っていたのは、自社ストアと開発用ストアの2つだけでした。

第三者のストアは1件だけインストールされていました。ただし同じ日にアンインストールされていて、理由欄は「複数のアプリをテストしている」でした。第三者による継続利用はゼロです。

この数字があったので、撤退の判断を「誰にも影響しないはず」という推測ではなく、履歴の実数で下せました。畳む作業は、手順の確認より先にこの確認から始めています。

Shopifyアプリ削除の手順は5段、順番を入れ替えない

実施した順番は次の5段です。

  • 1段目 証拠保全
  • 2段目 App Storeの掲載を限定公開(非公開)にして、新規インストールを止める
  • 3段目 全ストアからアンインストールする
  • 4段目 アプリ本体をShopifyのDev Dashboardから削除する
  • 5段目 インフラを停止する(クラウドのプロジェクト、ホスティング、DB)

社内の記録には、この順でないとShopifyからGDPR用Webhookの未応答の警告が来る、とメモしています。

順番が決まる理由

アプリをアンインストールすると、あとからShopifyが必須のWebhookを送ってきます。アプリ本体やサーバーを先に消すと、そのWebhookを受ける相手がいなくなります。

だから、受け口になるサーバーは、アンインストールが終わるまで残します。インフラの停止が最後に来るのは、この理屈によります。

2段目を3段目より前に置くのも同じ考え方です。先にアンインストールだけ進めても、掲載が公開のままなら新規インストールは続きます。入口を閉じてから、中身を片づけます。

削除の前に残した証拠

1段目の証拠保全では、あとから「何がどうなっていたか」を示せるように、次のものを残しました。

  • App Store掲載ページのスクリーンショットとHTML
  • Partner管理画面のアプリ一覧
  • 掲載を限定公開に切り替える前と後の画面
  • 自社ストアでアンインストールが完了した画面
  • DB削除前の最終サマリー(テーブルごとの行数)

削除したあとは、画面も数字も取り直せません。「消したあとに手に入らないもの」を基準にすると、撮るもののリストが作りやすくなります。

DBの最終サマリー

DBは削除前に、テーブルごとの行数を記録しました。内訳は次のとおりです。

  • shops 3行
  • change_history 65行
  • link_proposals 100行
  • link_settings 3行
  • settings 3行
  • alerts、seo_templates、tasks、users 各0行

行数だけでも残しておくと、何が溜まっていたアプリだったのかを後から説明できます。中身そのものを持ち出さずに済むので、顧客データを手元に残さない点でも扱いやすい記録です。

アプリ本体を消すと、client_idは戻らない

4段目のアプリ本体の削除は、不可逆の操作です。アプリ本体を削除すると、そのアプリのclient_id(アプリ識別子)は復元できません。再開するなら、作り直しになります。

だから削除は、証拠保全、掲載の非公開化、全ストアのアンインストールが終わったあとに置きました。不可逆だと分かったうえで押す操作は、手順の最後の側に寄せます。

コードはGitHubに残す

戻せないのはアプリ本体の登録の側です。コード一式はGitHubに全量残していて、リモートとの同期も確認しています。

再開する場合でも、ゼロから書き直す必要はありません。作り直しになるのはアプリの登録のほうです。

インフラ停止で見落としやすい課金と同居DB

5段目のインフラ停止では、課金が続くものと、消す対象を間違えやすいものがありました。

クラウドの課金は小額でも止まらない

Google Cloudのプロジェクトには、保存したコンテナイメージが11.3GB、ソース置き場が10.9GB残っていました。アプリが使われていなくても、月に約200円がかかり続けていました。

このプロジェクトは削除申請の状態にしました。30日以内なら取り消せる猶予があります。小額でも放置すると止まらない費用は、畳む作業の項目に入れておきます。

ホスティングを消してもDBは残る

Vercelのプロジェクトは削除し、URLが404を返すことを確認しました。ホスティングの連携機能で作ったDBは0件でした。

DB(Neon)はホスティングとは別のアカウントで管理されていました。つまり、ホスティングを消してもDBは残ります。ホスティングを消した時点で終わった気になると、DBが取り残されます。

同居しているDBを間違えない

そのDBのアカウントには、稼働中の別サービス(アクセス解析)や、他のアプリのDBも同居していました。同じアカウントの中から消す対象を選ぶことになります。

そこで、消す対象をプロジェクトIDで確かめてから削除しました。名前の見た目や並びで選ぶと、稼働中のサービスを巻き込むおそれがあります。

破壊操作は人が実行した

DB削除のような破壊操作は、AIの自動実行のほうが安全装置で止まりました。そのため、この操作は人が手で実行しています。

AIに任せている作業でも、取り返しのつかない操作で止まる設計はそのまま残しています。止まったことを不具合とは扱わず、確認の場面として使いました。

撤去後に確認したこと

結果として、撤去の未了はゼロでした。確認できたのは次の点です。

  • 全ストアからのアンインストール完了(自社ストアは完了画面を保存済み)
  • Vercelのプロジェクト削除と、URLの404
  • Google Cloudのプロジェクトは削除申請状態(30日以内は取り消し可能)
  • DBの削除(削除前の行数を記録済み)
  • コードのGitHubへの全量保存

自作アプリを畳む前のチェック項目

  • インストール履歴を数え、継続して使っている第三者がいないか確かめる
  • 証拠(画面、HTML、DBの行数)を、消す前に残す
  • 掲載の非公開化、アンインストール、アプリ本体の削除の順を守る
  • サーバーはアンインストール後の必須Webhookの受け口として、最後まで残す
  • クラウドの保存容量とホスティングの課金を洗い出す
  • DBが別アカウントにないか、同居する他のDBがないかを確かめ、IDで対象を選ぶ
  • コードのバックアップを取り、リモートとの同期を確認する

relmeaでは、削除ボタンはこのリストが全部埋まってから押すことにしています。押す前にやることのほとんどは、記録を取ることと、順番を守ることでした。