Skip to main content

Multipart upload

Multipart upload lets you split a large object into parts, upload them in parallel (or out of order, with retries), and then assemble the final object server-side. Filebase's multipart implementation is wire-compatible with AWS S3 — every SDK and tool that knows how to do multipart upload against AWS works against Filebase.

When to use it

Object sizeRecommendation
Under 100 MBSingle PutObject is fine
100 MB – 5 GBUse multipart for parallelism and resumability
Over 5 GBRequired — single PutObject is capped at 5 GB
Over 1 TBAllowed up to 5 TB, but consider whether splitting at the application layer makes sense

The protocol

Three calls:

  1. CreateMultipartUpload — gives you an UploadId that ties the parts together.
  2. UploadPart — called once per part. Each part is 5 MiB to 5 GiB. The last part can be smaller. Up to 10,000 parts.
  3. CompleteMultipartUpload — assembles the parts in order and persists the final object.

If anything goes wrong, call AbortMultipartUpload to discard the upload and free the part storage.

High-level uploaders

You almost never write the three calls yourself — every modern AWS SDK has a high-level uploader that switches to multipart automatically.

AWS CLI

aws --endpoint https://s3.filebase.io s3 cp ./large-file.bin s3://my-bucket/

The CLI uses multipart automatically once the file exceeds 8 MB.

To tune the threshold or part size:

aws configure set default.s3.multipart_threshold 64MB
aws configure set default.s3.multipart_chunksize 64MB

AWS SDK for JavaScript v3

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

const s3 = new S3Client({
endpoint: 'https://s3.filebase.io',
region: 'auto',
credentials: { accessKeyId: KEY, secretAccessKey: SECRET },
});

const upload = new Upload({
client: s3,
params: {
Bucket: 'my-bucket',
Key: 'large-file.bin',
Body: createReadStream('./large-file.bin'),
},
partSize: 1024 * 1024 * 8, // 8 MB parts
queueSize: 4, // 4 concurrent parts
});

upload.on('httpUploadProgress', (p) => {
console.log(`${p.loaded} / ${p.total} bytes`);
});

await upload.done();

AWS SDK for Python (boto3)

s3.upload_file(
Filename='./large-file.bin',
Bucket='my-bucket',
Key='large-file.bin',
Config=boto3.s3.transfer.TransferConfig(
multipart_threshold=8 * 1024 * 1024,
multipart_chunksize=8 * 1024 * 1024,
max_concurrency=4,
),
)

AWS SDK for Go v2

import "github.com/aws/aws-sdk-go-v2/feature/s3/manager"

uploader := manager.NewUploader(client, func(u *manager.Uploader) {
u.PartSize = 8 * 1024 * 1024 // 8 MB
u.Concurrency = 4
})

f, _ := os.Open("./large-file.bin")
defer f.Close()

_, err := uploader.Upload(ctx, &s3.PutObjectInput{
Bucket: aws.String("my-bucket"),
Key: aws.String("large-file.bin"),
Body: f,
})

Low-level multipart, by hand

If you need fine-grained control (for example, uploading parts from disparate sources, or retrying in unusual ways), use the three-call protocol directly:

AWS SDK for JavaScript v3
import {
CreateMultipartUploadCommand,
UploadPartCommand,
CompleteMultipartUploadCommand,
AbortMultipartUploadCommand,
} from '@aws-sdk/client-s3';

// 1. Start the upload
const { UploadId } = await s3.send(
new CreateMultipartUploadCommand({
Bucket: 'my-bucket',
Key: 'large-file.bin',
ContentType: 'application/octet-stream',
}),
);

// 2. Upload each part (5 MB minimum, except the last)
const parts = [];
for (let partNumber = 1; partNumber <= totalParts; partNumber++) {
const body = readPart(partNumber);
const { ETag } = await s3.send(
new UploadPartCommand({
Bucket: 'my-bucket',
Key: 'large-file.bin',
UploadId,
PartNumber: partNumber,
Body: body,
}),
);
parts.push({ ETag, PartNumber: partNumber });
}

// 3. Finish
await s3.send(
new CompleteMultipartUploadCommand({
Bucket: 'my-bucket',
Key: 'large-file.bin',
UploadId,
MultipartUpload: { Parts: parts },
}),
);

// On error, abort to free part storage
// await s3.send(new AbortMultipartUploadCommand({ Bucket, Key, UploadId }));

Handling failures

If UploadPart fails, retry the same part with the same PartNumber and UploadId. Parts can be uploaded in any order — CompleteMultipartUpload reassembles them by part number.

If your process crashes mid-upload, Filebase keeps the parts around indefinitely. List in-progress uploads with ListMultipartUploads and either resume them or abort them with AbortMultipartUpload. Aborting frees the storage; not aborting and not completing leaves orphaned parts that count toward your storage quota.

Browser uploads with pre-signed URLs

For direct browser-to-Filebase multipart uploads, generate a pre-signed URL for each part. See browser uploads.

ETag for multipart objects

Multipart object ETags follow AWS's composite-hash format: <md5-of-md5s>-<part-count>. Tools that integrity-check by ETag (e.g., the AWS CLI when downloading) handle multipart ETags automatically.

What's next