2026-08-05
Salesforceのガバナ制限は本当に諸悪の根源なのか
はじめに
先日、Salesforceのカスタムオブジェクト一括登録処理で3種類のガバナ制限に連続で引っかかった話を書きました。同期SOQLの上限、enqueueJobの上限、非同期SOQLの上限と、修正するたびに次の壁が出てくる展開で、正直なところ開発中は「なんでこんなに制約だらけなんだ」と何度も思いました。
ガバナ制限は、Salesforce開発者の間で諸悪の根源のように語られることがあります。他の言語やプラットフォームなら気にしなくていい上限を、常に頭の片隅に置いて設計しなければいけないからです。ただ振り返ってみると、諸悪の根源というよりは、設計の粗を早めに教えてくれる早期警告装置に近かったと思っています。この記事では、あの一件を振り返りながらその理由を説明します。
制約が可視化してくれたもの
振り返ると、ガバナ制限に引っかかった箇所はどれも制限そのものが問題だったのではなく、制限が炙り出した設計の粗が問題だったケースでした。具体的に何につまずいてどう直したかは前の記事にまとめているので、ここでは一般化した形で3つのパターンを挙げます。
ループの中で問い合わせを発行する
// 件数が増えるほど問い合わせ回数も増える
for (Id recordId : recordIds) {
Account acc = [SELECT Id, Name FROM Account WHERE Id = :recordId];
// ...
}
// 事前にまとめて取得しておけば、件数によらず問い合わせは1回で済む
Map<Id, Account> accounts = new Map<Id, Account>(
[SELECT Id, Name FROM Account WHERE Id IN :recordIds]
);
for (Id recordId : recordIds) {
Account acc = accounts.get(recordId);
// ...
}
件数が少ないうちは前者でも動いてしまうため、レビューでも見逃されやすいミスです。
まとめて処理できるものを1件ずつ非同期ジョブに積む
// 1件ごとにジョブを積む — 件数が増えるほどジョブ数も増える
for (Id recordId : recordIds) {
System.enqueueJob(new MyAsyncJob(recordId));
}
// 複数件をまとめて1つのジョブに渡す
System.enqueueJob(new MyAsyncJob(recordIds));
まとめられるものを1件ずつ処理する設計は、ジョブ数の上限にも早く到達しますし、単純に無駄なオーバーヘッドも積み重なります。
非同期処理1回あたりのコストを見積もらない
非同期ジョブの中でさらに問い合わせを発行する場合、コストは1回のジョブで処理する件数と1件あたりの問い合わせ回数の掛け算で決まります。
まとめる件数を増やせば1回あたりの処理は効率化しますが、増やしすぎると今度はこの掛け算が上限を超えます。まとめるほど効率的という発想だけで件数を決めると、この掛け算を見落としがちです。
ガバナ制限がなければ、こうした設計ミスはどれもエラーにならず本番のスケールでだけ静かに遅くなるコードとして残っていたはずです。処理件数が少ないテスト環境では気づかず、本番で件数が増えて初めて重くなる、あるいはタイムアウトする。原因の特定はガバナ制限に引っかかるより遥かに厄介だったと思います。
それでも面倒なものは面倒
だからといって、ガバナ制限が快適だとは言いません。複数の制限が同時に絡む設計では、常にそれらを逆算しながらコードを書く必要があります。実際、複数の制限を同時に満たす範囲を計算する場面もありましたが、これは他の言語なら発生しない種類の手間です。設計を変更するたびに「この変更でどのガバナ制限に影響するか」を都度考え直す必要があり、この負担は今後も減らない気がします。
諸悪の根源ではなく、早期警告装置
それでも振り返ると、ガバナ制限は設計の粗を、本番で顕在化する前にエラーとして教えてくれる仕組みだったと思います。制限に引っかかるのは煩わしいですが、そのおかげで件数が増えたら遅くなるという質の悪いバグを、テストの時点で強制的に発見させられました。制限がない環境なら同じ設計ミスをしても気づかないまま本番に出ていたはずで、その場合の調査コストの方がよほど大きかったはずです。
諸悪の根源というより、設計の甘さを早めに突きつけてくる、口うるさいレビュアーに近いというのが、今の実感です。面倒なことに変わりはありませんが、面倒さの矛先は制限そのものではなく、制限がなければ見過ごしていた自分の設計の方にあったのだと思います。