コンテンツへスキップ
DedicatedPHP 接触

猶予期間付きSaaSアカウント解約の設計方法

解約申請、一時停止、最終クローズを分け、アクセスと処理を制御し、リソースを重複させずに組織を再有効化する方法を解説します。

申請から再有効化または最終クローズまでを示すSaaSアカウント解約の状態遷移図

猶予期間付きのSaaSアカウント解約は、単一の操作を先送りするものではありません。アクセス、請求、自動タスク、連携、データを調整するライフサイクルフローです。アプリケーションがクローズ日を保存し、ログイン時に確認するだけでは、ほかのプロセスが組織を有効な状態として処理し続ける可能性があります。

各段階の意味、誰が状態を遷移させられるか、どの効果を元に戻せるかを明確に設計する必要があります。そうすれば、申請の取り消しがアカウントを一から再構築することにはならず、期限への到達もユーザーが再度ログインするかどうかに左右されません。

解約申請、一時停止、最終クローズを分ける

解約申請、一時停止、最終クローズを分ける — guía visual de DedicatedPHP

申請は意思を示すもので、権限のある人がアカウントのクローズを求めます。一時停止では、申請の処理中に組織が何を実行できるかを定めます。最終クローズでは、認証情報の失効、処理の停止、データポリシーの適用など、最後のアクションを実行します。これらは異なる時点であり、分けてモデル化するのが適切です。

アクセス制限をいつ開始するかは、重要なプロダクト上の判断です。期限までアクセスを維持する場合は、そのことを明確に伝え、その間の利用を管理する必要があります。直ちに制限する場合、猶予期間はアカウントの復旧に使うものであり、通常どおりサービスを使い続けるためのものではありません。普遍的な正解はなく、ビジネスモデル、リスク、プロダクトの義務によって異なります。

請求やサブスクリプションへの影響も定義する必要があります。アカウントを解約しても外部サブスクリプションが必ず解約されるわけではなく、支払いの解約によって組織を削除すべきとも限りません。各判断の正となる情報源を明確にし、決済プロバイダーの単独イベントから稼働状態を推測しないようにします。

状態と許可する遷移を定義する

状態を明示したモデルを使うと、UI、API、バックグラウンドジョブに同じルールを適用しやすくなります。簡単なフローでは、active、deletion_requested、suspended、closedなどの状態を使えます。申請と同時に一時停止するなら、申請状態を一つだけ設け、制限を示す属性を持たせれば十分な場合もあります。実際の運用上の違いを表さない状態は追加しないでください。

有効な状態遷移を文書化します。たとえば、有効な組織は解約を申請でき、有効な申請は取り消すことができ、期限切れの申請は最終クローズへ移行できます。一般に、クローズ済みの組織を同じ取り消し操作で再開できるようにすべきではありません。復旧を提供する場合は、別の手順と明確な制限が必要です。

  • 申請を開始した人、日時、経路、猶予期間の終了日時を記録します。
  • 権限と現在の状態は、UIだけでなくサーバー側でも確認します。
  • 繰り返しの遷移や同時申請を拒否するか、明示的に処理します。
  • 状態変更をアトミックに保存し、トランザクショナル・アウトボックスなどの信頼できるパターンで副作用を通知します。

PHPアプリケーションでは、状態遷移のルールをドメインサービスなどの同等のレイヤーに集約します。コントローラーが複数のフィールドを直接変更し、すべての利用側が新しい意味を理解すると想定すべきではありません。データベースには、保留中の処理が以前のWebリクエストの状態に依存せず、対応するアクションを判断できるだけの情報を保持します。

アクセスを制限し、保留中の処理を封じ込める

猶予期間中のロールごとの権限を定義します。管理者には解約の取り消しやエクスポートに必要な情報の閲覧を許可し、組織のメンバーはブロックする、といった設計が考えられます。読み取り専用アクセスを許可する場合は、対象となるリソースと、API、ダウンロード、管理機能を引き続き利用できるかを明確にします。同じ制御をUI、API、自動化ジョブに適用する必要があります。

ログインをブロックするだけでは不十分です。アクセストークン、APIキー、アクティブなセッション、連携用認証情報は引き続き使える場合があります。どれを失効させ、どれを一時停止し、どれを一時的に保持するかを決めます。認証情報を失効させる場合は、再有効化がすでに存在しないシークレットに依存しないよう、その影響を記録します。再発行が必要になることもあります。

キューやスケジュール済みタスクも見直します。たとえば、送信、同期、レポート、webhook、請求処理などです。外部に影響する操作を実行する直前に、各プロセスが組織の最新状態を確認する必要があります。すでにキューに入っているジョブは、明示したポリシーに従ってキャンセル、保留、または完了させます。アカウントの状態を変更すれば、分散キューのメッセージも自動的に取り除かれると想定しないでください。

タスクのキャンセルにも冪等性が必要です。ネットワーク障害で再試行されたジョブが、通知やクローズ処理を重複して実行してはなりません。適切なイベントID、冪等性キー、一意制約を使い、結果を記録して、安全な再試行と新しいアクションを区別します。

解約の取り消しと再有効化を安全に行う

猶予期間中の申請取り消しは、何が起きたかを確認せずに「すべてを元に戻す」処理ではなく、定義済みの状態遷移であるべきです。処理では期限内であることを検証し、状態を一度だけ更新したうえで、一時停止していた機能のうち現在も有効なものだけを復元します。

重複を避けるため、サブスクリプション、webhook、スケジュール済みタスク、ワークスペース、認証情報を無差別に再作成しないでください。安定した識別子を保持し、副作用ごとに状態を記録します。外部コンポーネントがすでに解約されている場合、アプリケーションはその状態を照合できる必要があります。存在するか確認し、制御された方法で再作成するか、手動対応が必要であることを通知します。

冪等な再有効化では、複数回リクエストされても同じ最終状態になります。ローカル変更にはトランザクションを使い、無条件の挿入ではなく更新操作を行い、外部システムには再試行戦略を用いることで、この性質を支えられます。処理が途中で失敗した場合は、完了済みのステップを記録し、成功済みのものを繰り返さずに続行できるようにします。

データ、追跡可能性、最終クローズを扱う

運用上のクローズとデータ削除は別の判断です。組織のデータ、バックアップ、監査ログ、法的または契約上の義務により保持する情報をどう扱うか定義します。適用される期間や理由は状況や管轄区域によって異なるため、プライバシーとコンプライアンスの責任者と確認する必要があります。適用されるポリシーに基づき、何を削除し、何をどのくらいの期間保持するかを顧客に伝えます。

猶予期間が終了したら、スケジュールされたプロセスで保留中の申請を検索し、アカウントをクローズする前に状態と期限を再確認します。一部の処理が失敗した場合、システムは失敗したステップを記録し、再開できる必要があります。closedフラグだけでは、認証情報の失効や連携の停止が完了した証拠にはなりません。

申請、取り消し、権限変更、最終処理の実行、エラーを追跡できるように記録します。記録へのアクセスを制限し、シークレットや不要な個人データを含めないようにします。想定時間を超過したケース、たとえば期限切れなのに有効な組織や、エラーの繰り返しで止まっているクローズをアラートで知らせます。

フローのテストチェックリスト

フローのテストチェックリスト — guía visual de DedicatedPHP
  • 権限のない人は解約を申請も取り消しもできない。
  • 解約を2回申請しても、期限、イベント、クローズが重複しない。
  • 猶予期間中、各ロールには定められた機能だけが正確に許可される。
  • セッション、トークン、API、キュー、連携が組織の状態に従う。
  • 期限前に取り消すと、処理やリソースを重複させずに所定のアクセスが復元される。
  • 期限切れの申請は遅れて届いたリクエストで取り消されず、クローズも二重に実行されない。
  • 一部失敗や再試行があっても、外部への影響を重複させずにクローズを完了できる。
  • データの保持・削除ルールは、運用上のアクセス制限とは別に検証される。

同時変更、キューの遅延、外部プロバイダーのエラーもテストしてください。設計の一貫性を示すのは、画面に「アカウントをクローズしました」と表示されることだけではありません。権限、処理、認証情報、データが同じ判断を反映し、システムがその状態に至った経緯を説明できることが重要です。

これらのアイデアをあなたのプロジェクトに活用してみませんか?あなたのPHPプラットフォームについて話し合いましょう。
関連サービスを見る