Best practices and limitations

  • Optimize throughput by using fewer larger jobs and ordering operations by type and parent resource.

  • Avoid concurrency issues by minimizing operations on the same objects across concurrent jobs and within a single job.

  • Retrieve results efficiently by avoiding frequent polling and limiting results per page to 1,000.

  • Batch jobs support up to one million operations, with a limit of 100 active or pending jobs per account, and requests for adding operations have size and operation count limits.

Consider these guidelines when using BatchJobService.

Improve throughput

  • Fewer larger jobs are preferred over many smaller jobs.

  • Order uploaded operations by operation type (except for interdependent operations that must be grouped consecutively in atomic sub-batches). For example, if your job contains operations to add standard campaigns, ad groups, and ad group criteria, order the operations in your upload so that all of the campaign operations are first, followed by all of the ad group operations, and finally all ad group criterion operations.

  • Within operations of the same type, it can improve performance to group them by parent resource. For example, if you have a series of AdGroupCriterionOperation objects, it is more efficient to group operations by ad group rather than intermixing operations that affect ad group criteria in different ad groups.

Atomicity in batch splitting

The Google Ads API splits the operations in a submitted batch job into smaller sub-batches for processing. While standard sub-batches execute with partial failure enabled, sub-batches for certain interdependent operations are processed atomically as a single transaction:

For both AssetGroup and Performance Max Campaign creation sub-batches (up to 1,000 operations total per sub-batch; any child create operations beyond 999 spill into the next non-atomic sub-batch):

When an atomic sub-batch fails, the offending operation's BatchJobResult.status contains the underlying validation error, while the remaining operations in that sub-batch are rolled back with the corresponding transaction error for that sub-batch. Inspect the adjacent BatchJobResult entries sharing the same AdGroup, AssetGroup, or Campaign ID to identify the root-cause error.

If related operations in any of these groups are not added consecutively, the Google Ads API splits them across separate sub-batches, causing the modification to fail minimum asset requirements or leaving listing group trees incomplete. See Use listing group filters in batch jobs and Performance Max batch processing for details.

Logical grouping

When modifying a product targeting hierarchy (AssetGroupListingGroupFilterOperation in Performance Max campaigns or AdGroupCriterionOperation in Shopping campaigns) or creating a new AssetGroup or Performance Max Campaign, group all operations targeting the same parent resource (AssetGroup, AdGroup, or Campaign) consecutively. This reduces backend lock contention and keeps interdependent trees together.

Data consistency

Because listing group filter trees and Performance Max asset requirements are validated at the end of each atomic sub-batch transaction, avoid splitting updates to the same parent resource across discontinuous ranges in a job or across concurrent jobs.

Avoid concurrency issues

  • When submitting multiple concurrent jobs for the same account, reduce the likelihood of jobs operating on the same objects at the same time while maintaining large job sizes. Many unfinished jobs with the status of RUNNING that try to mutate the same set of objects can lead to deadlock-like conditions, resulting in severe slow-down and even job failures.

  • Don't submit multiple operations that mutate the same object in the same job, as the result can be unpredictable.

Retrieve results optimally

  • Don't poll the job status too frequently or you risk hitting rate limit errors.

  • Leave page_size unset (or set it to the maximum of 1000) when calling ListBatchJobResults to minimize pagination round trips, and only set response_content_type to MUTABLE_RESOURCE if your application inspects the returned resource fields beyond resource_name.

  • The results order is the same as the upload order.

Additional usage guidance

Limitations

Single mutate operation size

While the overall request can be up to 41,937,920 bytes, the serialized size of a single MutateOperation within the batch is capped at 10,484,504 bytes (10 MiB minus 1,256 bytes). Exceeding this limit returns a BatchJobError.REQUEST_TOO_LARGE error. Note that while the reference documentation for BatchJobError.REQUEST_TOO_LARGE cites the 10,484,504-byte threshold, AddBatchJobOperations returns this same error code when any of the three request thresholds (41,937,920 total request bytes, 10,484,504 single-operation bytes, or 10,000 operations per call) is exceeded, with the error's message field specifying which limit was violated.