This chapter covers S3 pre-signed URLs and multipart upload, two critical mechanisms for secure, scalable data transfer in AWS. For the DVA-C02 exam, these topics appear in roughly 8-12% of questions, often in scenarios involving temporary access, large file uploads, or cross-account sharing. Mastering pre-signed URLs and multipart upload will help you answer questions about security, performance, and cost optimization. The exam tests your ability to choose the right approach for granting time-limited access and handling large objects efficiently.
Jump to a section
Imagine you own a secure parking garage (your S3 bucket). You want to allow a friend to pick up a package from your car, but you can't be there. You issue a valet parking ticket (pre-signed URL) that grants access for a specific car (object) for a limited time. The ticket includes: your garage's address (bucket endpoint), which car (object key), and an expiration time. Your friend presents the ticket to the garage attendant (S3 endpoint). The attendant checks the ticket's validity: is it signed with your secret key? Is it within the time window? If valid, the attendant retrieves the package and hands it over. The ticket only works for that specific car and expires after the time you set. You cannot revoke a ticket once issued; you can only wait for it to expire. If your friend loses the ticket, anyone who finds it can use it until it expires. For large packages (multipart upload), you can issue multiple tickets for each part, allowing your friend to upload a huge item in pieces, each with its own time-limited permission. This is exactly how pre-signed URLs work: they delegate temporary, scoped access without sharing permanent credentials.
What Are Pre-Signed URLs and Why Do They Exist?
A pre-signed URL is a URL that grants temporary access to a specific S3 object for a specific operation (GET, PUT, DELETE, etc.). It is generated using the requester's AWS credentials (access key and secret key) to sign the URL. Anyone with the URL can perform the operation within the expiration window, without needing AWS credentials. This solves the problem of granting granular, time-limited access without sharing long-term keys.
Pre-signed URLs are commonly used for:
Allowing users to upload files directly to S3 without exposing AWS credentials.
Sharing private objects with a limited audience for a limited time.
Enabling serverless applications (e.g., Lambda, API Gateway) to generate URLs for clients.
How Pre-Signed URLs Work Internally
A pre-signed URL is constructed by appending query parameters to the standard S3 REST API endpoint. The signature is computed using HMAC-SHA256 with the secret access key. The URL includes:
Bucket and object key
AWS access key ID
Expiration timestamp (epoch time)
Signature (hex-encoded HMAC)
Optional: HTTP method, content-type, content-md5, and other headers you want to enforce.
When a client uses the URL, S3 recalculates the signature using the same algorithm and checks it against the provided signature. If they match and the expiration time has not passed, the request is allowed.
Important: The signature is tied to the HTTP method. A GET pre-signed URL cannot be used for PUT. The URL must be generated with the exact method you intend to permit.
Key Components, Defaults, and Timers
Expiration: You set the expiration time in seconds from generation. Maximum is typically 7 days (604800 seconds) when using IAM user credentials. For IAM roles (temporary credentials), the maximum is the role's session duration (usually 1 hour).
Signature version: S3 supports Signature Version 4 (SigV4) and Signature Version 2 (deprecated). AWS SDKs use SigV4 by default.
HTTP Method: Required when generating the URL. Common methods: GET, PUT, DELETE, HEAD.
Headers: You can include headers like Content-Type and Content-MD5 in the signature to enforce them. If a client omits or changes them, the request fails.
Bucket policies: Pre-signed URLs do not bypass bucket policies. The URL grants permission only if the underlying IAM user/role has the necessary permissions (e.g., s3:GetObject). However, a bucket policy can explicitly deny access even with a valid pre-signed URL.
Configuration and Verification
To generate a pre-signed URL using the AWS CLI:
aws s3 presign s3://my-bucket/my-object --expires-in 3600This outputs a URL valid for 1 hour. To generate for PUT (upload):
aws s3 presign s3://my-bucket/my-object --expires-in 3600 --method PUTUsing Python SDK (boto3):
import boto3
from botocore.config import Config
s3 = boto3.client('s3', config=Config(signature_version='s3v4'))
url = s3.generate_presigned_url(
ClientMethod='get_object',
Params={'Bucket': 'my-bucket', 'Key': 'my-object'},
ExpiresIn=3600
)Verifying a pre-signed URL: You can test it with curl:
curl -v "<pre-signed-url>"If the URL is expired or malformed, S3 returns a 403 Forbidden with an error like "SignatureDoesNotMatch" or "AccessDenied".
Interaction with Related Technologies
CloudFront Signed URLs vs Pre-Signed URLs: CloudFront signed URLs control access at the CDN edge and can have additional conditions (IP, date). Pre-signed URLs are for direct S3 access.
AWS Lambda: Often used to generate pre-signed URLs on demand. Lambda needs IAM permissions to generate the URL (i.e., s3:GetObject for the target object).
API Gateway: Can return pre-signed URLs from REST APIs, enabling serverless file uploads.
IAM Roles: When using temporary credentials from STS, the maximum expiration is limited by the role's session duration (default 1 hour, max 12 hours if configured).
Multipart Upload: What It Is and Why It Exists
Multipart upload allows you to upload a single object as a set of parts. It is designed for large objects (recommended for objects > 100 MB, required for objects > 5 GB). Benefits:
Parallel upload of parts improves throughput.
Pause and resume uploads.
Begin upload before you know the total object size.
Upload parts in any order and assemble later.
How Multipart Upload Works Internally
The process has three phases:
1. Initiation: You call CreateMultipartUpload which returns an upload ID.
2. Part upload: You upload each part using UploadPart, specifying the upload ID and part number (1 to 10,000). Each part must be at least 5 MB (except the last part). You receive an ETag for each part.
3. Completion: You call CompleteMultipartUpload with the list of part numbers and ETags. S3 assembles the parts in order.
Alternatively, you can abort the upload with AbortMultipartUpload, which deletes all uploaded parts.
Key Components and Defaults
Part size: Minimum 5 MB per part (except last). No maximum part size, but total object max is 5 TB.
Maximum parts: 10,000.
Upload ID: Unique identifier for the multipart upload. Required for all subsequent operations.
ETag: Each part returns an ETag (usually MD5 hash of the part, but not guaranteed for multipart). You must track these for completion.
Abort lifecycle: You can configure lifecycle rules to automatically abort incomplete multipart uploads after a specified number of days (cost savings).
Configuration and Verification
Using AWS CLI to perform multipart upload:
# Initiate
aws s3api create-multipart-upload --bucket my-bucket --key largefile.iso
# Upload part
aws s3api upload-part --bucket my-bucket --key largefile.iso --part-number 1 --body part1 --upload-id <upload-id>
# Complete
aws s3api complete-multipart-upload --bucket my-bucket --key largefile.iso --upload-id <upload-id> --multipart-upload file://parts.jsonUsing boto3:
import boto3
s3 = boto3.client('s3')
response = s3.create_multipart_upload(Bucket='my-bucket', Key='largefile.iso')
upload_id = response['UploadId']
# Upload part
with open('part1', 'rb') as f:
response = s3.upload_part(Bucket='my-bucket', Key='largefile.iso', PartNumber=1, UploadId=upload_id, Body=f)
etag1 = response['ETag']
# Complete
s3.complete_multipart_upload(
Bucket='my-bucket',
Key='largefile.iso',
UploadId=upload_id,
MultipartUpload={'Parts': [{'ETag': etag1, 'PartNumber': 1}]}
)Verification: Use aws s3api list-parts to see uploaded parts, or aws s3api list-multipart-uploads to see in-progress uploads.
Combining Pre-Signed URLs with Multipart Upload
You can generate pre-signed URLs for each part of a multipart upload. This allows a client to upload large files directly to S3 without credentials. Steps:
1. Server initiates a multipart upload (using AWS credentials) and gets an upload ID.
2. Server generates pre-signed URLs for each part using generate_presigned_url with method upload_part.
3. Client uploads each part directly to S3 using the pre-signed URLs.
4. After all parts are uploaded, server completes the multipart upload.
This pattern is common in serverless file upload applications where the client cannot hold AWS credentials.
Interaction with Related Technologies
S3 Transfer Acceleration: Can be used with multipart upload for faster uploads over long distances.
S3 Lifecycle: Can abort incomplete multipart uploads after a set number of days.
S3 Event Notifications: Can trigger Lambda on completion of multipart upload (via s3:ObjectCreated:* event).
CloudFront: Can serve objects uploaded via multipart upload, but note that multipart uploads are not supported for streaming uploads via CloudFront.
Exam Critical Details
Pre-signed URLs are generated with the signer's credentials; the signer must have permissions to perform the operation.
You cannot revoke a pre-signed URL before expiration unless you rotate the signer's keys (which invalidates all URLs signed with those keys).
For multipart upload, the minimum part size is 5 MB (except last part). The exam may test this as a constraint.
Multipart upload is required for objects > 5 GB; recommended for > 100 MB.
Pre-signed URLs for upload_part require the upload ID in the parameters.
The AWS SDK's generate_presigned_url for upload_part requires UploadId in Params.
Common Pitfalls
Using pre-signed URLs with expired credentials: The URL becomes invalid immediately if the signing credentials expire (e.g., temporary credentials from STS).
Forgetting to include required headers in the signature: If you sign with Content-Type, the client must send that exact header.
Multipart upload part numbers must be contiguous? No, they can be any order, but S3 assembles them in numeric order.
Pre-signed URLs are not compatible with bucket policies that use aws:SourceIp condition unless the URL includes the IP condition (which it doesn't by default).
Advanced: Using Pre-Signed URLs with Custom Conditions
You can use generate_presigned_post (boto3) to create a pre-signed POST form that enforces additional conditions like content-length range, success redirect, and metadata. This is used for browser-based uploads.
Example:
s3 = boto3.client('s3')
conditions = [
["content-length-range", 0, 10485760], # 10 MB max
{"acl": "public-read"}
]
fields = {
"acl": "public-read"
}
response = s3.generate_presigned_post(
Bucket='my-bucket',
Key='${filename}',
Conditions=conditions,
Fields=fields,
ExpiresIn=3600
)This returns a URL and form fields that the client can use to upload via HTML form.
Summary of Key Numbers
Pre-signed URL max expiration: 7 days (IAM user), role session duration (temporary credentials).
Multipart upload part size minimum: 5 MB (except last).
Multipart upload maximum parts: 10,000.
Maximum object size: 5 TB.
Multipart upload recommended for > 100 MB, required for > 5 GB.
Initiate Multipart Upload
The server calls CreateMultipartUpload on the S3 API, specifying the bucket, key, and optionally storage class, ACL, etc. S3 returns a unique UploadId, which is a string like 'abc123...'. This UploadId identifies the entire upload session and is required for all subsequent part uploads, completions, and aborts. The server must store this ID securely, often in a database or in-memory cache, as the client will need it indirectly via pre-signed URLs.
Generate Pre-Signed URLs for Parts
The server generates a pre-signed URL for each part using the AWS SDK. For each part, the server calls generate_presigned_url with ClientMethod='upload_part' and Params including Bucket, Key, PartNumber, and UploadId. The server sets an expiration time (e.g., 1 hour). The resulting URL is a temporary, signed endpoint that allows the client to upload that specific part. The server sends these URLs to the client (e.g., via API response).
Client Uploads Parts in Parallel
The client receives the list of pre-signed URLs and uploads each part directly to S3 using HTTP PUT requests. The client can upload parts in any order and in parallel to maximize throughput. Each part must be at least 5 MB (except the last part). S3 validates the signature and expiration on each request. Upon successful upload, S3 returns an ETag (usually the MD5 hash of the part) in the response header. The client must track these ETags along with part numbers.
Client Signals Completion
After the client has uploaded all parts, it sends a request to the server (or directly to S3 if the server provides a completion URL) indicating that all parts are ready. Ideally, the client sends the list of part numbers and ETags back to the server. The server then calls CompleteMultipartUpload with the UploadId and the list of parts (sorted by part number). S3 assembles the parts in order and creates the final object. If any part is missing, the completion fails.
Server Completes or Aborts Upload
The server calls CompleteMultipartUpload with the UploadId and the list of parts (ETags and part numbers). S3 verifies that all parts are present and that the ETags match. If successful, S3 returns the final object's ETag (not simply the MD5 of the whole object). If the upload fails (e.g., network issue during part upload), the server can call AbortMultipartUpload to delete all uploaded parts and free storage. The server should also have a cleanup mechanism for abandoned uploads.
Enterprise Scenario 1: Secure File Sharing for a Healthcare Platform
A healthcare SaaS platform allows doctors to upload patient MRI scans (often 200-500 MB) to S3 for analysis. The platform cannot expose AWS credentials to the browser. Solution: The backend (Node.js on Elastic Beanstalk) generates a pre-signed URL for each upload using a Lambda function. For large files, the backend initiates a multipart upload and generates pre-signed URLs for each part (e.g., 10 parts of 50 MB). The frontend JavaScript uses these URLs to upload parts in parallel using the browser's Fetch API. The backend completes the upload after receiving success callbacks. Common issue: If the pre-signed URL expires before all parts are uploaded (e.g., slow connection), the upload fails. Mitigation: Set expiration based on estimated upload time (e.g., 24 hours) and monitor progress. Also, implement a retry mechanism for failed parts.
Enterprise Scenario 2: Video Processing Pipeline
A media company ingests user-submitted videos (up to 2 GB) for transcoding. Users upload via a web form. The backend creates a pre-signed POST form that enforces a maximum file size of 2 GB and requires a specific content type. After upload, an S3 event triggers Lambda to start a transcoding job (Elastic Transcoder or MediaConvert). For very large videos, the backend uses multipart upload with pre-signed URLs. The client is a mobile app that uploads parts sequentially to avoid memory issues. The backend tracks progress in DynamoDB. Performance consideration: Use S3 Transfer Acceleration for uploads from distant regions. Misconfiguration: Not setting a lifecycle policy to abort incomplete multipart uploads can lead to orphaned parts accumulating storage costs. Best practice: Set lifecycle rule to abort multipart uploads after 7 days.
Enterprise Scenario 3: Cross-Account Data Sharing
A financial analytics firm needs to share daily reports (CSV files) with partner companies. They generate pre-signed URLs for each report and email them to partners. The URLs expire after 24 hours. To avoid regenerating URLs for each partner, they use a single pre-signed URL that is unique per object. However, they must ensure that the bucket policy does not override the pre-signed URL permissions. They also implement CloudTrail logging to audit access. Common mistake: Sharing pre-signed URLs via unencrypted email, which exposes the URL. Mitigation: Use a secure portal where partners log in to retrieve URLs. Also, note that pre-signed URLs cannot be restricted to specific IPs unless using CloudFront signed URLs with IP restrictions.
Exactly What DVA-C02 Tests
The exam objectives under Domain 1 (Development) Objective 1.4: "Implement application security" include pre-signed URLs and multipart upload. Specifically, you must know:
How to generate pre-signed URLs for different operations (GET, PUT).
The relationship between pre-signed URL expiration and the signer's credential type.
Multipart upload lifecycle: initiate, upload part, complete, abort.
Minimum part size (5 MB) and maximum parts (10,000).
When to use multipart upload (objects > 100 MB recommended, > 5 GB required).
How to combine pre-signed URLs with multipart upload for client-side uploads.
Common Wrong Answers and Why Candidates Choose Them
"Pre-signed URLs can be revoked" — Candidates think they can invalidate a URL by deleting the object or changing permissions. Reality: The only way is to wait for expiration or rotate the signer's keys (which invalidates all URLs). Deleting the object makes the URL return 404, but the URL itself is still valid (it points to a non-existent object). The exam may present a scenario where a security breach requires immediate revocation; the correct answer is to invalidate the credentials used to sign (rotate keys).
"Multipart upload requires parts to be uploaded in order" — Candidates assume sequential upload. Reality: Parts can be uploaded in any order; S3 assembles them by part number at completion.
"Pre-signed URLs work across all AWS services" — They only work for S3 (and some other services like CloudWatch Logs via similar mechanisms). The exam may distract with options like DynamoDB or Lambda.
"Pre-signed URL expiration can be set to any time up to 7 days regardless of credentials" — If the signer uses temporary credentials (STS), the max expiration is the role's session duration (usually 1 hour). The exam tests this distinction.
Specific Numbers and Terms
7 days (604800 seconds) for IAM user-signed URLs.
5 MB minimum part size (except last part).
10,000 maximum parts.
5 TB maximum object size.
UploadId — must be included in pre-signed URL for upload_part.
ETag — returned for each part; required for completion.
Signature Version 4 — default signing algorithm.
Edge Cases and Exceptions
Pre-signed URLs generated with temporary credentials (e.g., from Lambda execution role) expire when the credentials expire, which may be shorter than the requested expiration. The SDK limits the expiration to the remaining credential lifetime.
If a bucket policy denies access (explicit deny), the pre-signed URL is ineffective.
Pre-signed URLs do not support aws:SourceIp condition unless the condition is embedded in the signature (which is not standard). Use CloudFront signed URLs for IP restrictions.
Multipart upload parts can be uploaded with different storage classes, but the final object's storage class is determined by the initiate call.
How to Eliminate Wrong Answers
If the question involves revoking access immediately, look for answers involving key rotation or bucket policy deny (but note that bucket policy deny works for future requests, not for already-issued URLs). The only immediate revocation is to invalidate the signing key.
If the question is about uploading large files from a browser, the correct answer is to generate pre-signed URLs for multipart upload parts.
If the question mentions "temporary credentials" and pre-signed URL expiration, remember that the max expiration is the credential lifetime, not 7 days.
Pre-signed URLs grant temporary, scoped access to S3 objects without sharing permanent credentials.
Maximum expiration for pre-signed URLs signed by IAM users is 7 days; for temporary credentials (STS), it's the role session duration.
Multipart upload allows parallel uploads of large objects; minimum part size is 5 MB (except last part), max 10,000 parts.
Multipart upload is required for objects > 5 GB and recommended for objects > 100 MB.
To upload large files from a client, combine multipart upload with pre-signed URLs for each part.
You cannot revoke a pre-signed URL before expiration; rotate the signing key to invalidate all URLs signed with that key.
Pre-signed URLs are tied to a specific HTTP method; a GET URL cannot be used for PUT.
Multipart upload parts can be uploaded in any order; S3 assembles them at completion by part number.
These come up on the exam all the time. Here's how to tell them apart.
Pre-Signed URLs (S3)
Direct access to S3 objects via S3 endpoint.
Expiration max 7 days for IAM users; tied to credential lifetime for temporary credentials.
Cannot restrict by IP address or other conditions (except via bucket policy).
Generated using IAM user or role credentials.
Suitable for direct uploads/downloads without CDN.
CloudFront Signed URLs
Access via CloudFront edge locations (cached).
Expiration can be set to any date (no 7-day limit).
Can restrict by IP, date, and other conditions via custom policy.
Generated using CloudFront key pairs (private/public).
Provides DDoS protection and lower latency via edge caching.
Mistake
Pre-signed URLs can be revoked by deleting the object.
Correct
Deleting the object makes the URL return 404, but the URL itself is still valid (it just points to nothing). The only way to revoke a pre-signed URL before expiration is to rotate the signing key, which invalidates all URLs signed with that key.
Mistake
Multipart upload parts must be uploaded in sequential order.
Correct
Parts can be uploaded in any order. S3 assembles them by part number when you call CompleteMultipartUpload. However, the part numbers must be between 1 and 10,000.
Mistake
Pre-signed URLs can grant access to any S3 operation.
Correct
Pre-signed URLs are tied to a specific HTTP method (GET, PUT, DELETE, HEAD). A GET URL cannot be used for PUT. Also, the signer must have IAM permissions for that operation.
Mistake
A pre-signed URL can be used by anyone, even if they don't have AWS credentials.
Correct
That is true — no credentials are needed to use the URL. But the URL itself is generated using credentials, and the signer must have the appropriate permissions.
Mistake
Multipart upload is only for objects larger than 5 GB.
Correct
Multipart upload is recommended for objects over 100 MB and required for objects over 5 GB. You can use it for smaller objects, but it adds overhead.
Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.
No, a single PUT request is limited to 5 GB. For objects larger than 5 GB, you must use multipart upload. You can generate pre-signed URLs for each part of a multipart upload, allowing the client to upload parts individually. The client must then signal completion so the server can call CompleteMultipartUpload.
If signed by an IAM user, the maximum expiration is 7 days (604800 seconds). If signed by temporary credentials (e.g., from an IAM role or STS), the maximum expiration is the remaining lifetime of those credentials, typically 1 hour for roles (up to 12 hours if configured). The SDK will limit the expiration to the credential's expiration.
You cannot revoke a specific pre-signed URL. The only way to invalidate all pre-signed URLs signed with a particular set of credentials is to rotate those credentials (e.g., change the IAM user's access key). Deleting the object will cause the URL to return a 404 error, but the URL itself is still valid (it just points to nothing).
The URL is still valid. When someone uses it, S3 will return a 404 Not Found error because the object doesn't exist. The pre-signed URL grants permission to perform the operation; it does not guarantee the object exists.
No, pre-signed URLs are for object-level operations only (GET, PUT, DELETE, HEAD). To list objects, you need to use the ListObjects API, which cannot be pre-signed. You would need to use a different mechanism, such as a bucket policy or IAM credentials.
Not required, but if you sign the URL with a specific Content-Type, the client must send that exact Content-Type header in the request. If the header is missing or different, S3 returns a SignatureDoesNotMatch error.
You can use the ListParts API to see which parts have been uploaded for a given UploadId. You can also use Amazon S3 Event Notifications to trigger events on completion (s3:ObjectCreated:*). For real-time progress, the client must report back to your application.
You've just covered S3 Pre-Signed URLs and Multipart Upload — now see how well it sticks with free DVA-C02 practice questions. Full explanations included, no account needed.
Done with this chapter?