---
schema_version: "1"
id: 1f53a14f92e03ad04389a98e5331bf34201edf2430b684a7b3177b244efd5e56
title: レコードトリガーオートメーション
collection: architect
version: current
locale: ja-jp
portal_url: https://docs.salesforce.com/architect/current/ja-jp/decision-guides/guides/record-triggered.md
canonical_url: https://architect.salesforce.com/docs/architect/ja-jp/decision-guides/guide/record-triggered.html
source_site: architect.salesforce.com
content_type: documentation
content_hash: b25367f13dbe422f7f57ea8f886e1e7ce0eba188fa038618c3c67cef3c73548e
products:
  - 決定ガイド
  - Architect Site Content Repo
updated_at: 2026-02-01T00:00:00Z
---
# レコードトリガーオートメーション

Salesforce Platform は、複雑なビジネスプロセスの要求を満たすために自動化アーキテクチャを継続的に進化させてきました。旧世代 (ワークフロールールとプロセスビルダー) では、イベント駆動型ロジックの最初のステップが提供され、イベント駆動型ロジックの自動化機能が拡張され、ビルダーの範囲が広がりました。

この進化により、レコードトリガーフローとApexトリガーという2つの補完的な柱を中心とした、パフォーマンスに優れた統合アーキテクチャが実現しました。

## ガイドの概要

このドキュメントでは、トリガー自動化を設計するときに十分な情報に基づいて意思決定を行うためのフレームワークとガイドラインについて説明します。Salesforce レコードへの変更によってトリガーされる自動化の適切なアプローチを選択する際の指針となる 3 つの主要な決定ポイントと使用事例の要件のバランスを取ります。

## スコープ内の商品

<table style="border:none">
  <tbody>
    <tr style="border:none">
      <td style="text-align:center;vertical-align:middle;border:none;padding:0.25rem 0">フロー</td>
      <td style="vertical-align:middle;border:none;padding:0.25rem 0"><a href="https://help.salesforce.com/s/articleView?id=platform.automate_about.htm&type=5">Salesforce Flow</a>は、強力なポイント・アンド・クリック自動化ツールです。ユーザーは、コードを記述せずに、Flow Builderを使用して複雑なビジネス・プロセス、画面、ロジックを視覚的に作成できます。データ更新、メールの送信、ユーザーへの案内などのタスクを自動化し、画面フロー (ユーザー操作) やトリガーフロー (レコード/スケジュール済みイベント) などの種別で柔軟性を提供します。</td>
    </tr>
    <tr style="border:none">
      <td style="text-align:center;vertical-align:middle;border:none;padding:0.25rem 0">Apex</td> 
      <td style="vertical-align:middle;border:none;padding:0.25rem 0"><a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_intro_what_is_apex.htm">Salesforce Apex</a> は、Java に似た Salesforce Platform 用の独自のオブジェクト指向プログラミング言語で、カスタムビジネスロジックの構築、プロセスの自動化、宣言型ツール以外のコア CRM 機能の拡張に使用されます。</td>
    </tr>
  </tbody>
</table>

## ポイント

Salesforce Platform で拡張性、メンテナンス性、パフォーマンスに優れたレコードトリガー自動化を構築するには、統制の取れたアーキテクチャ主導のアプローチが必要です。フローと Apex の選択とそれぞれの実装は、明確な原則セットに従って行われます。これらのポイントはこれらの原則を要約し、最新の自動化設計の基本ルールとして機能します。

- **Salesforceオブジェクトの自動化密度に基づいて、ジョブに適したツールを選択します。**

  - **低密度**のオートメーションには、Salesforce オブジェクトのレコードトリガーフローを使用します。

  - 呼び出し可能なApexを使用してレコード トリガー フロー ロジックを増強し、**中密度**の自動化を実現します。

  - SalesforceオブジェクトのApexトリガーを使用して、**高密度**の自動化を実現します。

- **非同期プロセスをトリガーするときは注意してください。**  
  このルールは、レコード トリガー フローで非同期プロセスを呼び出す場合でも、Apex からキュー可能なジョブを呼び出す場合でも適用されます。このパターンは、作業の負荷を軽減しがちですが、複雑なエラー処理シナリオが発生し、ガバナ制限に達するリスクが高まる可能性があります。

- **Salesforce オブジェクトごとに 1 つのエントリポイントを使用します。**  
  特定の Salesforce オブジェクトで、自動化へのエントリポイントとして 1 つのメカニズムを使用します。同じオブジェクトのエントリ ポイントとしてフロー トリガーと Apex トリガーを混在させないようにしてください。

## 決定ポイント

考慮すべき主な決定ポイントは次の 3 つです。

- 宣言型とプログラムによる実装
- オートメーション密度
- 密度選択マトリックス

### 宣言型とプログラムによる実装

フローと Apex には、共通の基本機能セットがあります。各ツールは、レコードの照会、条件ロジックの実行、変数の割り当て、およびレコードの作成、更新、削除などの DML 操作 (指定された順序で実行) を実行できます。

ただし、この機能の重複は、ツールが交換可能であるという意味ではありません。アーキテクチャの選択は、タスクを実行できる_かどう_かではなく、タスクを_どのよう_に実行し、パフォーマンス、拡張性、および保守性に長期的な影響があるかについてです。フローは、宣言型の明確さと簡単なプロセスの実装速度に優れており、Apexは、複雑なソリューションに必要な詳細な制御と強力な処理能力を提供します。

### オートメーション密度

**自動化密度**は、特定の Salesforce オブジェクトにかかる負荷です。これは、オブジェクトの最適な実装を判断するためのヒューリスティックとして機能します。自動化の密度が高まるにつれて、トランザクション制限に違反する可能性が高くなります。

量と複雑さの 3 つの特定のディメンションを調べて、自動化密度を計算します。

- **オートメーション数量:** 1 つのデータ操作言語 (DML) イベント中に実行される一意の自動化メタデータエントリ (フロー、トリガーアクションなど) の未加工の数。

- **レコード量:** API 読み込みまたは高負荷のバッチ処理によって処理されるトランザクションあたりのレコード数。パフォーマンスが重要になります。

- **依存関係の無秩序な増加:** 最初の CRUD 操作によってトリガーされる下流の DML 操作の基準。1 つの更新が関連オブジェクトの更新にカスケードされるグラフの深さを定量化します (ケース → 取引先 → 取引先責任者 → カスタムロールアップなど)。

<img style="border:1px solid #e5e5e5;margin:2rem 0rem" src="https://a.sfdcstatic.com/developer-website/prod/images/architect/record-triggered/automation-density.png" alt="オートメーション密度ディメンション">

Salesforceアプリケーションのスコープと複雑さが増大するにつれて、レコードトリガーフローまたは Apexトリガーのいずれか、ひとつの主要なエントリーポイントに統一することを推奨します。1 つの Salesforce オブジェクトで複数のメカニズムにわたって自動化をパーティション分割すると、メンテナンス性が低下し、ガバナンスが断片化してしまうため、避けてください。

### 密度選択マトリックス

このマトリックスを使用して、Salesforce オブジェクトに必要なアーキテクチャ標準を決定します。

- **レコード トリガー フロー**は、自動化密度が低い場合に推奨されるソリューションです。互いに独立していてわかりやすいオートメーションに最適なパワーとアクセシビリティのバランスを実現します。

- **ハイブリッド パターン(**呼び出し可能なApexを使用したレコード トリガー フロー)は、複雑さが増している中密度の自動化に適した強力でメンテナンス可能な選択肢です。このパターンにより、チームは宣言型 Flow において整然とした処理の流れを維持しつつ、計算負荷の高い操作を Apex に委任し、アクセシビリティとパフォーマンスのバランスを実現できます。

- **Apexトリガー**は、高密度のオートメーションを支える堅牢なアーキテクチャ構築のための基本要素を提供します。Apexのパフォーマンス、詳細な制御、およびオブジェクト指向の抽象化と多態性は、これらのシナリオの複雑さと拡張性の管理に適しています。

<table>
  <thead>
    <tr>
      <th scope="col" style="width:8%">密度レベル</th>
      <th scope="col" style="width:18%">自動化数量</th>
      <th scope="col">データ量 (バッチサイズ)</th>
      <th scope="col">依存関係の無秩序な増加</th>
      <th scope="col">アーキテクチャ標準</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><b>Low (低)</b></td>
      <td><b>&lt; 15</b><br>
        オートメーション</td>
      <td><b>標準</b><br>
        ユーザー主導の UI 操作または小さな API 読み込み (1 ～ 200 レコード)</td>
      <td><b>個別</b><br>
        自己完結型ロジック。同じオブジェクトまたは関連オブジェクトに対する 0 ～ 1 のダウンストリーム DML 操作。</td>
      <td><b>レコードトリガーフロー</b></td>
    </tr>
    <tr>
      <td><b>Medium (中)</b></td>
      <td><b>15–30</b><br>
        オートメーション</td>
      <td><b>中程度</b><br>
        標準バッチ処理 (慎重な一括処理が必要なロジックを使用)</td>
      <td><b>密結合</b><br>
        親/子の更新、2～4件のダウンストリーム DML 操作。再帰のリスク</td>
      <td><b>ハイブリッドパターン</b><br>
        フロー + 呼び出し可能な Apex</td>
    </tr>
    <tr>
      <td><b>High (高)</b></td>
      <td><b>> 30</b><br>
        オートメーション</td>
      <td><b>High (高)</b><br>
        一括 API 読み込みを使用する大量のデータ (2,000 ～ 10,000 件以上のレコード)</td>
      <td><b>複雑および再帰的</b><br>
        深い依存関係グラフ (5 つ以上の下流 DML 操作)。三角再帰ループのリスク</td>
      <td><b>Apexトリガー メタデータ フレームワーク</b></td>
    </tr>
  </tbody>
</table>
実際のアーキテクチャ上の意思決定では、オートメーション密度のすべてのディメンションを総合的に考慮する必要があります。特定の Salesforce オブジェクトのオートメーションメカニズムを選択するときは、将来のスコープを考慮してください。

また、Salesforce はマルチテナント環境で共有リソース管理を適用し、暴走した自動化によって共有リソースが独占されないように [府の制限](https://developer.salesforce.com/docs/atlas.en-us.salesforce_app_limits_cheatsheet.meta/salesforce_app_limits_cheatsheet/salesforce_app_limits_platform_apexgov.htm)を適用しているため、1 日あたりの DML 操作の合計数を考慮してください。1 日の DML 量が多い Salesforce オブジェクトでは、自動化の選択を慎重に行う必要があります。たとえば、CPU 時間 (60,000 ミリ秒) とヒープサイズ (12 MB) の非同期制限は同期制限よりも高くなります。さらに、非同期実行に関する組織全体の24時間の制限（25万、またはユーザーライセンスの200倍として計算）では、実行時の例外を回避するために1日あたりの合計DMLをアーキテクチャ設計に組み込む必要があります。

## 商品比較

レコードトリガーフローは、レコードトリガーによるオートメーションのためのプラットフォームのPremierな宣言型ツールです。Flow の使いやすさと組み込みのプラットフォームのセーフガードにより、チームは拡張性と信頼性に優れたソリューションを簡単に構築できます。これは、Salesforce Platform でソリューションを構築するほとんどのチームにとって理想的な選択肢です。

Apex は、プラットフォーム独自の強く型付けされたオブジェクト指向プログラミング言語です。Apex は、オートメーション密度の高い Salesforce オブジェクトや、高いパフォーマンス、高度なロジック、またはトランザクションにおけるきめ細かな制御を必要とするユースケースに使用してください。

意思決定プロセスを支援するために、このマトリックスでは主要なアーキテクチャ機能における Flow と Apex の直接比較を提供します。

<table>
  <thead>
    <tr>
      <th scope="col">機能</th>
      <th scope="col">レコードトリガーフロー</th>
      <th scope="col">Apex トリガー</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><b>デリバリーとメンテナンスの迅速性</b></td>
      <td><b>推奨</b><br>
        Flow Builder のビジュアル・ユーザー・インタフェースを使用すると、管理者やその他の宣言型ビルダーは、Apexコードの作成、テスト、リリースよりも迅速に自動化を作成および変更できます。このインターフェースにより、より幅広いチームメンバーがビジネス上の価値を実現でき、単純なタスクの専門的な開発者リソースへの依存が軽減されます。</td>
      <td><b>専門知識が必要</b><br>
        Apex では、コードの実装、テスト、管理に適切なスキルを持つソフトウェア開発者が必要です。</td>
    </tr>
    <tr>
      <td><b>モジュール性</b></td>
      <td><b>利用可</b><br>
        レコードトリガーフローはデフォルトでモジュール化されています。モノリシックロジックではなく、チームは特定の要件に合わせて個別のフローを作成し、フロートリガーエクスプローラーを使用してそれらを一緒に振り付けます。このモジュール化により、変更が分離され、簡単に拡張できるため、長期的な所有コストを大幅に削減できます。</td>
      <td><b>利用可</b><br>
        Apex は、設計上、機能モジュールに分割されています。各 Apex クラスは、1 つの機能モジュールを実装することを目的としています。</td>
    </tr>
    <tr>
      <td><b>可視性とガバナンス</b></td>
      <td><b>推奨</b><br>
        フローの視覚的な性質により、ビジネスロジックが直感的に表現されます。フロートリガーエクスプローラーでは、オブジェクトのすべてのフローの統合ビューが提供されるため、アーキテクトやシステム管理者はコードを読むことなく簡単に理解、管理、トラブルシューティングできます。</td>
      <td><b>専門知識が必要</b><br>
        メタデータ フレームワークを使用してトリガーを整理することは有益ですが、Apexでは、コードを整理して保守できるように、統制の取れた開発チームが必要です。</td>
    </tr>
    <tr>
      <td><b>高パフォーマンスの一括データ処理</b></td>
      <td><b>非推奨</b><br>
        複雑なロジックや大量のデータを処理する場合、ガバナ制限に達するリスクが高くなります。</td>
      <td><b>推奨</b><br>
        Apexコードはプラットフォームのコア・サービスに近い場所で実行され、開発者はクエリの最適化、データ処理、アルゴリズムの効率性をより詳細に制御できます。これにより、特に大量のデータを含む複雑なシナリオでパフォーマンスと拡張性が向上します。</td>
    </tr>
    <tr>
      <td><b>堅牢なロジックとデータ構造</b></td>
      <td><b>利用可</b><br>
        <a href="https://help.salesforce.com/s/articleView?id=platform.flow_ref_elements_transform.htm&language=en_US&type=5">フロー変換要素</a>は、いくつかの複雑な処理タスクに役立ちます。ただし、フローにはネイティブの Map および Set データ構造がないため、複雑なデータ処理が煩雑になり、計算効率が低下します。</td>
      <td><b>推奨</b><br>
        Apex では、対応付け、設定、プログラムによるループにフルアクセスして、効率性の高い安全な一括データ操作を実行できます。Apex は、フル機能のプログラミング言語であり、複雑なビジネス問題を保守可能かつ効率的に解決するのに役立つ複雑な論理構造、データ構造、設計パターンへのアクセスも提供します。Apexには、現在宣言型ツールでは使用できない高度な関数（BusinessHours、Cryptoなど）の豊富な標準ライブラリが含まれています。</td>
    </tr>
    <tr>
      <td><b>トランザクション制御</b></td>
      <td><b>使用不可</b><br>
        フローでは、部分的なトランザクションの確定またはロールバックで `Database.savepoint`、`Database.rollback`、または部分的に成功した DML 操作にアクセスできません。</td>
      <td><b>利用可</b><br>
        Apexは、トランザクションの整合性と複雑なエラー・リカバリのシナリオをフルかつ詳細に制御します。</td>
    </tr>
    <tr>
      <td><b>メール配信</b></td>
      <td><b>推奨</b><br>
        レコードトリガーフローから事前設定されたメールアラートを送信するのは、簡単で拡張性があります。カスタムメールアラートは、実行時に作成および配布できます。カスタムメールには、<a href="https://help.salesforce.com/s/articleView?id=000381534&type=1">毎日のメール送信</a>制限が適用されます。</td>
      <td><b>利用可</b><br>
        Apex はカスタム電子メール メッセージを生成および送信できます。Apex から送信されるすべてのメールには、<a href="https://help.salesforce.com/s/articleView?id=000381534&type=1">1 日あたりのメール送信</a>制限が適用されます。</td>
    </tr>
    <tr>
      <td><b>プラットフォーム保護の適用</b></td>
      <td><b>推奨</b><br>
        フローには、自動一括処理や自動再試行などの組み込みの保護が含まれます。これらの保護により、価値実現までの時間を短縮し、複雑な手動コーディングを必要とするパフォーマンスの低下を回避できます。</td>
      <td><b>手動実装が必要</b><br>
        一括処理などの保護は、明示的にコーディングする必要があります (コレクションの管理やループ内での SOQL の回避など)。自動再試行はトリガーに固有ではなく、実装するには複雑なカスタムロジックが必要です。</td>
    </tr>
    <tr>
      <td><b>非同期処理</b></td>
      <td><b>利用可</b><br>
        フローは、非同期パスで個別のトランザクションを必要とする自動化の簡単なメカニズムを提供します。これらの自動化には 1 日の制限が適用されます。</td>
      <td><b>利用可</b><br>
        Apex では、変更データキャプチャと、分離されたトリガー登録者によって処理されるキュー可能なイベントを使用して、完全な制御が可能になります。</td>
    </tr>
    <tr>
      <td><b>スケジュール済み処理</b></td>
      <td><b>推奨</b><br>
        フローのスケジュール済みパスには、ユニークで強力なスケジュール機能 (「完了予定日の 3 日前に開始」など) があります。この機能には、レコードのデータが変更された場合の自動キャンセルと再スケジュールが含まれます。これらの自動化には 1 日の制限が適用されます。</td>
      <td><b>使用不可</b><br>
        Apex トリガーでは、自動キャンセルを使用する一時的なレコード固有のイベントをネイティブにスケジュールできません。スケジュール済み Apex は存在しますが、基本的に異なるメカニズムであり、特定の時間に実行され、トリガーの一部として個々のレコードの処理中にスケジュールされることはありません。</td>
    </tr>
    <tr>
      <td><b>順序と調整</b></td>
      <td><b>利用可</b><br>
        フロートリガーエクスプローラーでは、管理者は同じオブジェクトの複数のフローの相対的な実行順序を定義できます。</td>
      <td><b>利用可</b><br>
        トリガーフレームワークでは、自動化の正確な順序を詳細に制御できます。</td>
    </tr>
    <tr>
      <td><b>同じレコードの項目更新</b></td>
      <td><b>入手可能 (保存前)</b><br>
        レコードトリガーフローは、最初の DML 確定の前にトリガーレコードを更新するための最もパフォーマンスの高い宣言型オプションです。</td>
      <td><b>入手可能 (保存前)</b><br>
        Apex は、最小限のオーバーヘッドで最高のパフォーマンスを提供します。</td>
    </tr>
    <tr>
      <td><b>クロスオブジェクト CRUD</b></td>
      <td><b>入手可能 (保存後)</b><br>
        フローは、シンプルで複雑度の低いクロスオブジェクト DML 操作に適しています。</td>
      <td><b>入手可能 (保存後)</b><br>
        Apexは、重複除外、エラー処理、クロスオブジェクトDML操作のパフォーマンスをより詳細に制御します。</td>
    </tr>
    <tr>
      <td><b>高価な計算の重複排除</b></td>
      <td><b>利用可</b><br>
        フローは、自動一括処理によって冗長なクエリと DML ステートメントを排除することに長けています。ただし、異なるフロートリガー間、または 1 つのトランザクション内の同じフローの複数の呼び出し間で状態をキャッシュまたは共有することはできません。この制限は、極端なパフォーマンスのシナリオでは重要になる場合があります。</td>
      <td><b>推奨</b><br>
        Apexは、コストのかかる操作の重複除外メカニズムを提供します。開発者は、静的プロパティと変数を使用するトランザクションキャッシュと、プラットフォームキャッシュを使用するプラットフォームレベルのキャッシュを活用して、データを保存および再利用できます。これらの技術は、SOQL クエリなどのトランザクションガバナ制限の消費を減らし、高いパフォーマンスと拡張性を確保するために重要です。</td>
    </tr>
    <tr>
      <td><b>カスタムエラー処理</b></td>
      <td><b>利用可</b><br>
        CustomError 要素は、保存操作をブロックし、ユーザーにメッセージを表示することができます。</td>
      <td><b>推奨</b><br>
        <code>addError()</code> メソッドは、柔軟な項目レベルおよび条件付きエラーメッセージングを提供します。</td>
    </tr>
  </tbody>
</table>

## 使用事例

判断の指針となる決定ポイントの使用方法を最も強調するには、次の使用事例と関連分析ポイントを考慮してください。

### 最適なレコメンデーション

この表は、提示された機能に基づき、一般的なユースケースに対する「最適な」推奨事項を示しています。最終的には、このドキュメントの「_関連するベストプラクティス_」セクションに記載されているような、特定のシナリオに最適な追加考慮事項も考慮します。ここでは、フローとApexの特定の組み合わせが最適なアプローチである場合についての詳細を説明します。

<table>
  <thead>
    <tr>
      <th scope="col">使用事例</th>
      <th scope="col">説明</th>
      <th scope="col" style="width:16%">Best-Fit</th>
      <th scope="col" style="width:38%">根拠</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><b>高パフォーマンスのバッチ処理</b></td>
      <td>何千ものレコードを効率的に処理する必要がある自動化</td>
      <td>Apex</td>
      <td>Apex は、プラットフォームとのインタフェースと未フォーマット時の速度を実現する豊富な API を提供します。</td>
    </tr>
    <tr>
      <td><b>複雑なデータ処理</b></td>
      <td>高度なデータ操作が必要なシナリオ</td>
      <td>Apex</td>
      <td>Apex は、Map や Set などのデータ構造を提供します。これらは、フローではネイティブに使用できず、パフォーマンスが高く一括安全なコードを記述するために不可欠です。</td>
    </tr>
    <tr>
      <td><b>トランザクション制御</b></td>
      <td>セーブポイント、ロールバック、部分的な確定などの制御メカニズム</td>
      <td>Apex</td>
      <td>Apex は Database.savepoint や Database.rollback などのメカニズムへのアクセスを提供し、部分的に成功した DML 操作を処理する機能を備えています。</td>
    </tr>
    <tr>
      <td><b>高度なカスタム検証</b></td>
      <td>レコードの複数の項目のデータ検証</td>
      <td>Apex</td>
      <td>フローでは `CustomError` 要素を使用して保存を防ぐことができますが、サブフローを含むすべてのフロー種別で使用できるわけではありません。Apex <code>addError()</code> メソッドは、トリガー処理中にいつでもレコードに追加できる複数の項目固有のエラー メッセージを提供します。</td>
    </tr>
    <tr>
      <td><b>単純なプロセス内のロジックがやや複雑</b></td>
      <td>高度な関数の標準ライブラリによって簡略化された、中程度の複雑さのロジックとデータ操作 (複雑なプロセスの一部として発生)</td>
      <td>フロー + Apex</td>
      <td>レコードトリガーフローはオーケストレーションレイヤーとして機能し、高複雑度のオペレーションはInvocable Apex内にカプセル化されます。</td>
    </tr>
    <tr>
      <td><b>シンプルから適度に複雑なロジック</b></td>
      <td>主データオブジェクトと関連データオブジェクトの両方に対するトリガー更新による、低から中程度の複雑さのデータ操作</td>
      <td>フロー</td>
      <td>フローは、システム管理者とデベロッパーの両方が扱いやすい宣言型モデルに基づいているため、通常は最適な選択肢となります。</td>
    </tr>
    <tr>
      <td><b>通知および送信メッセージ</b></td>
      <td>アウトバウンドメールおよびメッセージの送信</td>
      <td>フロー</td>
      <td>フローを使用すると、レコードの変更時にメールアラートおよびアウトバウンドメッセージの送信が容易で、拡張性にも優れています。</td>
    </tr>
    <tr>
      <td><b>スケジュール済み処理</b></td>
      <td>将来の動的な日付 (完了予定日の 3 日前など) での自動化</td>
      <td>フロー</td>
      <td>スケジュールパスは、レコードのデータが変更された場合にプラットフォームがこれらのパスのスケジュール設定、キャンセル、再スケジュールを自動的に処理するため、フローに独自の強みをもたらします。</td>
    </tr>
  </tbody>
</table>

### スケーラブルな処理: 非同期ユースケースの詳細

拡張性は、実装を設計するときの重要な考慮事項です。レコードトリガーオートメーションのビジネスロジックが複雑になったり、実行時間が長くなったり、大量のデータが関係したりすると、Salesforce Platform のコアガバナ制限がアーキテクチャ上の制約になります。データの一括更新、複雑な API コールアウト、重い計算などの操作は、合計 CPU 時間や 1 つのデータベーストランザクション内の DML ステートメント数などの制限に違反するリスクを高めます。制限例外が原因で同期トリガーが失敗すると、ユーザーの保存トランザクション全体がロールバックされ、ユーザーエクスペリエンスが低下し、データが失われる可能性があります。この固有のリスクにより、複雑な作業の負荷が軽減されるアーキテクチャパターンが必要になります。

この場合、非同期オートメーションが不可欠です。アーキテクトは、非同期メカニズムを使用して、実行時間が長い作業や大量の作業を、同期レコード保存の主トランザクションから効果的に分離できます。迅速かつ信頼性の高い方法で保存が完了し、重い処理は後で実行される別のプラットフォーム管理トランザクションに委任されます。分離により、安定性が向上し、トランザクションの失敗が防止され、拡張性の高い企業向けアプリケーションの構築に不可欠です。このプラットフォームは、信頼性、ボリューム、複雑さという各観点から明確な利点とトレードオフを持つ、いくつかの特殊なツールを提供します。

### フローの非同期パス

レコードトリガーフローの「非同期で実行」パスは、「起動して忘れる」非同期ロジックの最もシンプルなメカニズムを提供します。このパスは、元のレコード保存トランザクションがデータベースに正常にコミットされた後、個別のトランザクションで実行されます。

- **理想的な使用**事例: これは、即時実行やカスタムエラー処理を必要としないタスクに適しています。たとえば、メール通知の送信、フォローアップ ToDo の作成、外部システムへの簡単なコールアウトなどです。

- **制限事項**: このメカニズムは、他の非同期フローインタビューと同じ1日のガバナ制限を共有します。大量の処理には適していません。

### 変更データキャプチャ (CDC)

変更データキャプチャ (CDC) は、大規模シナリオでのレコード変更によってトリガーされる非同期ロジックを処理するための高スループット、拡張性、復元性の高いパターンです。このモデルでは、トリガーの唯一の責務はレコードの同期保存です。次に、プラットフォームは、大規模イベントバスへのレコードの変更を含む詳細なイベントメッセージを公開します。個別の専用 Apex トリガーがこの変更イベントに登録します。複雑で実行時間が長い作業や非同期の作業を実行します。

- **メリット**: このパターンでは、非同期プロセスを最初のユーザートランザクションから分離します。非同期処理が失敗しても、ユーザーのレコード保存はロールバックされません。このパターンでは、複数の内部登録者または外部システムが使用できる耐久性のあるイベントストリームも提供され、イベントを最大 72 時間再生できるため、強力な復元力が得られます。

- **制限**: CDC イベントメッセージには、レコードの前の状態 (Apex `Trigger.oldMap`に相当) は含まれません。イベントペイロードには、新しい項目値が含まれますが、変更元の値は含まれません。そのため、特定の状態遷移に基づいてロジックを実装することが困難です (たとえば、`Status__c`が「待機中」から「承認済み」に変更された場合にのみ実行)。イベント登録者でオブジェクトの項目履歴を照会することでこれを軽減できますが、これによりプロセスが複雑になり、特定の関心項目で項目履歴管理が使用できない場合があります。これにより、CDC にオフロードできる自動化の種類が制限される場合があります。

デフォルトでは、CDC は最大 5 つの Salesforce オブジェクトで有効にできます。追加が必要な組織は、この制限を削除し、イベント配信の割り当てを増やす Add-on/アドオン ライセンスを購入できます。

### トリガーからのキュー可能 Apex

Queueable Apex ジョブをトリガーから直接キューに入れることは、リスクの高いパターンと見なす必要があります。これは、Apex による制御が必要な場合 (複雑なロジックやカスタム再試行メカニズムなど) にのみ使用され、CDC は実行可能なオプションではありません。

Queueable Apex が必要な場合は、実装に適切な保護を含める必要があります。

- **制限チェック**: コードは、別のジョブを追加する前に、トランザクションですでにキューに入っているジョブの数を確認する必要があります。

  ```
  if (Limits.getQueueableJobs() < Limits.getLimitQueueableJobs()) { ... }
  ```

- **コンテキスト認識**: コードは、一括処理ジョブ (`System.isBatch()`) などの非同期コンテキスト内で実行されているかどうかを検出し、そのコンテキストで適用されるトランザクションあたりの 1 ジョブの制限に準拠するように動作を変更する必要があります。

### トリガーされた非同期 Apex の制限に関する考慮事項

同期トリガーから非同期 Apex を呼び出すと、安定性のリスクが生じます。組織レベルの影響 (制限を超えるなど) を回避するために、このパターンには厳格な設計とテストが必要です。

- 非同期Apex実行の1日あたりの制限(`Batch`、`Queueable`、`@Future`)は、組織全体で共有されます(通常は25万件、またはユーザー・ライセンスに基づく計算)。20,000 レコードの一括データ読み込みでは、トリガーが 200 のチャンクで実行され、100 の個別のトリガー呼び出しが発生します。一括バッチサイズが 200 レコード未満の場合、さらに多くなります。各呼び出しで非同期ジョブがキューに入れられると、1 つのデータ読み込みによる 1 日あたりの制限のかなりの部分が消費される可能性があります。この消費によっては、他の重要なビジネスプロセスにとって必要な非同期リソースが枯渇する可能性があります。

- ジョブをキューに入れるためのガバナ制限は、コンテキストによって大幅に異なります。UI のユーザーアクション (_同期_トランザクション) によって起動されるトリガーから、最大 50 個のキュー可能なジョブをキューに追加できます。ただし、バッチ Apex クラスの `execute` メソッド内 (非_同期_トランザクション) で起動されたトリガーから、キューに入れることができるジョブは 1 つのみです。この違いを考慮しないと、大規模データ操作中に`LimitException`エラーが発生する、一般的で重大な障害点になります。

- トリガー コンテキストから直接 Schedulable Apex(`System.schedule`)または Batch Apex(`Database.executeBatch`)をコールすると、アンチパターンになります。これらのメソッドは、トリガーコンテキストから呼び出すようには設計されていません。これを行うと、非同期 Apex 割り当てが急速に消費され、制限例外が発生します。

### 適切な非同期パターンの選択

各非同期メカニズムには、パフォーマンス、ガバナ制限、信頼性に関する特定のトレードオフがあります。この決定ツリーをガイドとして活用し、これらのオプションを検討して、ユースケースに適したメカニズムを選択してください。

<img style="border:1px solid #e5e5e5;margin:2rem 0rem" src="https://a.sfdcstatic.com/developer-website/prod/images/architect/record-triggered/async-pattern.png" alt="非同期パターン決定ツリー">

### スケジュール済みジョブの代替

フローチャートが示すように、大規模な DML 操作に直面しているが (オブジェクトの制限などにより) 変更データキャプチャを使用できない場合、多くの場合、最適なアーキテクチャの選択はトリガーで呼び出されるプロセスを完全に回避することです。

代わりに、スケジュール済みプロセスを使用することを検討してください。これは、スケジュール済みフローまたはスケジュール済み Apex のいずれかです。必要な手順は次のとおりです。

1. 同期トリガーでシンプルで低コストの更新を実行します。たとえば、`Status__c` フィールドを「処理待機中」に設定したり、Chatter投稿などの低コストの関連レコードを挿入して、レコードの処理が必要であることを示します。

2. 15 分ごとや 1 時間ごとなど、定期的に実行されるスケジュール済みジョブ (スケジュール済みフローまたはスケジュール済み Apex) を作成します。

3. スケジュール済みジョブで待機中の状態のすべてのレコードを照会し、制御された大量のコンテキストで複雑なロジックを実行して、レコードを処理済みとして更新します。

このパターンは、重い処理をユーザーの同期保存から完全に分離し、トリガー起動バッチのトランザクションあたり1つのジョブの制限を受けず、非リアルタイム要件に対応する拡張性とガバナンスが高いソリューションを提供します。

スケジュール済みジョブのレイテンシがビジネス要件で許容できない場合、CDCまたはトリガー起動キューイブルの使用が引き続き制限されている場合は、アーキテクチャの重大な不一致を示します。この時点で、異なるメカニズムを考慮する必要があります。コアアプリケーション設計を再評価すると、次のような特定の結論に達する可能性があります。

- CDC オブジェクト制限を削除するアドオンの購入。

- ほぼリアルタイムの処理が本当に「必須」なのか、スケジュール済みジョブの遅延がプラットフォームの安定性にとって許容可能なトレードオフなのかを判断するビジネス要件に根本的に挑戦します。

## 機能以外の考慮事項

決定ポイントに加えて、複雑さや標準など、機能以外の考慮事項も考慮する必要があります。

### 複雑さ

実装の複雑さのレベルは、ソリューションの総所有コストだけでなく、変化するビジネス要件に適応する能力にも影響します。ベストプラクティスに従わないと、実装が複雑になる可能性があります。このドキュメントの「_Related Best Practices_ (関連するベストプラクティス)」セクションでは、ソリューションの複雑さを軽減するための推奨事項を次に示します。

- ハイブリッドパターン: フローでの複雑なロジックの呼び出し可能な Apex

- Apex トリガーでのメタデータフレームワークの使用

- メガフローと複数のフロー

### プロセスと標準

本ドキュメンテーションはオートメーション自体と同じくらい重要です。メンテナンス性が確保されるだけでなく、AI やエージェントベースのツールにとっても重要です。ドキュメントは、ビジネスプロセスの理解と管理に役立ちます。

**In Flow**

- すべての要素と変数に一貫した命名規則を設定します。

- フローの \[説明] 項目を使用して、フローの全体的な目的、トリガー条件、意図した結果を説明します。

- 個々の要素 (`Get Records`、`Action`、`Transform` など) で [説明] 項目を使用します。これは、意図を伝えるための最良の方法です。これは、呼び出し可能なアクションとサブフローで特に重要であり、説明はアクションによって実行される複雑なロジックを説明する主要な場所です。

**In Apex**

- ロジックの背後にある_理由_を、_何_であるかだけでなく、明確にコードにコメントします。

- メタデータ駆動型フレームワークを使用している場合は、メタデータレコードに人間が判読可能な \[説明] 項目が含まれていることを確認し、各ハンドラークラスが実行する内容と実行タイミングを説明します。

DevOps とソース管理は、成熟した開発ライフサイクルの一部です。Salesforce プロジェクトでは、Git などのソース管理ツールを常に使用します。Apex クラスと Salesforce フローはどちらもビジネス ロジックを定義するメタデータであり、バージョン管理する必要があります。

レコードトリガー自動化の管理のコンテキストでは、最新の DevOps パイプラインには不可欠な利点があります。

- **自動品質チェック:** [Salesforce Code Analyzer](https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/overview) などのツールは、パイプライン内で自動的に実行するように設定できます。静的分析では、昇格前に両方の自動化ツールの問題パターンを検出し、パフォーマンス低下の一般的な原因である、フロー ループ内の非効率的な`Get Records`要素やループのApex内の`SOQL`クエリなどの問題にフラグを設定できます。

- **回帰防止:** 自動化の密度が高まると、1 つのフローまたは Apex クラスを変更すると、同じオブジェクトの他の自動化に意図しない結果が生じる可能性があります。提案された変更に対して自動化されたApexテストを実行する堅牢なDevOpsテスト戦略は、新しいフロー バージョンで既存のApexロジックが破損しないこと(およびその逆)を確認する最も信頼性の高い方法です。

- **コラボレーションと可視性:** ソース管理は「単一の情報源」です。これにより、システム管理者と開発者は同じオブジェクトの自動化に並行して取り組むことができます。また、貴重な監査証跡も提供されます。本番プロセスが中断すると、自動化を変更した_ユーザー_、自動化を変更した_タイミング_、および(確定メッセージを介して)自動化を変更した_理由_をすぐに確認できます。

管理者と開発者が混在するチームの場合、[DevOps Center](https://help.salesforce.com/s/articleView?id=platform.devops_center_overview.htm&type=5)では、これらのすべてのステップをコレオグラフィーするのに役立つ統合インターフェイスが提供され、拡張性の高いソース制御ベースの開発プロセスをチームの全員が利用できるようになります。

ドキュメントと DevOps のこの組み合わせにより、組織の長期的な健全性とメンテナンス性が確保され、フォローするすべてのアーキテクトとシステム管理者にメリットがもたらされます。

## 関連するベストプラクティス

上記の決定ガイドは、実装を計画する前に使用することをお勧めします。使用事例に最適な製品を選択できるようにすることを目的としています。製品を選択したら、実装の既存のベストプラクティスを理解することが重要です。

### ハイブリッドパターンの活用: フローでの複雑なロジック用の呼び出し可能な Apex

_オブジェクトあたり1_つのツールの原則は、高密度の自動化を管理するために重要ですが、それを純粋に宣言型か純粋にプログラム スタックかの二者択一として解釈しないでください。より効果的で管理しやすいアーキテクチャパターンでは、ハイブリッドモデルを活用します。つまり、レコードトリガーフローをオーケストレーションレイヤーとして配置しながら、呼び出し可能な Apex 内で高複雑度の操作がカプセル化されます。

<img style="border:1px solid #e5e5e5;margin:2rem 0rem" src="https://a.sfdcstatic.com/developer-website/prod/images/architect/record-triggered/hybrid-pattern.png" alt="ハイブリッドパターン図">

#### オーケストレーションレイヤー: フロー

レコードトリガーフローは、ビジネスプロセスのオーケストレーションレイヤーとして機能します。エントリ条件と実行コンテキスト (_何_と_いつ_) を所有します。このレイヤー内で決定ロジックとルーティングを保持することで、フロートリガーエクスプローラーでアーキテクチャのプロセストポロジーを透過的かつ管理可能にし、重要なビジネスロジックがコード内で不明瞭にならないようにします。

#### 複合コンポーネント: 呼び出し可能な Apex

複雑なコンポーネントの一般的な例として、ケースレコードのサービスレベル契約 (SLA) の計算の実装があります。BusinessHours オブジェクトとその関連ロジックは、非勤務時間と休日を除外する正確な計算に不可欠ですが、フローではネイティブにアクセスできないため、専用の Apex クラスが使用されます。このクラスは、多くの場合 `ServiceLevelAgreementCalculator` などと呼ばれ、`@InvocableMethod` で注釈が付けられた 1 つの静的メソッドを使用して設計され、経過した営業時間を計算し、SLA が「目標内」か「違反」かを判断し、構造化された出力を返します。このアプローチでは、Apexの複雑で高パフォーマンスのロジックをカプセル化しつつ、レコードトリガーフローの宣言型のオーケストレーションレイヤーにシームレスに実行・統合されます。

Apex `ServiceLevelAgreementCalculator` クラスが定義されると、レコードトリガーフロー内で使用できるようになります。

このパターンは、懸念の厳格な分離を示しています。宣言型レイヤーはトランザクションライフサイクルとオーケストレーションの管理に使用され、コードは高複雑度の実行に使用されます。コードを基盤ではなく機能的なユーティリティとして扱うことで、パフォーマンスとメンテナンス性のバランスを取ります。

#### ハイブリッドパターンの主な利点

**モジュール性**: この手法は、プロセス全体でApexまたはフローのみを使用するという一辺倒なアプローチから脱却しています。代わりに、アーキテクチャは複雑なロジックを、バルクセーフかつ個別にテスト可能なユニットにカプセル化します。これらのユニットは宣言型レイヤーで使用される再利用可能なコンポーネントとして機能し、アーキテクチャ設計を複雑にすることなく自動化を拡張できます。

**再利用性**: ロジックはトリガーイベントから分離されます。適切に設計されたコード ユニット(`InvocableMethod`など)は1回のみ記述され、複数のエントリー ポイント(レコードトリガー フロー、画面フロー、外部インテグレーション)で活用されます。このコードの再利用により、冗長な開発が排除されます。

**保守性**: プロセスフローロジックは宣言型フロー内で表示および管理可能なままです。この一元化により、デバッグのオーバーヘッドが大幅に削減され、システムの実行順序が確定的で透過的になります。

#### ハイブリッドパターンの制限とトレードオフ

フローから呼び出し可能な Apex を使用するハイブリッド モデルは強力ですが、汎用的なアプローチではありません。アーキテクトは、ハイブリッド ソリューションに取り組む前に、特定の制限とトレードオフを認識しておく必要があります。

- **No before-save support**: これは最も重要な制限事項です。呼び出し可能なアクションは、保存後コンテキスト (アクションと関連レコードのフロー) でのみ使用できます。高パフォーマンスな保存前コンテキスト（フィールドの高速更新のフロー）では使用できません。そのため、このパターンを使用して同じレコードのフィールドの更新を委任することはできません。保存前フローまたは保存前コンテキストのApexトリガー内でネイティブのフロー要素を使用して、高パフォーマンスの仕事を実行します。

- **No after-undelete support:** 現在、レコードトリガーフローでは復元後のコンテキストはサポートされていません。Salesforce オブジェクトに、ごみ箱からレコードを復元するときに自動化を実行するというビジネス要件がある場合、Apex トリガーが唯一のソリューションです。

- 大規模シナリオの**パフォーマンスオーバーヘッド:** フローランタイムから Apex ランタイムへの移行は、コストゼロの運用ではありません。一般に高速ですが、フローのランタイムから呼び出し可能アクションにドロップする動作は、Apex トリガー内に完全に収まるネイティブ実行ほど計算速度は速くありません。ほとんどの中密度のオートメーションでは、このマイクロオーバーヘッドは無視できるほど小さく、アクセシビリティの向上に十分見合うものです。ただし、極端に高パフォーマンスかつ高ボリュームのシナリオでは、Apexのみのフレームワークの方が純粋な計算速度の点で有利です。

### 従来の自動化の戦略

オートメーション密度のヒューリスティックは、新しいグリーンフィールドアーキテクチャには決定的な指針を提供しますが、企業のSalesforce環境における実情は、より複雑なことが多いです。成熟した組織では、同じ Salesforce オブジェクトで動作するレコードトリガーフローと Apex トリガーを見つけるのが一般的です。このシナリオは、前に説明したハイブリッド パターンとは異なります。ここでは、フローと Apex トリガーが結合されておらず、連携するように設計されていません。

この共存は、多くの場合、プラットフォーム機能の進化や従来の技術的負債が原因です。これは許容される運用状態ですが、アーキテクトはそれを最終状態ではなく、計算されたトレードオフとして捉える必要があります。

オーケストレーションが断片化することで、ガバナンスとメンテナンスのオーバーヘッドが大きくなり、開発、テスト、インシデント処理の作業がバラバラになり、煩雑になります。これにより、解決までの時間 (TTR) が増加し、運用が複雑になります。

- 新しい Salesforce オブジェクトの場合、主要なガイドとして自動化密度の原則に従います。

- 既存の Salesforce オブジェクトで、ハイブリッドなフットプリントを持ち、レコードトリガーフローと Apex トリガーの両方のエントリーポイントが存在する場合、密度を評価した上で、メンテナンス性を考慮したハイブリッド状態にリファクタリングするよう設計します。

  - 低密度の場合は、Apexトリガーをレコード トリガー フローにリファクタリングし、実行順序を指定して、1つの自動化エントリ ポイントに取り込みます。

  - 中密度の場合は、複雑な大規模フローを、適切な実行順序を保ったまま、フローのサブセットにリファクタリングします。Apex トリガーは、削除取消後のコンテキストをサポートするなど、どうしても必要な場合にのみ導入してください。

  - 高密度の場合は、Apexトリガーの実装をお勧めします。

### Apex トリガーでメタデータフレームワークを使用する

Salesforce Platform での組織のビジネスプロセスが成熟するにつれて、レコードトリガー自動化の量と複雑さは必然的に増加します。基本的なベストプラクティスは、_ApexトリガーをSalesforceオブジェクト_ごとに1つ管理することです。プラットフォームでは、同じイベントに対して同じオブジェクトに対する複数のトリガーの実行順序が保証されないため、このルールは非常に重要です。この制限により、動作が不安定になったり、競合状態になったり、デバッグが困難になったりする可能性があります。

ただし、_ワン トリガー_の原則に従うと、アーキテクチャ上の課題が生じます。つまり、その1つのエントリー ポイントから呼び出されるすべてのビジネス ロジックを、メンテナンス可能で拡張可能な方法で管理およびオーケストレーションする方法です。

#### Classic トリガハンドラの制限事項

このアーキテクチャの最初の進化は Classic トリガハンドラパターンでした。この方法では、1 つの Apex トリガーですべてのロジックが対応するハンドラ クラス（`OpportunityTriggerHandler` など）に委任されます。このメソッドにより、ロジックがトリガーファイルから分離され、開発者はハンドラクラスのメソッド (`afterInsert()` など) 内の実行順序を決定的に制御できます。

このパターンは改善されていますが、多くの場合、ハンドラークラスがモノリシックになります。ビジネス要件が追加されるにつれ、クラスは大規模になり、管理が難しくなり、単独でテストすることも困難になります。すべての個々のプロセスの実行順序が 1 つのメソッド内でハードコードされるため、クラスがマージの競合を起こしやすく、大規模なエンタープライズ環境でのガバナンスとメンテナンスのオーバーヘッドが大幅に増加します。

#### 解決策: メタデータ駆動型トリガーフレームワーク

モジュール性とオーケストレーションのコア問題を解決するために、アーキテクトは**メタデータ駆動型トリガー フレームワーク**に移行します。これは、自動化ロジック自体を実行_方法_と実行_タイミング_の設定から分離する、アーキテクチャ上の重要な飛躍です。

このフレームワークは、次の3つの主要な利点に基づいて構築されています。

- **パーティショニング:** 1 つのハンドラ クラスではなく、コア ビジネス ロジックが小さな原子 Apex クラス (`RecalculateAccountValues` クラスや `NotifySalesLeads` クラスなど) に分割され、各クラスが \[_Single Responsibility Principle_ (単一責任の原則)] に従います。このモジュール化により、ロジックを個別にテスト、デバッグ、および理解しやすくなっています。

- **順序と振付:** Apex で実行順序がハードコードされなくなりました。代わりに、通常はカスタムメタデータ型 (`TriggerAction__mdt` など) に保存されている設定レコードによって宣言的に定義されます。これにより、管理者はリリースやコードの変更を必要としないメタデータレコードを変更するだけで、自動化アクションの並び替え、追加、削除ができます。

- **バイパス機能:** このフレームワークは、標準化された詳細なバイパス機能を提供します。各自動化アクションは、そのメタデータレコードを使用してグローバルに無効にするか、カスタム権限を参照して特定の管理ユーザーに対してスキップするように設定できます。

オブジェクトの単一の Apex トリガーは、動的ディスパッチャーとしてのみ機能します。ビジネスロジックが含まれておらず、代わりに中央`MetadataTriggerHandler`クラスがインスタンス化されます。このハンドラは、カスタムメタデータレコードを照会して実行順序を動的に決定し、指定された順序で正しいアトミック Apex クラスを呼び出します。自動化は、1 つの透過的で管理可能なレイヤーで統合されます。

### トランザクションでの高価な操作の重複排除

堅牢なフレームワークでApexを使用する重要なメリットは、トランザクションの状態を管理でき、重複作業を排除してパフォーマンスを最適化できることです。ロジックが蓄積されると、保存順序内のさまざまなオートメーションが同じ高価な操作を個別に実行し、貴重なガバナ制限を消費して DML 操作時間が増加することがよくあります。

このフレームワークは、次の 2 つの主な戦略でこれに対処するように設計されています。

- **共有状態管理:** 1つのApexトランザクションの範囲内で、静的プロパティと変数を使用してデータをキャッシュします。これにより、設定の`SOQL`クエリなどの高価な操作は、トリガーの異なるレコードまたはフェーズで自動化ロジックが複数回呼び出された場合でも、1 回のみ実行されます。トランザクション制限の消費が大幅に削減されます。

- **プラットフォームキャッシュ利用**率: 単純なトランザクション内キャッシュだけでなく、プラットフォームキャッシュを使用して、データベース全体で特定のデータを照会しないようにします。この管理対象のメモリ内キャッシュは、非プリミティブで、コードベース全体で頻繁に参照され、トランザクション全体 (プロファイル、ロール、営業時間など) で不変のデータを取得する場合に最適です。`Cache.CacheBuilder` インターフェイスを使用して、システムは最初にキャッシュを確認し、データが存在しない場合にのみデータベースクエリを実行するため、パフォーマンスと拡張性が最大限に高まります。

### 同じレコードの更新には保存前更新を使用

オートメーションでトランザクションを開始するレコードの項目値のみを変更する必要がある場合は、必ず保存前更新を使用してください。これは、フローにおける高速フィールド更新（保存前に実行）と、Apex トリガーにおける保存前のコンテキストロジック（挿入前、更新前）の両方に適用されます。

このパターンは、2 回目の DML 操作と再帰的な保存サイクルが回避されるため、どのツールを使用してもパフォーマンスは優れています。変更は、データベースにコミット_される前_にメモリ内のレコードに対して行われ、元のトランザクションの一部として保存されます。保存順序全体を再実行し、すべてのオートメーションを再度実行する2回目の保存のオーバーヘッドが排除されます。

### 非制御再帰の防止

非制御再帰は、更新後のトリガーでよく発生する落とし穴で、トリガーのロジックによって DML 更新が実行され、同じトリガーが再度起動されます。これにより、最終的にガバナ制限例外で終了する無限ループが発生します。これまで、静的 Boolean フラグや処理済みレコード ID のコレクションは、このような再帰を防ぐために使用されてきましたが、より正確で堅牢なパターンは、レコード自体の新しいバージョンと古いバージョン間で項目値を比較してロジックをゲートすることです。

ロジックは、関心のある特定の項目が実際に変更された場合にのみ実行します。これにより、重要なデータが変更されない同じトランザクション内の後続の DML 操作でトリガーのロジックが実行されなくなります。

#### レコードトリガーフローでの再帰の制御

レコードトリガーフローでは、条件の要件を満たすようにレコードが更新されたときにのみ実行されるようにフローを設定することで、非制御の再帰を防止します。

<img style="border:1px solid #e5e5e5;margin:2rem 0rem" src="https://a.sfdcstatic.com/developer-website/prod/images/architect/record-triggered/recursion-flow.png" alt="レコードトリガーフローでの再帰の制御">

フローで入力条件数式を使用する場合、`$Record` グローバル変数 (新しい値を表す) と `$RecordPrior` グローバル変数 (保存前の元の値を表す) を比較することで、暴走を回避できます。たとえば、商談の \[金額] 項目が変更された場合にのみフローが実行されるようにするには、次のように入力条件で使用します。

```
$Record.Amount != $Record__Prior.Amount
```

#### Apex での再帰制御

新しいバージョンのレコード `Trigger.new` の項目値と古いバージョンのレコード `Trigger.oldMap` の項目値を比較し、探している特定の変更が行われているかどうかを確認します。このアプローチにより、自動化が即効性を発揮し、必要な場合にのみ実行されるため、システムの効率が向上し、破滅的な再帰ループを回避できます。

### 自動化のスキップ

優れた設計の Salesforce 組織には、オートメーションをバイパスするための一貫して信頼性の高いメカニズムが必要です。これは省略可能な機能ではなく、データの整合性を維持し、管理タスクを有効にするためのコア業務要件です。

次のようなシナリオでは、バイパスフレームワークが不可欠です。

- 大量のデータを読み込む場合、レコードごとにトリガーをトリガーすると、プロセスが大幅に遅くなり、制限例外が発生し、誤った関連レコードと通知が作成される可能性があります。バイパスを使用すると、データをクリーンかつ効率的に挿入できます。

- インテグレーションユーザーは、外部の記録システムからデータを同期する必要がある場合があります。ユーザーが開始した変更 (メールの送信、ToDo の作成など) で通常起動される自動化は、変更が別のシステムから行われた場合に望ましくない場合や冗長になる場合があります。

- システム管理者またはサポートスタッフは、レコードの修正更新を実行する必要がある場合があります。バイパスメカニズムを使用すると、意図しない結果になる可能性がある標準のビジネスオートメーションをトリガーせずにこれらの変更を行うことができます。

**カスタム権限**: バイパス ロジックを実装するための最新のスケーラブルな標準はカスタム権限です。これらは、いくつかの理由で古い方法よりも優れています。

- **柔軟性:** 権限セットを使用してカスタム権限をユーザーに割り当てることができます。この手法は、最新の Salesforce セキュリティおよびアクセスモデルに準拠しているため、きめ細かく柔軟な割り当てが可能です。バイパスは特定のユーザーに付与することも、特定の有効期限で一時的に付与することもできます。

- **保守性:** カスタム権限を使用すると、プロファイルやユーザーを自動化ロジックにハードコードする必要がありません。ユーザーのロールが変更されたり、新しいプロファイルにアクセスをバイパスする必要がある場合、変更は単純な権限セットの割り当てであり、リリースを必要とするコードやフローの変更ではありません。

- **拡張性:** カスタム権限は、複雑なユーザーベース全体で例外を管理するためのスケーラブルなフレームワークを提供します。権限セット、権限セットグループ、またはプロファイルを使用してユーザーに割り当てることができます。権限セットまたはプロファイルへの関連付けもソースメタデータで表現できます。

**実装パターン**: 組織内のすべてのレコードトリガー自動化に一貫したバイパスパターンを適用します。

**レコードトリガーフローのバイパス**: フローをバイパスする最も効率的な方法は、フローの実行を一切防止することです。これは、フローのエントリ条件に条件を追加することで実現されます。

- レコードトリガーフローの開始要素で、\[エントリ条件] を \[数式が True と評価] に設定します。

  - 数式ビルダーで、`$Permission` グローバル変数を使用してカスタム権限のチェックを組み込みます。チェックを既存のエントリ条件と組み合わせます。

    - 数式パターン:

    ```
    ( ) && NOT($Permission.Bypass_This_Flow)
    ```

  - このパターンにより、指定されたカスタム権限がユーザーに割り当てられ_ていない_場合にのみフローが実行されます。このチェックは、フローインタビューが作成される前に実行されるため、最もパフォーマンスの高い方法です。

**Apex トリガー フレームワーク**のバイパス:Apex で、バイパス ロジックをメタデータ駆動型トリガー フレームワークに直接統合し、詳細な制御を可能にします。

- `TriggerAction__mdt` カスタムメタデータ型には、`BypassPermission__c` などのテキストフィールドを含める必要があります。

  - `MetadataTriggerHandler` クラスでは、アクションを動的に実行する前に、コードがこの項目の値を読み取る必要があります。

  - フィールドに値が入力されている場合、ハンドラは `FeatureManagement.checkPermission()` メソッドを使用して、現在の実行ユーザーに指定したカスタム権限があるかどうかを判断します。

  - `checkPermission()` が true を返すと、ハンドラはその特定のアクションをスキップし、シーケンスの次のアクションに進みます。

  - このパターンは、グローバルバイパス (すべての`TriggerAction__mdt`レコードが同じ権限を参照している場合) とアクションごとの詳細なバイパス (異なるレコードが異なる権限を参照している場合、または一部のレコードにまったくバイパス権限がない場合) の両方を可能にするため、強力です。

### メガフローと複数のフロー

これは、オブジェクトのすべてのオートメーションを 1 つの巨大なメガフローに統合するのはアンチパターンです。1つのフローに統合するのと、ロジックを複数の条件が整ったフローに分割するのとでは、パフォーマンスに大きな影響はありません。最も大きなパフォーマンス向上は、次の点から得られます。

- 同一レコードの項目自動更新に、保存前フローを使用します。

- 特定の使用事例に影響しない変更に対してフローの実行が除外されるように、正確なエントリ条件を記述します。

[フロートリガーエクスプローラー](https://trailhead.salesforce.com/content/learn/modules/record-triggered-flows/meet-flow-trigger-explorer)では、オブジェクトの各フローに順序値を割り当てて、順次実行順序を保証できます。

<img style="border:1px solid #e5e5e5;margin:2rem 0rem" src="https://a.sfdcstatic.com/developer-website/prod/images/architect/record-triggered/trigger-explorer.png" alt="Flow Trigger Explorer">

## リソース

<table>
  <thead>
    <tr>
      <th scope="col">Apex</th>
      <th scope="col">フロー</th>
      <th scope="col">業務</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>
        <ul>
          <li><a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_intro_what_is_apex.htm">Apex とは?</a></li>
          <li><a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_integration_intro.htm">Apex ユーティリティ</a></li>
        </ul>
      </td>
      <td>
        <ul>
          <li><a href="https://help.salesforce.com/s/articleView?id=platform.automate_about.htm&type=5">Salesforce フローを使用した自動化について</a></li>
          <li><a href="https://trailhead.salesforce.com/content/learn/modules/record-triggered-flows/meet-flow-trigger-explorer">Flow Trigger Explorer のご紹介</a></li>
          <li><a href="https://help.salesforce.com/s/articleView?id=platform.flow_ref_elements_transform.htm&language=en_US&type=5">Flow 変換要素</a></li>
        </ul>
      </td>
      <td>
        <ul>
          <li><a href="https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/guide/code-analyzer.html">Salesforce Code Analyzer</a></li>
          <li><a href="https://help.salesforce.com/s/articleView?id=platform.devops_center_overview.htm&type=5">DevOps Center</a></li>
        </ul>
      </td>
    </tr>
  </tbody>
</table>
