Every PDF export went nginx → app → S3 → app → client. Compute bill climbs, timeouts multiply. Presigned URL 15 min: client pulls direct from bucket. CPU drops, but URL lands in Slack.
Presigned = temporary HMAC capability. Powerful, sensitive.
When to use
Large downloads/uploads, mobile, temp partners. Avoid homegrown streaming proxy.
Not long session auth — use app IAM role.
Secure generation
Backend minimal s3:GetObject on user prefix. Never root keys. Short expiry.
Optional Content-Disposition, SSE-KMS.
Browser direct upload
Backend presigned PUT → client upload → validate etag/size → tag clean.
Limit size via content-length-range.
Risks
Shared URL, enumeration, replay upload — table mitigations TTL, UUID keys, checksum scan, strict prefix IAM.
Observability
Log URL generation. Alert volume anomaly. CloudTrail if budget.
URL security
Minimal business TTL. UUID object key. Strict IAM prefix. Log generation. Revocation = rotate IAM + remaining URLs die by short expiry anyway.
Do not log signed query string plaintext in public access logs.
Leak test: shared expired URL must 403.
UX patterns
Download: presigned GET 5–15 min. Large upload: multipart presigned + client progress.
Do not presign list bucket — single object scope.
Audit: who generated URL for which userId — trace abuse.
Mobile apps embedding presigned in deep links: expiry must match UX session — deep link replay risk.
Multipart upload presigned: abort incomplete MPU lifecycle saves inode and cost.
Compliance
Presigned URL PII export: access log + short expiry + audit who requested GDPR export.
Do not send presigned via unencrypted SMS — even short TTL, interception risk.
IAM key rotation tied to app layer presigned secret rotation.
Operational summary
Presigned delegates bandwidth and temporary access — minimal IAM, short TTL, UUID keys, generation audit. Bucket CORS distinct from API CORS.
URL leak = data leak until expiry — secret rotation if serious.
Architecture decision record
When presigned vs app proxy vs CDN signed cookies — document latency, egress cost, audit, mobile UX tradeoff. Review ADR annually or if download traffic 2x.
Mobile deep links
Presigned URLs in mobile deep links outlive user session mentally — TTL must match UX copy « link expires in 15 minutes » literally.
Revoke by object delete if URL leaked — presigned still valid until expiry even after « disable user ».
Security review
Quarterly audit presigned generation logs: who, which object class, TTL distribution. Anomaly: TTL suddenly max — investigate compromised admin script.
Content-Disposition attachment on presigned download reduces XSS open in browser tab risk for user uploads.
IAM policy condition aws:SecureTransport true on bucket — presigned HTTPS only.
Operational follow-up
Quarterly IAM presigned scope review — permission creep. Average TTL audit from logs. Pen test presigned URL signature tamper — must fail closed. Document gaps between host marketing and field measurement in the quarterly review.
Quarterly follow-up
Quarterly IAM presigned scope review — permission creep. Average TTL audit from logs. Pen test presigned URL signature tamper — must fail closed. Document gaps between host marketing and field measurement in the quarterly review.
Clock skew on signing server invalidates presigned URLs — keep app servers on NTP.
Keep a dated runbook, before/after metrics, post-incident review — cumulative discipline beats Friday night panic.
Keep a dated runbook, before/after metrics, post-incident review — cumulative discipline beats Friday night panic.
Keep a dated runbook, before/after metrics, post-incident review — cumulative discipline beats Friday night panic.
Keep a dated runbook, before/after metrics, post-incident review — cumulative discipline beats Friday night panic.
Keep a dated runbook, before/after metrics, post-incident review — cumulative discipline beats Friday night panic.
Keep a dated runbook, before/after metrics, post-incident review — cumulative discipline beats Friday night panic.
Presigned ADR
vs proxy vs CDN cookies. TTL = literal UX copy. IAM rotate revocation.
Deep dive s3-presigned-urls
Keep before/after metrics for each change, the last successful drill date, and documented gaps between host marketing and field measurement. A quarterly review with business teams avoids repeating the same mistakes. To compare infrastructure and read more field notes, browse our directory, comparison tool, and technical blog guides.:::note Key takeaway. Presigned delegates bandwidth; minimal IAM + short TTL + unguessable object keys. :::
Decide and move forward without blind spots
- Minimal IAM on prefix —
s3:GetObjector Put limited touser/{id}/, never root keys. - Minimal business TTL — minutes to hours; UX copy « link expires in 15 min » literal.
- UUID object keys — no sequential enumeration; log generation without plaintext signed query.
- PUT upload flow — backend validates etag/size, async scan, clean tag.
- Annual ADR — presigned vs app proxy vs CDN signed cookies by egress and audit.
Object storage and egress: comparison tool, directory, guides.
Frequently asked questions
Presigned GET vs PUT?
GET = temporary client download. PUT = direct browser upload to bucket without your server.
Recommended max duration?
Minutes to hours for user download. Upload session: cover session + margin, not days without rotation.
Leaked URL = leaked data?
Yes until expiry. Limit object scope, Content-Type, checksum; rotate IAM keys if serious leak.
CDN alternative?
CloudFront signed cookies for cacheable public content; presigned S3 for private one-off access.
Shorten TTL before optimizing chunk size — leakage costs more than latency.
