Overview
Amazon S3 (Simple Storage Service) is object storage: you put objects (files up to 5 TB) into buckets under keys, and retrieve them over HTTPS. It is designed for 99.999999999% durability by storing data redundantly across multiple availability zones, scales to virtually unlimited size, and has been strongly consistent for reads after writes since 2020.
S3 is the backbone of countless systems: media storage, static website hosting behind CloudFront, backups, data lakes, logs, and ML datasets. Key features include storage classes, lifecycle rules, versioning, replication, event notifications, pre-signed URLs, encryption, and fine-grained access control with Block Public Access by default.
You hand over a box with a label (key), and the warehouse keeps copies in several buildings. Anyone you authorize can fetch the box by its label, and you can set rules to move old boxes to cheaper back rooms.
When to use it
- User uploads, images, and video.
- Static assets and website hosting with a CDN.
- Backups, archives, and logs.
- Data lakes queried by Athena, Spark, or warehouses.
Where it shows up in interviews
Recognize it when: clients upload large files.
- Design Dropbox
- Design Instagram uploads
Recognize it when: process files when they arrive.
- Design thumbnail generation
- Design a data ingestion pipeline
Where it is used in real software
Store media, logs, and data lakes in S3 at petabyte to exabyte scale.
S3 plus CloudFront hosts single-page apps and documentation sites.
Single-digit millisecond storage class for high-performance workloads like ML training.
Key terms
- Bucket / key / object
- Container / name / data plus metadata.
- Pre-signed URL
- Time-limited URL granting access to one object operation.
- Versioning
- Keep every version of an object; protects against deletes.
- Storage classes
- Standard, Intelligent-Tiering, IA, Glacier tiers.
- Multipart upload
- Upload large objects in parallel parts.
How it works, step by step
- 1Client asks the API for an upload URL
API authorizes and returns a pre-signed PUT URL.
- 2Client uploads directly to S3
No file bytes pass through your servers.
- 3S3 emits an event
To SQS, SNS, EventBridge, or Lambda.
- 4Workers process the object
Thumbnails, virus scan, metadata extraction.
- 5Serve via CloudFront
With origin access control; the bucket stays private.
STEP 1The browser requests an upload URL for photo.jpg; the API checks permissions.
S3 storage classes
Pick by access frequency
| Class | Access pattern | Retrieval | Relative cost |
|---|---|---|---|
| Standard | Frequent | Milliseconds | Highest storage |
| Intelligent-Tiering | Unknown or changing | Milliseconds | Auto-optimized |
| Standard-IA | Monthly | Milliseconds, retrieval fee | Lower |
| Glacier Instant / Flexible | Quarterly / yearly | ms / minutes-hours | Much lower |
| Glacier Deep Archive | Rarely (compliance) | Up to 12-48 hours | Lowest |
NOWClass: Standard | Access pattern: Frequent | Retrieval: Milliseconds | Relative cost: Highest storage
Lifecycle rules move objects between classes automatically as they age.
Implementation
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";import { getSignedUrl } from "@aws-sdk/s3-request-presigner";import { randomUUID } from "node:crypto"; const s3 = new S3Client({}); export async function createUploadUrl(userId: string, contentType: string) { if (!["image/jpeg", "image/png", "image/webp"].includes(contentType)) throw new Error("Unsupported type"); const key = `uploads/${userId}/${randomUUID()}`; // never trust client file names as keys const url = await getSignedUrl( s3, new PutObjectCommand({ Bucket: process.env.UPLOAD_BUCKET, Key: key, ContentType: contentType }), { expiresIn: 300 }, // 5 minutes ); return { url, key };}Complexity and performance
Across 3+ AZs.
Single PUT up to 5 GB.
Parallelize with prefixes.
Trade-offs
S3 is ideal for large objects but slower than local disks or caches for small, frequent reads; put a CDN or cache in front.
Millions of tiny objects cost more in requests; batch small records into larger files.
Variants and related techniques
MinIO, Cloudflare R2, Google Cloud Storage, Azure Blob.
Write-once-read-many for compliance and ransomware protection.
Common mistakes
- Public buckets.
Fix: Keep Block Public Access on; serve via CloudFront with origin access control.
- Proxying uploads through app servers.
Fix: Use pre-signed URLs for direct upload.
- No versioning on critical data.
Fix: Enable versioning and MFA delete or Object Lock.
Interview questions
How do you handle large file uploads?
Issue pre-signed URLs (multipart for large files) so clients upload directly to S3 in parallel parts, trigger processing from S3 events, and store metadata in a database.
How do you serve private files to authorized users?
Keep the bucket private and generate short-lived pre-signed GET URLs or CloudFront signed URLs/cookies after checking permissions.
Practice problems
| Problem | Difficulty | What it trains |
|---|---|---|
| Implement pre-signed uploads | Easy | Security. |
| Design Dropbox's storage layer | Hard | Chunking, dedupe, sync. |