この記事で分かること:
- Apply to each の「コンカレンシーの制御」が実際に効くケースと効かないケース
- 並列実行で逆に処理が詰まる3つの原因
- 大企業環境で実際に見た判断の目安と、設定手順
大企業で Power Automate のフロー設計を担当していて、「Apply to each を並列実行にしたら速くなると聞いたが、逆に遅くなった」という話を同僚から聞いたことがある。設定は確かに入っている。でも結果が期待と逆だった。
理由は「並列実行が速くなるかどうかは、ループ内の処理の中身による」という、シンプルだが見落としやすい点にある。この記事では、並列実行が有効なケースと逆効果になる3つのパターンを整理する。
Apply to each の「コンカレンシーの制御」とは
Power Automate(クラウドフロー)の Apply to each アクションには、デフォルトで「アイテムを逐次処理する」設定がある。これを変えるのが「コンカレンシーの制御」だ。
設定場所:Apply to each の右上「…」→「設定」→「コンカレンシーの制御」
- オフ(デフォルト):1件ずつ逐次処理
- オン:並列度を 1〜50 の範囲でスライダーで選ぶ
「並列にすれば速くなる」という印象を持ちやすいが、実際には中身によって効果が大きく変わる。また、コンカレンシーの制御をオンにした後でオフに戻すと、設定していたループ変数の初期化が変わる場合があるため、変更前後の動作確認が必要になることも覚えておきたい。
速くなる条件:ループ内が「待ち」主体のとき
並列実行が効果を発揮するのは、ループ内の処理の大半が「外部の応答を待っている時間」のケースだ。
典型的な処理の例:
- HTTP アクションで外部 API を呼ぶ(1件あたり 500ms〜2秒かかる)
- SharePoint や Dataverse から行を取得する
- メール送信(Exchange/Outlook コネクタ)
- LLM API を呼ぶ(Copilot Studio のエージェントとの連携含む)
こういった処理は、CPUの計算時間ではなくネットワーク往復の待ち時間が支配的だ。逐次実行では「A が終わるまで B は待つ」が積み重なるため、100件あれば処理時間も単純に長くなる。並列実行にすれば、同時に複数の「待ち」が走るので大幅に短縮できる可能性がある。
| 処理の中身 | 逐次実行 | 並列実行(度=10) |
|---|---|---|
| HTTP呼び出し 100件 × 各1秒 | 100秒以上 | 10秒前後になる場合がある |
| Dataverse 行取得 100件 | 遅い | 改善が見込める |
| SharePoint ファイル読み込み 100件 | 遅い | 改善が見込める |
| 軽い変数操作のみ 100件 | 速い | 効果はほぼ変わらない(後述の問題あり) |
改善幅は実際の環境・並列数・外部サービス側のレートリミットによって変わるため、実際に計測するまで断定できない点に注意したい。
逆効果になる3パターン
パターン1:アイテム間に依存関係がある
ループ内で「前のアイテムの結果を次の処理に使う」ロジックがあると、並列実行は壊れる。
よくある例:
- SharePoint リストの行を順番に読みながら、前の行の値と今の行の値を累積している
- 変数を Apply to each 内でインクリメントしている(
Increment variable) -
Append to array variableでリストを組み立てている
Power Automate の変数操作は並列実行と相性が悪い。複数のブランチが同時に同じ変数を更新しようとすると、値が不定になったり後から実行されたブランチが前の書き込みを上書きしたりする。実際に動いているように見えて、集計値がおかしくなるケースがある。
Microsoft の公式ドキュメントにも、コンカレンシーの制御を使う場合に変数への追記動作が変わることが記載されている(ループを制御する - Power Automate | Microsoft Learn)。
判断の目安:ループ内に Set variable / Increment variable / Append to array variable がある場合は、並列実行を入れる前に依存関係を確認する。依存関係があれば、その変数操作を Apply to each の外に出せないか設計を見直す方向を先に検討する。
パターン2:外部サービスのレートリミットに当たる
呼び出し先の API やサービスに、単位時間あたりのリクエスト数上限(レートリミット)がある場合、並列度を上げるとかえって 429 エラーが増えて再試行が発生し、全体の時間が延びることがある。
大企業環境で見かけるパターン:
- Graph API(SharePoint / Teams / Exchange):テナントレベルと接続ごとの両方にスロットリング制限がある。大量の Apply to each ループ内で Graph API を並列に呼ぶと、429 エラーが頻発することがある
- Dataverse:環境によっては1分あたりの呼び出し上限がある
- 外部の有償 API:プランによって秒間リクエスト数に上限がある
この場合、並列度を上げるほど再試行が増えて逆効果になる可能性がある。並列度を 3〜5 程度に抑えるか、逐次実行のままで各アクションに「再試行ポリシー」を設定する方が安定することがある。
判断の目安:Graph API を Apply to each 内で大量に呼ぶフローを並列化する場合は、まず少数件数(10〜20件)で並列度を変えながら実行ログを見て、再試行の回数を確認する。フロー実行詳細の各アクションに「再試行」が記録されていれば、並列度を下げる方向を検討する。
パターン3:並列実行後に全件の結果を集約する必要がある
並列実行で処理自体は速くなったが、「全件が終わった後で結果を1つにまとめる」処理を Apply to each の外側に置いている場合、集約のロジックが複雑になりやすい。
よくある設計:
- 並列で取得した複数のデータを配列に追加して、後で一括処理する
- Apply to each 内で条件分岐させて、条件を満たした行だけを別の配列に入れる
配列変数への追記(Append to array variable)はパターン1で述べた変数操作の問題と同様に、並列実行で順序や追記数に不整合が出ることがある。「100件処理したはずなのに配列の中身が80件しかない」という状況が起きやすい。
回避策の考え方:集約が必要な場合は、各アイテムの処理結果を個別にどこか(SharePoint リストの行、Dataverse の行)に書き出しておき、Apply to each が終わった後でまとめて読み直す構成にすると、並列化の恩恵を受けながら集約もできる。処理の途中状態をリストに持つことで、再実行した場合の回復も設計しやすくなる。
実際に設定するときの確認手順
並列実行を入れるか判断するときに確認していること:
ステップ1:ループ内のアクションを確認する
- HTTP / SharePoint Get item / Graph API を呼んでいる → 並列化の候補
-
Increment variable/Set variable/Append to array variableがある → 依存関係を確認してから
ステップ2:呼び出し先のレートリミットを確認する
- Graph API を使っている → Microsoft Graph throttling and limits を確認
- 外部サービス → APIドキュメントのrate limitセクションを確認
ステップ3:小さい並列度(3〜5)から試す
- いきなり50にしない
- フローの実行履歴で、各アクションに再試行が増えていないか確認する
ステップ4:フローの実行時間を比較する
- Power Automate の「実行履歴」には開始〜終了の時間が出る
- 変更前後で同じ件数のデータで比較するのが理想
- 実行時間が短くなっていても、エラー率が上がっていないかを合わせて確認する
コンカレンシー制御で変わる「スロットリングポリシー」との関係
もう一つ覚えておきたいのは、Power Automate のフローには「クラウドフローの実行時間の上限(クラウドフローは30分まで)」という制限がある。大量データのループを逐次実行していると、この時間制限に引っかかることがある。
並列実行で全体の実行時間を短縮することで、この時間制限の問題を回避しやすくなる、という使い方もある。ただしこの場合も、上で述べた3パターンの問題がなければ、という前提になる。
また、フロー自体の「コンカレンシーの制御」(トリガー側の設定:同じフローが複数同時に実行されるのを制限する)と、Apply to each 内のコンカレンシー制御は別の設定だ。ここを混同するケースがあるので注意が必要だ。
- トリガー側のコンカレンシー制御:同じフローが複数同時に起動されるのを制限する(例:スケジュールトリガーで同時実行数を1に制限する)
- Apply to each 内のコンカレンシー制御:ループ内のアイテムを並列に処理する
どちらの設定かを確認してから変更するようにすると、意図しない動作を避けやすい。
まとめ
- Apply to each の並列実行は「待ち時間が多い処理」では有効で、HTTPや外部API取得が代表例
- アイテム間に依存関係がある・変数を使った集計をしている・レートリミットがある場合は逆効果になる可能性がある
- 並列度はいきなり最大にせず、3〜5 から始めて実行履歴で確認するのが安全
- トリガー側のコンカレンシー制御と Apply to each 内の設定は別物
一番よくある「期待と逆になった」パターンは、変数のインクリメントが並列でおかしくなるケースだ。ループ内のロジックを一度シンプルな目線で確認してから並列化を検討すると、想定外の動作を避けやすい。
皆さんの現場では、Apply to each の並列化でうまくいったケース・うまくいかなかったケースはありましたか?
関連:Power Automateでレポート集計を自動化する時によくある落とし穴
この記事の内容で詰まったことや、自分の環境に応用したいケースはありますか?Copilot・AIエージェント構築の相談を受け付けています(ご連絡の際は「Qiitaを見た」とお書きください):https://coconala.com/services/4209036