AWS S3
Buckets, IAM policies, CORS, and CloudFront CDN.
AWS S3 stores user uploads, exports, and static assets. Buckets are private — access is via presigned URLs or CloudFront.
Buckets
| Bucket | Environment suffix | Purpose |
|---|---|---|
app-uploads-{env} | -alpha, -beta, -prod | User-uploaded files (private) |
app-assets-{env} | -alpha, -beta, -prod | Public static assets via CDN |
IAM task role policy
Attach to the ECS task role (see AWS ECS):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:GetObject", "s3:DeleteObject"],
"Resource": "arn:aws:s3:::app-uploads-prod/*"
},
{
"Effect": "Allow",
"Action": ["s3:ListBucket"],
"Resource": "arn:aws:s3:::app-uploads-prod"
}
]
}CORS (for browser presigned uploads)
[
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["PUT", "GET"],
"AllowedOrigins": ["https://app.example.com", "http://localhost:3000"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 3600
}
]CloudFront
- Origin: S3 bucket (OAC — Origin Access Control)
- Cache behavior: respect
Cache-Controlheaders on assets - Custom domain:
cdn.example.com
Lifecycle rules
| Prefix | Rule |
|---|---|
uploads/ | Transition to IA after 90 days |
exports/ | Delete after 7 days |
Express implementation
See AWS S3 — Backend guide for presigned URL code and upload flow.