> [!NOTE]
> **Note:** If you interact with Cloud Storage via the XML API, consider using [XML API multipart uploads](https://docs.cloud.google.com/storage/docs/multipart-uploads) instead of parallel composite uploads: XML API multipart uploads support a greater number of parts than compose operations, have less potential for early deletion fees, and don't require `Delete` requests to remove the source parts once the final object is assembled.

One strategy for uploading large files is called *parallel composite uploads* .
In such an upload, a file is divided into up to 32 chunks,
the chunks are uploaded in parallel to temporary objects, the final object is
[recreated using the temporary objects](https://docs.cloud.google.com/storage/docs/composing-objects), and the temporary objects are
deleted.

Parallel composite uploads can be significantly faster if network and disk
speed are not limiting factors; however, the final object stored in your bucket
is a *composite object* , which only has a crc32c hash and not an [MD5 hash](https://docs.cloud.google.com/storage/docs/metadata#md5).
As a result, you must use crcmod to perform integrity checks when downloading
the object with Python applications. You should only perform parallel composite
uploads if the following apply:

- You don't need the uploaded objects to have an [MD5 hash](https://docs.cloud.google.com/storage/docs/metadata#md5).

- Any Python user, including [gsutil](https://docs.cloud.google.com/storage/docs/gsutil) users, who needs to download your
  objects has either google-crc32c or crcmod installed.

  For example, if you use Python to upload video assets that are only served
  by a Java application, parallel composite uploads are a good choice because
  there are efficient CRC32C implementations available in Java.

> [!WARNING]
> **Warning:** Parallel composite uploads involve deleting temporary objects. Keep in mind the following:
>
> - To minimize billing for temporary objects, hard delete the temporary objects during the composition process.
> - If you plan to delete the temporary objects after the composition process has finished, then use [Standard storage](https://docs.cloud.google.com/storage/docs/storage-classes#standard) for temporary objects to avoid the [early deletion fees](https://docs.cloud.google.com/storage/pricing) that are charged for other storage classes. After the final object is composed, you can change its storage class.
> - If your bucket has data protection features like [soft delete](https://docs.cloud.google.com/storage/docs/soft-delete) or [Object Versioning](https://docs.cloud.google.com/storage/docs/object-versioning) enabled, deleting temporary objects after the composition process has finished can increase your storage bill significantly. Consider disabling these protections on your bucket if you perform parallel composite uploads frequently. Alternatively, hard delete the temporary objects during the composition process.
> - You shouldn't use parallel composite uploads when uploading to a bucket that has a [retention policy](https://docs.cloud.google.com/storage/docs/bucket-lock), because the temporary objects can't be deleted until they meet the retention period.
> - If the bucket you upload to has [default object holds](https://docs.cloud.google.com/storage/docs/object-holds#default-holds) enabled, you must [release the hold](https://docs.cloud.google.com/storage/docs/holding-objects#set-object-hold) from each temporary object before you can delete it.

## How tools and APIs use parallel composite uploads

Depending on how you interact with Cloud Storage, parallel composite
uploads might be managed automatically on your behalf. This section describes
parallel composite upload behavior for different tools and provides information
for how you can modify the behavior.

### Console

The Google Cloud console does not perform parallel composite uploads.

### Command line

You can configure how and when [`gcloud storage cp`](https://docs.cloud.google.com/sdk/gcloud/reference/storage/cp) performs parallel
composite uploads by modifying the following properties:

- **`storage/parallel_composite_upload_enabled`** : Property for enabling
  parallel composite uploads. If `False`, disable parallel composite
  uploads. If `True` or `None`, perform parallel composite uploads for
  objects that meet the criteria defined in the other properties. The
  default setting is `None`.

- **`storage/parallel_composite_upload_compatibility_check`** : Property for
  toggling safety checks. If `True`, `gcloud storage` only performs parallel
  composite uploads when all of the following conditions are met:

  - The [storage class](https://docs.cloud.google.com/storage/docs/storage-classes) for the uploaded object is `STANDARD`.
  - The destination bucket does not have a [retention policy](https://docs.cloud.google.com/storage/docs/bucket-lock).
  - The destination bucket does not have [default object holds](https://docs.cloud.google.com/storage/docs/object-holds#default-holds) enabled.

  Note that in order to check these conditions, the gcloud CLI
  retrieves the metadata for the destination bucket as part of the upload
  command.

  If `False`, `gcloud storage` does not perform any checks. The default
  setting is `True`.
- **`storage/parallel_composite_upload_threshold`**: The minimum total file
  size for performing a parallel composite upload. The default setting is
  150 MiB.

- **`storage/parallel_composite_upload_component_size`**: The maximum size
  for each temporary object. The property is ignored if the total file size
  is so large that it would require more than 32 chunks
  at this size.

- **`storage/parallel_composite_upload_component_prefix`** : The prefix used
  when naming temporary objects. This property can be set either as an
  absolute path or as a path relative to the final object. See the
  [property description](https://docs.cloud.google.com/sdk/gcloud/reference/topic/configurations#parallel_composite_upload_component_prefix) for more information. The default prefix is the
  absolute path `/gcloud/tmp/parallel_composite_uploads/see_gcloud_storage_cp_help_for_details`.

You can modify these properties by creating a [named configuration](https://docs.cloud.google.com/sdk/gcloud/reference/topic/configurations) and
applying the configuration either on a per-command basis by using the
[`--configuration` project-wide flag](https://docs.cloud.google.com/sdk/gcloud/reference#--configuration) or for all gcloud CLI
commands by using the [`gcloud config set` command](https://docs.cloud.google.com/sdk/gcloud/reference/config/set).

No additional local disk space is required when using gcloud CLI
to perform parallel composite uploads. If a parallel composite upload fails
prior to composition, run the gcloud CLI command again to take
advantage of resumable uploads for the temporary objects that failed. Any
temporary objects that uploaded successfully before the failure do not get
re-uploaded when you resume the upload.

Temporary objects are named in the following fashion:

```
TEMPORARY_PREFIX/RANDOM_VALUE_HEX_DIGEST_COMPONENT_ID
```

Where:

- `TEMPORARY_PREFIX` is controlled by the `storage/parallel_composite_upload_component_prefix` property.
- `RANDOM_VALUE` is a random numerical value.
- `HEX_DIGEST` is a hash derived from the name of the source resource.
- `COMPONENT_ID` is the sequential number of the component.

Generally, temporary objects are deleted at the end of a parallel composite
upload, but to avoid leaving temporary objects around, you should check the
exit status from the gcloud CLI command, and you should manually
delete any temporary objects that were uploaded as part of any aborted
upload.

### Client libraries


### Java


For more information, see the
[Cloud Storage Java API
reference documentation](https://cloud.google.com/java/docs/reference/google-cloud-storage/latest/overview).


To authenticate to Cloud Storage, set up Application Default Credentials.
For more information, see

[Set up authentication for client libraries](https://docs.cloud.google.com/storage/docs/authentication#client-libs).

You can perform parallel composite uploads by setting `AllowParallelCompositeUpload` to `true`.
For example:

    import com.google.cloud.storage.transfermanager.https://docs.cloud.google.com/java/docs/reference/google-cloud-storage/latest/com.google.cloud.storage.transfermanager.ParallelUploadConfig.html;
    import com.google.cloud.storage.transfermanager.https://docs.cloud.google.com/java/docs/reference/google-cloud-storage/latest/com.google.cloud.storage.transfermanager.TransferManager.html;
    import com.google.cloud.storage.transfermanager.https://docs.cloud.google.com/java/docs/reference/google-cloud-storage/latest/com.google.cloud.storage.transfermanager.TransferManagerConfig.html;
    import com.google.cloud.storage.transfermanager.https://docs.cloud.google.com/java/docs/reference/google-cloud-storage/latest/com.google.cloud.storage.transfermanager.UploadResult.html;
    import java.io.IOException;
    import java.nio.file.Path;
    import java.util.List;

    class AllowParallelCompositeUpload {

      public static void parallelCompositeUploadAllowed(String bucketName, List<Path> files)
          throws IOException {
        https://docs.cloud.google.com/java/docs/reference/google-cloud-storage/latest/com.google.cloud.storage.transfermanager.TransferManager.html transferManager =
            https://docs.cloud.google.com/java/docs/reference/google-cloud-storage/latest/com.google.cloud.storage.transfermanager.TransferManagerConfig.html.newBuilder()
                .https://docs.cloud.google.com/java/docs/reference/google-cloud-storage/latest/com.google.cloud.storage.transfermanager.TransferManagerConfig.Builder.html#com_google_cloud_storage_transfermanager_TransferManagerConfig_Builder_setAllowParallelCompositeUpload_boolean_(true)
                .build()
                .https://docs.cloud.google.com/java/docs/reference/google-cloud-storage/latest/com.google.cloud.storage.transfermanager.TransferManagerConfig.html#com_google_cloud_storage_transfermanager_TransferManagerConfig_getService__();
        https://docs.cloud.google.com/java/docs/reference/google-cloud-storage/latest/com.google.cloud.storage.transfermanager.ParallelUploadConfig.html parallelUploadConfig =
            https://docs.cloud.google.com/java/docs/reference/google-cloud-storage/latest/com.google.cloud.storage.transfermanager.ParallelUploadConfig.html.newBuilder().setBucketName(bucketName).build();
        List<UploadResult> results =
            transferManager.https://docs.cloud.google.com/java/docs/reference/google-cloud-storage/latest/com.google.cloud.storage.transfermanager.TransferManager.html#com_google_cloud_storage_transfermanager_TransferManager_uploadFiles_java_util_List_java_nio_file_Path__com_google_cloud_storage_transfermanager_ParallelUploadConfig_(files, parallelUploadConfig).https://docs.cloud.google.com/java/docs/reference/google-cloud-storage/latest/com.google.cloud.storage.transfermanager.UploadJob.html#com_google_cloud_storage_transfermanager_UploadJob_getUploadResults__();
        for (https://docs.cloud.google.com/java/docs/reference/google-cloud-storage/latest/com.google.cloud.storage.transfermanager.UploadResult.html result : results) {
          System.out.println(
              "Upload for "
                  + result.getInput().getName()
                  + " completed with status "
                  + result.getStatus());
        }
      }
    }

### Node.js


For more information, see the
[Cloud Storage Node.js API
reference documentation](https://cloud.google.com/nodejs/docs/reference/storage/latest).


To authenticate to Cloud Storage, set up Application Default Credentials.
For more information, see

[Set up authentication for client libraries](https://docs.cloud.google.com/storage/docs/authentication#client-libs).

The Node.js client library does not support parallel composite uploads. Instead, use
[XML API multipart uploads](https://docs.cloud.google.com/storage/docs/multipart-uploads).

### Python


For more information, see the
[Cloud Storage Python API
reference documentation](https://cloud.google.com/python/docs/reference/storage/latest).


To authenticate to Cloud Storage, set up Application Default Credentials.
For more information, see

[Set up authentication for client libraries](https://docs.cloud.google.com/storage/docs/authentication#client-libs).

The Python client library does not support parallel composite uploads. Instead, use
[XML API multipart uploads](https://docs.cloud.google.com/storage/docs/multipart-uploads).

<br />

### REST APIs

### JSON API

The [JSON API](https://docs.cloud.google.com/storage/docs/json_api) supports uploading object chunks
in parallel and recombining them into a single object using the
[`compose` operation](https://docs.cloud.google.com/storage/docs/composing-objects).

Keep the following in mind when designing code for parallel composite
uploads:

- When using the `compose` operation, you can hard delete the source
  objects as part of the composition process.

  Use this option to minimize billing for temporary objects that don't
  need to be protected by soft delete or Object Versioning.

- In order to protect against changes to source objects between the upload
  and compose requests, you should provide an expected
  [generation number](https://docs.cloud.google.com/storage/docs/metadata#generation-number) for each source.

### XML API

The [XML API](https://docs.cloud.google.com/storage/docs/xml-api) supports uploading object chunks
in parallel and recombining them into a single object using the
[`compose` operation](https://docs.cloud.google.com/storage/docs/composing-objects).

Keep the following in mind when designing code for parallel composite
uploads:

- When using the `compose` operation, the source objects are unaffected
  by the composition process.

  This means that if they are meant to be temporary, you must explicitly
  [delete them](https://docs.cloud.google.com/storage/docs/deleting-objects) once you've successfully completed the composition, or
  else the source objects remain in your bucket and are billed
  accordingly.
- In order to protect against changes to source objects between the upload
  and compose requests, you should provide an expected
  [generation number](https://docs.cloud.google.com/storage/docs/metadata#generation-number) for each source.