Upload large objects with multipart upload

When and how to use multipart upload — the Upload helper in the AWS SDK for JavaScript v3, the CLI, the size and part limits (objects up to about 50 TB), the KMS permission multipart needs, and cleaning up incomplete uploads.

markdownguidev4Z4SQ-ZA0Vstage: buildtrust: officialservice: s3interface: sdkmultipart uploadlarge file uploadlib-storage UploadCreateMultipartUploadUploadPartCompleteMultipartUploadAbortMultipartUploadpart size10000 partsEntityTooLargeNoSuchUploadInvalidPart

Created 18 Oct 2026 · Modified 23 Oct 2026 · 4 versions

Use multipart upload from about 100 MB, and let the SDK's helper do it. It splits the file into parts uploaded in parallel and retried individually, then S3 assembles the object. Objects can now be up to 48.8 TiB (announced as 50 TB in December 2025, up from 5 TB).

Limits you must design around

ItemLimit
Parts per upload10,000
Part size5 MiB – 5 GiB (the last part may be smaller)
Largest object48.8 TiB

At 10,000 parts, the part size sets the largest file you can upload: 8 MiB parts reach about 78 GiB; for a 1 TiB file parts must be at least about 105 MiB. Pick the part size from the expected maximum file size, not from a default.

TypeScript: the Upload helper

import { S3Client } from "@aws-sdk/client-s3";
import { Upload } from "@aws-sdk/lib-storage";
import { createReadStream } from "node:fs";

const upload = new Upload({
  client: new S3Client({ region: "<bucket region>" }),
  params: { Bucket: "<bucket>", Key: "<key>", Body: createReadStream("./big.bin") },
  partSize: 64 * 1024 * 1024, // bytes; size for your largest file (see above)
  queueSize: 4,               // parts in flight
});
upload.on("httpUploadProgress", (p) => console.log(p.loaded, p.total));
await upload.done();

@aws-sdk/lib-storage works in Node.js and browsers and replaces SDK v2's upload(). AWS recommends the latest CRT-based transfer tooling for very large objects. partSize and queueSize were checked against the package's TypeScript types.

CLI

aws s3 cp ./big.bin s3://<bucket>/<key> switches to multipart automatically for large files (UNVERIFIED threshold). For explicit control: aws s3api create-multipart-upload, upload-part per part, complete-multipart-upload with the ordered part list, or abort-multipart-upload.

Permissions

s3:PutObject on the object ARN covers the multipart calls. On an SSE-KMS bucket, multipart needs kms:Decrypt as well as kms:GenerateDataKey: a role that can upload small files but fails on large ones is usually missing kms:Decrypt.

What it changes and costs

Uploaded parts are kept until the upload is completed or aborted, and are billed as storage until the upload is completed or aborted (the CreateMultipartUpload API documentation says so). An upload that is never completed leaves parts behind that do not appear as objects; abort failed uploads in code, and add a lifecycle rule that aborts incomplete multipart uploads after a few days (UNVERIFIED rule name in the collected sources: AbortIncompleteMultipartUpload). Completing the upload creates or replaces the object and emits s3:ObjectCreated:CompleteMultipartUpload, not s3:ObjectCreated:Put: an event notification that listens only for Put never fires for large uploads (patterns/s3-to-lambda.md).

Errors

CodeCause → fix
EntityTooLargeSingle-request upload above the limit: switch to multipart
EntityTooSmallA non-final part under 5 MiB: raise partSize
InvalidPartA listed part is missing or its ETag does not match: re-upload that part
InvalidPartOrderComplete request lists parts out of order: sort by part number
NoSuchUploadThe upload ID was already completed or aborted, or is wrong
InvalidRequestIncludes CopyObject on an object over 5 GB: use multipart copy (UploadPartCopy)
403 on large files onlykms:Decrypt missing (above)

Read this document as markdown — the same bytes an agent receives.